omnibias.torch.scan_equivariant
PyTorch activation derivatives, trainable operator layers, network jets, and direct differential-operator contractions.
import omnibias.torch.scan_equivariantModule contract & mathematical conventions
Discrete-orbit equivariant scan (torch; theory 02-08).
Exact steering is gaussian-family only. C_L is a discrete orbit, not SO(2).
steerable_basis returns None for non-gaussian bases (no fallback).
Shared formulas do not imply universal floating-point identity. Verify dtype, shape, derivative-order support, and the stated numerical assumptions for the path you use.
EquivariantScan
omnibias.torch.EquivariantScanSource ↗class EquivariantScan(nn.Module)Scan a C_L orientation orbit. Not SO(2) / SO(3).
Parameters
| Name | Type & default | Contract |
|---|---|---|
dimpositional-or-keyword | intRequired | See the operation contract and implementation below. |
bankpositional-or-keyword | OrientationBankRequired | See the operation contract and implementation below. |
offsetspositional-or-keyword | BankSpecRequired | See the operation contract and implementation below. |
templatekeyword-only | OpName | strDefault: 'grad' | See the operation contract and implementation below. |
basekeyword-only | strDefault: 'gaussian' | See the operation contract and implementation below. |
readoutkeyword-only | Literal['orbit', 'max', 'fourier']Default: 'orbit' | See the operation contract and implementation below. |
dtypekeyword-only | torch.dtype | NoneDefault: None | See the operation contract and implementation below. |
Regression example · equivariant scan parity
This example belongs to the pinned upstream test suite. It may use fixtures and imports from its full file. Run it from that checkout with its test dependencies installed.
def test_equivariant_scan_parity() -> None:
pytest.importorskip("jax")
import jax
import jax.numpy as jnp
from omnibias.jax.scan_equivariant import equivariant_scan_apply
from omnibias.jax.scan_equivariant import steerable_basis as steerable_jax
jax.config.update("jax_enable_x64", True)
torch.set_default_dtype(torch.float64)
assert steerable_basis(1, 2, base="tanh") is None
assert steerable_jax(1, 2, base="tanh") is None
angles = (0.0, math.pi / 2)
offsets = BankSpec.uniform(-0.4, 0.4, 5)
net = EquivariantScan(
2,
OrientationBank(angles),
offsets,
base="gaussian",
dtype=torch.float64,
)
x = torch.tensor([[0.2, -0.15], [0.05, 0.3]], dtype=torch.float64)
y_t = net(x)
y_j = equivariant_scan_apply(
jnp.asarray(x.numpy()), angles, offsets, base="gaussian"
)
assert np.asarray(y_t.detach().cpu()) == pytest.approx(
np.asarray(y_j), rel=1e-12, abs=1e-12
)python -m pytest tests/test_equivariant_parity.py -k test_equivariant_scan_parity -qFields & methods
__init__method
__init__(self, dim: int, bank: OrientationBank, offsets: BankSpec, *, template: OpName | str='grad', base: str='gaussian', readout: Literal['orbit', 'max', 'fourier']='orbit', dtype: torch.dtype | None=None) -> NoneSee the class contract above and the exact method implementation below.
Parameters
| Name | Type & default | Contract |
|---|---|---|
dimpositional-or-keyword | intRequired | See the operation contract and implementation below. |
bankpositional-or-keyword | OrientationBankRequired | See the operation contract and implementation below. |
offsetspositional-or-keyword | BankSpecRequired | See the operation contract and implementation below. |
templatekeyword-only | OpName | strDefault: 'grad' | See the operation contract and implementation below. |
basekeyword-only | strDefault: 'gaussian' | See the operation contract and implementation below. |
readoutkeyword-only | Literal['orbit', 'max', 'fourier']Default: 'orbit' | See the operation contract and implementation below. |
dtypekeyword-only | torch.dtype | NoneDefault: None | See the operation contract and implementation below. |
Returns: None
Validation & failure cases
- When
dim < 2, raisesValueError('equivariant scan needs dim >= 2').
Method implementation
def __init__(
self,
dim: int,
bank: OrientationBank,
offsets: BankSpec,
*,
template: OpName | str = "grad",
base: str = "gaussian",
readout: Literal["orbit", "max", "fourier"] = "orbit",
dtype: torch.dtype | None = None,
) -> None:
super().__init__()
if dim < 2:
raise ValueError("equivariant scan needs dim >= 2")
self.dim = int(dim)
self.orientation = bank
self.base = str(base)
self.readout = readout
dt = torch.get_default_dtype() if dtype is None else dtype
self.scan = BiasScan(1, offsets, template=template, base=base, dtype=dt)forwardmethod
forward(self, x: Tensor) -> TensorSee the class contract above and the exact method implementation below.
Parameters
| Name | Type & default | Contract |
|---|---|---|
xpositional-or-keyword | TensorRequired | See the operation contract and implementation below. |
Returns: Tensor
Method implementation
def forward(self, x: Tensor) -> Tensor:
responses = []
for angle in self.orientation.angles:
c, s = math.cos(angle), math.sin(angle)
w = torch.zeros(x.shape[-1], dtype=x.dtype, device=x.device)
w[0] = c
w[1] = s
z = (x * w).sum(dim=-1, keepdim=True)
responses.append(self.scan(z))
stacked = torch.stack(responses, dim=-1)
if self.readout == "max":
return stacked.amax(dim=-1)
if self.readout == "fourier":
return stacked.mean(dim=-1)
return stackeddimattribute
dim = int(dim)Public instance attribute assigned by __init__. The source assignment is dim = int(dim); it describes instance state, not a literal constructor default.
orientationattribute
orientation: OrientationBank = bankPublic instance attribute assigned by __init__. The source assignment is orientation = bank; it describes instance state, not a literal constructor default.
baseattribute
base = str(base)Public instance attribute assigned by __init__. The source assignment is base = str(base); it describes instance state, not a literal constructor default.
readoutattribute
readout: Literal['orbit', 'max', 'fourier'] = readoutPublic instance attribute assigned by __init__. The source assignment is readout = readout; it describes instance state, not a literal constructor default.
scanattribute
scan = BiasScan(1, offsets, template=template, base=base, dtype=dt)Public instance attribute assigned by __init__. The source assignment is scan = BiasScan(1, offsets, template=template, base=base, dtype=dt); it describes instance state, not a literal constructor default.
Read the implementation
class EquivariantScan(nn.Module):
"""Scan a ``C_L`` orientation orbit. Not SO(2) / SO(3)."""
def __init__(
self,
dim: int,
bank: OrientationBank,
offsets: BankSpec,
*,
template: OpName | str = "grad",
base: str = "gaussian",
readout: Literal["orbit", "max", "fourier"] = "orbit",
dtype: torch.dtype | None = None,
) -> None:
super().__init__()
if dim < 2:
raise ValueError("equivariant scan needs dim >= 2")
self.dim = int(dim)
self.orientation = bank
self.base = str(base)
self.readout = readout
dt = torch.get_default_dtype() if dtype is None else dtype
self.scan = BiasScan(1, offsets, template=template, base=base, dtype=dt)
def forward(self, x: Tensor) -> Tensor:
responses = []
for angle in self.orientation.angles:
c, s = math.cos(angle), math.sin(angle)
w = torch.zeros(x.shape[-1], dtype=x.dtype, device=x.device)
w[0] = c
w[1] = s
z = (x * w).sum(dim=-1, keepdim=True)
responses.append(self.scan(z))
stacked = torch.stack(responses, dim=-1)
if self.readout == "max":
return stacked.amax(dim=-1)
if self.readout == "fourier":
return stacked.mean(dim=-1)
return stackedOther public import paths
omnibias.torch.EquivariantScanomnibias.torch.scan_equivariant.EquivariantScan
OrientationBank
omnibias.torch.scan_equivariant.OrientationBankSource ↗class OrientationBankDataclass constructor fields; inherited fields, if any, are declared by the base class. A field(...) expression describes a default factory or field options, not a literal argument default.
The module contract describes the context for this operation. Its signature, explicit validation, return expressions, and implementation are recorded below.
Parameters
| Name | Type & default | Contract |
|---|---|---|
anglesdataclass field | tuple[float, ...]Required | See the operation contract and implementation below. |
steerable_orderdataclass field | int | NoneDefault: None | See the operation contract and implementation below. |
Regression example · equivariant scan parity
This example belongs to the pinned upstream test suite. It may use fixtures and imports from its full file. Run it from that checkout with its test dependencies installed.
def test_equivariant_scan_parity() -> None:
pytest.importorskip("jax")
import jax
import jax.numpy as jnp
from omnibias.jax.scan_equivariant import equivariant_scan_apply
from omnibias.jax.scan_equivariant import steerable_basis as steerable_jax
jax.config.update("jax_enable_x64", True)
torch.set_default_dtype(torch.float64)
assert steerable_basis(1, 2, base="tanh") is None
assert steerable_jax(1, 2, base="tanh") is None
angles = (0.0, math.pi / 2)
offsets = BankSpec.uniform(-0.4, 0.4, 5)
net = EquivariantScan(
2,
OrientationBank(angles),
offsets,
base="gaussian",
dtype=torch.float64,
)
x = torch.tensor([[0.2, -0.15], [0.05, 0.3]], dtype=torch.float64)
y_t = net(x)
y_j = equivariant_scan_apply(
jnp.asarray(x.numpy()), angles, offsets, base="gaussian"
)
assert np.asarray(y_t.detach().cpu()) == pytest.approx(
np.asarray(y_j), rel=1e-12, abs=1e-12
)python -m pytest tests/test_equivariant_parity.py -k test_equivariant_scan_parity -qFields & methods
anglesfield
angles: tuple[float, ...]Declared tuple[float, ...] field on OrientationBank. A value must be provided when constructing the configuration, unless an inherited constructor supplies it.
View source ↗steerable_orderfield
steerable_order: int | None = NoneDeclared int | None field on OrientationBank. Default expression: None.
Read the implementation
class OrientationBank:
angles: tuple[float, ...]
steerable_order: int | None = NoneSteerableBasis
omnibias.torch.scan_equivariant.SteerableBasisSource ↗class SteerableBasisDataclass constructor fields; inherited fields, if any, are declared by the base class. A field(...) expression describes a default factory or field options, not a literal argument default.
The module contract describes the context for this operation. Its signature, explicit validation, return expressions, and implementation are recorded below.
Parameters
| Name | Type & default | Contract |
|---|---|---|
orderdataclass field | intRequired | See the operation contract and implementation below. |
dimdataclass field | intRequired | See the operation contract and implementation below. |
matricesdataclass field | tuple[tuple[tuple[float, ...], ...], ...]Required | See the operation contract and implementation below. |
Fields & methods
orderfield
order: intDeclared int field on SteerableBasis. A value must be provided when constructing the configuration, unless an inherited constructor supplies it.
View source ↗dimfield
dim: intDeclared int field on SteerableBasis. A value must be provided when constructing the configuration, unless an inherited constructor supplies it.
View source ↗matricesfield
matrices: tuple[tuple[tuple[float, ...], ...], ...]Declared tuple[tuple[tuple[float, ...], ...], ...] field on SteerableBasis. A value must be provided when constructing the configuration, unless an inherited constructor supplies it.
View source ↗Read the implementation
class SteerableBasis:
order: int
dim: int
matrices: tuple[tuple[tuple[float, ...], ...], ...]steerable_basis
omnibias.torch.steerable_basisSource ↗steerable_basis(order: int, dim: int, *, base: str='gaussian') -> SteerableBasis | NoneExact steering coefficients. None for non-gaussian (no approximation).
Parameters
| Name | Type & default | Contract |
|---|---|---|
orderpositional-or-keyword | intRequired | See the operation contract and implementation below. |
dimpositional-or-keyword | intRequired | See the operation contract and implementation below. |
basekeyword-only | strDefault: 'gaussian' | See the operation contract and implementation below. |
SteerableBasis | NoneRegression example · equivariant scan parity
This example belongs to the pinned upstream test suite. It may use fixtures and imports from its full file. Run it from that checkout with its test dependencies installed.
def test_equivariant_scan_parity() -> None:
pytest.importorskip("jax")
import jax
import jax.numpy as jnp
from omnibias.jax.scan_equivariant import equivariant_scan_apply
from omnibias.jax.scan_equivariant import steerable_basis as steerable_jax
jax.config.update("jax_enable_x64", True)
torch.set_default_dtype(torch.float64)
assert steerable_basis(1, 2, base="tanh") is None
assert steerable_jax(1, 2, base="tanh") is None
angles = (0.0, math.pi / 2)
offsets = BankSpec.uniform(-0.4, 0.4, 5)
net = EquivariantScan(
2,
OrientationBank(angles),
offsets,
base="gaussian",
dtype=torch.float64,
)
x = torch.tensor([[0.2, -0.15], [0.05, 0.3]], dtype=torch.float64)
y_t = net(x)
y_j = equivariant_scan_apply(
jnp.asarray(x.numpy()), angles, offsets, base="gaussian"
)
assert np.asarray(y_t.detach().cpu()) == pytest.approx(
np.asarray(y_j), rel=1e-12, abs=1e-12
)python -m pytest tests/test_equivariant_parity.py -k test_equivariant_scan_parity -qRead the implementation
def steerable_basis(order: int, dim: int, *, base: str = "gaussian") -> SteerableBasis | None:
"""Exact steering coefficients. ``None`` for non-gaussian (no approximation)."""
if str(base).lower() != "gaussian":
return None
if dim != 2:
return None
n = int(order)
# Rotation of 2-D homogeneous harmonics of degree n: (n+1) cartesian
# monomials mixed by an SO(2) representation. Stored as R(theta) later.
return SteerableBasis(order=n, dim=2, matrices=())Other public import paths
omnibias.torch.steerable_basisomnibias.torch.scan_equivariant.steerable_basis