Coverage for src/cvx/linalg/core/types.py: 100%

12 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-08-15 07:08 +0000

1"""Type aliases and structural protocols for linear algebra utilities. 

2 

3Defines the NumPy ndarray aliases used across the linalg subpackage and the 

4:class:`SupportsMatvec` protocol -- the minimal matrix-free contract (a dimension 

5``n`` and a ``matvec``) that lets lower layers accept an operator structurally, 

6without importing the :mod:`~cvx.linalg.operators` backends. 

7""" 

8 

9from typing import Protocol, TypeAlias, runtime_checkable 

10 

11import numpy as np 

12import numpy.typing as npt 

13 

14Matrix: TypeAlias = npt.NDArray[np.float64] 

15"""A 2-D float64 NumPy array.""" 

16 

17Vector: TypeAlias = npt.NDArray[np.float64] 

18"""A 1-D float64 NumPy array.""" 

19 

20 

21@runtime_checkable 

22class SupportsMatvec(Protocol): 

23 """Structural protocol for an operator applied matrix-free. 

24 

25 Anything exposing a dimension ``n`` and a ``matvec(x) -> A @ x`` satisfies it, 

26 so a routine can accept an operator by shape rather than by importing a concrete 

27 class. Every :class:`~cvx.linalg.SymmetricOperator` conforms; plain arrays and 

28 bare callables deliberately do not. It lives in :mod:`~cvx.linalg.core.types` 

29 (the lowest layer) so consumers such as 

30 :func:`~cvx.linalg.power_iteration` can ``isinstance``-check against it without 

31 pulling in the operator backends. 

32 """ 

33 

34 @property 

35 def n(self) -> int: 

36 """Dimension of the operator (it acts on vectors of length ``n``).""" 

37 ... 

38 

39 def matvec(self, x: Vector | Matrix) -> Vector | Matrix: 

40 """Return ``A @ x``.""" 

41 ...