File size: 1,952 Bytes
47c7eb2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# SPDX-License-Identifier: Apache-2.0
# © 2026 SZL Holdings · Stephen P. Lutar · ORCID 0009-0001-0110-4173
"""Hub-compliant kernel layer for the szl-lambda-gate kernel.



Per the Kernel Hub `kernel-requirements`, layers exposed for extension must be

PURE torch.nn.Module subclasses:

  - no custom __init__,

  - no class variables,

  - only a `forward` method.



The layer therefore reads its parameters (weights / threshold) off the module

instance it is bound to (set by the host model) and only defines `forward`.



HONESTY: `LambdaGate` emits an ADVISORY governance signal (the weighted

geometric mean Λ plus a pass/fail vs threshold). Λ is NOT proven trust; its

uniqueness is Conjecture 1 (open).

"""
import torch
from torch import nn

from ._lambda import lambda_aggregate, lambda_gate


class LambdaGate(nn.Module):
    """Pure Λ-gate layer.



    Reads optional ``self.weights`` (1-D, length k) and ``self.threshold``

    (float, default 0.5) off the bound module instance.



    forward(axes) -> LambdaGateResult(score, passed, threshold, advisory) where

    ``score`` = Λ(axes) over the last dim and ``passed`` = score >= threshold.

    Differentiable in ``score`` w.r.t. ``axes``.

    """

    def forward(self, axes: torch.Tensor):
        weights = getattr(self, "weights", None)
        threshold = getattr(self, "threshold", 0.5)
        return lambda_gate(axes, weights=weights, threshold=float(threshold))


class LambdaAggregate(nn.Module):
    """Pure Λ-aggregator layer: forward(axes) -> Λ(axes) tensor in [0,1].



    Reads optional ``self.weights`` (1-D, length k) off the bound module

    instance; uniform weights when absent. Returns just the score (no gate),

    fully differentiable w.r.t. ``axes``.

    """

    def forward(self, axes: torch.Tensor) -> torch.Tensor:
        weights = getattr(self, "weights", None)
        return lambda_aggregate(axes, weights=weights)