Source code for torch_openreml.covariance.simple_matrix

"""
Simple covariance matrix from a user-supplied function.

This module provides a minimal adapter for wrapping a plain function as a
:class:`~torch_openreml.covariance.matrix.Matrix`, intended for simple cases
where all parameters are free with identity transforms — no manual parameter
specifications or transform logic required.

Classes:
    SimpleMatrix:
        A covariance matrix backed by a user-defined callable.
"""

from torch_openreml.covariance.matrix import Matrix
from torch_openreml.covariance.param import simple_param_specs


[docs] class SimpleMatrix(Matrix): r""" A covariance matrix for simple, function-based parameterisations. This is the easiest way to use :class:`~torch_openreml.MarginalREML` with a custom covariance structure: provide the number of parameters and a function that maps a flat parameter tensor to the covariance matrix. All parameters are free and use an identity transform (unconstrained). The ``default`` argument sets the value used for each free parameter when none are provided. For more advanced needs (custom transforms, fixed parameters, manual gradients), subclass :class:`~torch_openreml.covariance.matrix.Matrix` directly. """ def __init__(self, num_free_params, call, manual_grad=None, default=None): """ Initialize a simple covariance matrix. Args: num_free_params (int): Number of free parameters. call (callable): Function with signature ``call(free_params) -> torch.Tensor`` that constructs the covariance matrix from a flat 1D parameter tensor. It receives the output of :meth:`~torch_openreml.covariance.matrix.Matrix.build_params` with ``include_fixed=False`` and ``trans=False``, so a parameter dict or ``None`` is resolved to the free parameter tensor itself, untransformed, before the call. manual_grad (callable, optional): Function with signature ``manual_grad(free_params) -> (grad, grad_names)`` for a closed-form Jacobian. If ``None`` (default), automatic differentiation is used. default (torch.Tensor, optional): Default value for each parameter, given as a 1D tensor of shape ``(1,)``. Passed to :func:`simple_param_specs`. Defaults to ``torch.tensor([0.0])``. Example: .. jupyter-execute:: import torch from torch_openreml.covariance import SimpleMatrix def my_v(free_params): return torch.diag(free_params) mat = SimpleMatrix(num_free_params=3, call=my_v, default=torch.tensor([1.0])) mat(torch.tensor([1.0, 2.0, 3.0])) .. jupyter-execute:: mat() .. jupyter-execute:: mat({ "theta_0": torch.tensor([2.0]), "theta_1": torch.tensor([3.0]), "theta_2": torch.tensor([4.0]), }) .. jupyter-execute:: mat.grad(torch.tensor([1.0, 2.0, 3.0])) """ if call is None: raise ValueError("'call' must be provided.") super().__init__(None, simple_param_specs(num_free_params, default=default)) self._call = call self._manual_grad = manual_grad
[docs] def __call__(self, free_params=None): params = self.build_params(free_params, include_fixed=False, trans=False) result = self._call(params) self._shape = tuple(result.shape) return result
[docs] def manual_grad(self, free_params=None): if self._manual_grad is None: raise NotImplementedError params = self.build_params(free_params, include_fixed=False, trans=False) return self._manual_grad(params)