omnibias.graph.jax.ops.spectral
Spectral graph operators and differentiable relaxations for ordering, assignment, and graph-structured learning.
import omnibias.graph.jax.ops.spectralModule contract & mathematical conventions
Differentiable spectral graph operators (jax).
Bit-identical twin of omnibias.graph.torch.ops.spectral; see that module
for the mathematical definitions. All operators take a symmetric non-negative
adjacency A of shape (n, n) and are differentiable in A.
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.
External type aliases
These public names refer to external types. Their implementations and inherited members belong to the originating library.
| Public name | External definition |
|---|---|
omnibias.graph.jax.ops.spectral.Array | typing.Any |
CutRelaxation
omnibias.graph.jax.ops.CutRelaxationSource ↗class CutRelaxationDataclass 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.
Rayleigh-Ritz relaxation of the k-way ratio / normalized cut.
Parameters
| Name | Type & default | Contract |
|---|---|---|
embeddingdataclass field | ArrayRequired | See the operation contract and implementation below. |
relaxed_cut_valuedataclass field | ArrayRequired | See the operation contract and implementation below. |
eigenvaluesdataclass field | ArrayRequired | See the operation contract and implementation below. |
Fields & methods
embeddingfield
embedding: ArrayDeclared Array field on CutRelaxation. A value must be provided when constructing the configuration, unless an inherited constructor supplies it.
View source ↗relaxed_cut_valuefield
relaxed_cut_value: ArrayDeclared Array field on CutRelaxation. A value must be provided when constructing the configuration, unless an inherited constructor supplies it.
View source ↗eigenvaluesfield
eigenvalues: ArrayDeclared Array field on CutRelaxation. A value must be provided when constructing the configuration, unless an inherited constructor supplies it.
View source ↗Read the implementation
class CutRelaxation:
"""Rayleigh-Ritz relaxation of the ``k``-way ratio / normalized cut."""
embedding: Array
relaxed_cut_value: Array
eigenvalues: ArrayOther public import paths
omnibias.graph.jax.ops.CutRelaxationomnibias.graph.jax.ops.spectral.CutRelaxation
degree
omnibias.graph.jax.ops.degreeSource ↗degree(adjacency: Array) -> ArrayWeighted node degrees d_i = sum_j A_{ij} -> shape (n,).
Parameters
| Name | Type & default | Contract |
|---|---|---|
adjacencypositional-or-keyword | ArrayRequired | See the operation contract and implementation below. |
ArrayRead the implementation
def degree(adjacency: Array) -> Array:
r"""Weighted node degrees ``d_i = sum_j A_{ij}`` -> shape ``(n,)``."""
_check_adjacency(adjacency)
return adjacency.sum(axis=-1)Other public import paths
omnibias.graph.jax.ops.degreeomnibias.graph.jax.ops.spectral.degree
fiedler_vector
omnibias.graph.jax.ops.fiedler_vectorSource ↗fiedler_vector(adjacency: Array, *, normalized: bool=False) -> ArrayThe eigenvector of the second-smallest Laplacian eigenvalue -> (n,).
Parameters
| Name | Type & default | Contract |
|---|---|---|
adjacencypositional-or-keyword | ArrayRequired | See the operation contract and implementation below. |
normalizedkeyword-only | boolDefault: False | See the operation contract and implementation below. |
ArrayExecuted regression · fiedler separates blocks
Recorded coverage confirms this test executed the API body. 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_fiedler_separates_blocks() -> None:
v = np.asarray(G.fiedler_vector(two_block_sbm(5, 1.0, 0.02)))
b0, b1 = v[:5], v[5:]
assert np.all(np.sign(b0) == np.sign(b0[0]))
assert np.all(np.sign(b1) == np.sign(b1[0]))
assert np.sign(b0[0]) != np.sign(b1[0])python -m pytest "packages/omnibias-graph/tests/test_spectral_jax.py::test_fiedler_separates_blocks" -qRead the implementation
def fiedler_vector(adjacency: Array, *, normalized: bool = False) -> Array:
r"""The eigenvector of the second-smallest Laplacian eigenvalue -> ``(n,)``."""
_, evecs = laplacian_spectrum(adjacency, normalized=normalized)
return evecs[:, 1]Other public import paths
omnibias.graph.jax.ops.fiedler_vectoromnibias.graph.jax.ops.spectral.fiedler_vector
graph_heat_kernel
omnibias.graph.jax.ops.graph_heat_kernelSource ↗graph_heat_kernel(adjacency: Array, t: float, *, normalized: bool=False) -> ArrayHeat kernel H = exp(-t L) via the symmetric eigendecomposition.
Parameters
| Name | Type & default | Contract |
|---|---|---|
adjacencypositional-or-keyword | ArrayRequired | See the operation contract and implementation below. |
tpositional-or-keyword | floatRequired | See the operation contract and implementation below. |
normalizedkeyword-only | boolDefault: False | See the operation contract and implementation below. |
ArrayExplicit validation & failure cases
- When
t < 0, raisesValueError(f'diffusion time t must be >= 0; got {t}').
These are explicit source guards. Backend operations may also raise for invalid shapes, dtypes, or unsupported devices.
Executed regression · heat kernel parity
Recorded coverage confirms this test executed the API body. 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_heat_kernel_parity(t: float) -> None:
m = _sym_adjacency(5)
_assert_close(GT.graph_heat_kernel(torch.tensor(m), t), GJ.graph_heat_kernel(jnp.asarray(m), t))python -m pytest "packages/omnibias-graph/tests/test_cross_backend.py::test_heat_kernel_parity[0.1]" -qRegression example · heat kernel semigroup and constant
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_heat_kernel_semigroup_and_constant() -> None:
a = two_block_sbm(3, 1.0, 0.3)
h_half = np.asarray(G.graph_heat_kernel(a, 0.25))
h_full = np.asarray(G.graph_heat_kernel(a, 0.5))
assert np.allclose(h_half @ h_half, h_full, atol=1e-10)
ones = np.ones(6)
assert np.allclose(np.asarray(G.graph_heat_kernel(a, 1.0)) @ ones, ones, atol=1e-10)python -m pytest packages/omnibias-graph/tests/test_spectral_jax.py -k test_heat_kernel_semigroup_and_constant -qRead the implementation
def graph_heat_kernel(adjacency: Array, t: float, *, normalized: bool = False) -> Array:
r"""Heat kernel ``H = exp(-t L)`` via the symmetric eigendecomposition."""
if t < 0:
raise ValueError(f"diffusion time t must be >= 0; got {t}")
evals, evecs = laplacian_spectrum(adjacency, normalized=normalized)
damp = jnp.exp(-t * evals)
return (evecs * damp[None, :]) @ evecs.TOther public import paths
omnibias.graph.jax.ops.graph_heat_kernelomnibias.graph.jax.ops.spectral.graph_heat_kernel
graph_laplacian
omnibias.graph.jax.ops.graph_laplacianSource ↗graph_laplacian(adjacency: Array) -> ArrayCombinatorial Laplacian L = D - A.
Parameters
| Name | Type & default | Contract |
|---|---|---|
adjacencypositional-or-keyword | ArrayRequired | See the operation contract and implementation below. |
ArrayExecuted regression · non square raises
Recorded coverage confirms this test executed the API body. 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_non_square_raises() -> None:
with pytest.raises(ValueError, match="square"):
G.graph_laplacian(jnp.zeros((3, 4)))python -m pytest "packages/omnibias-graph/tests/test_spectral_jax.py::test_non_square_raises" -qRead the implementation
def graph_laplacian(adjacency: Array) -> Array:
r"""Combinatorial Laplacian ``L = D - A``."""
_check_adjacency(adjacency)
d = adjacency.sum(axis=-1)
return jnp.diag(d) - adjacencyOther public import paths
omnibias.graph.jax.ops.graph_laplacianomnibias.graph.jax.ops.spectral.graph_laplacian
laplacian_spectrum
omnibias.graph.jax.ops.laplacian_spectrumSource ↗laplacian_spectrum(adjacency: Array, *, normalized: bool=False) -> tuple[Array, Array]Ascending eigenvalues / eigenvectors of the (symmetric) Laplacian.
Parameters
| Name | Type & default | Contract |
|---|---|---|
adjacencypositional-or-keyword | ArrayRequired | See the operation contract and implementation below. |
normalizedkeyword-only | boolDefault: False | See the operation contract and implementation below. |
tuple[Array, Array]Executed regression · heat kernel parity
Recorded coverage confirms this test executed the API body. 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_heat_kernel_parity(t: float) -> None:
m = _sym_adjacency(5)
_assert_close(GT.graph_heat_kernel(torch.tensor(m), t), GJ.graph_heat_kernel(jnp.asarray(m), t))python -m pytest "packages/omnibias-graph/tests/test_cross_backend.py::test_heat_kernel_parity[0.1]" -qRegression example · ring eigenvalues
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_ring_eigenvalues(n: int) -> None:
evals, _ = G.laplacian_spectrum(ring_adjacency(n))
exact = np.sort([2 - 2 * math.cos(2 * math.pi * k / n) for k in range(n)])
assert np.allclose(np.asarray(evals), exact, atol=1e-10)python -m pytest packages/omnibias-graph/tests/test_spectral_jax.py -k test_ring_eigenvalues -qRead the implementation
def laplacian_spectrum(
adjacency: Array, *, normalized: bool = False
) -> tuple[Array, Array]:
r"""Ascending eigenvalues / eigenvectors of the (symmetric) Laplacian."""
lap = _symmetric_laplacian(adjacency, normalized=normalized)
lap = 0.5 * (lap + lap.T)
evals, evecs = jnp.linalg.eigh(lap)
return evals, evecsOther public import paths
omnibias.graph.jax.ops.laplacian_spectrumomnibias.graph.jax.ops.spectral.laplacian_spectrum
normalized_laplacian
omnibias.graph.jax.ops.normalized_laplacianSource ↗normalized_laplacian(adjacency: Array) -> ArraySymmetric normalized Laplacian L_sym = I - D^{-1/2} A D^{-1/2}.
Parameters
| Name | Type & default | Contract |
|---|---|---|
adjacencypositional-or-keyword | ArrayRequired | See the operation contract and implementation below. |
ArrayExecuted regression · laplacian parity
Recorded coverage confirms this test executed the API body. 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_laplacian_parity(seed: int, name: str) -> None:
m = _sym_adjacency(seed)
_assert_close(getattr(GT, name)(torch.tensor(m)), getattr(GJ, name)(jnp.asarray(m)))python -m pytest "packages/omnibias-graph/tests/test_cross_backend.py::test_laplacian_parity[normalized_laplacian-0]" -qRegression example · normalized spectrum in 0 2
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_normalized_spectrum_in_0_2() -> None:
ln = G.normalized_laplacian(ring_adjacency(10))
ev = np.linalg.eigvalsh(np.asarray(ln))
assert ev.min() > -1e-10 and ev.max() < 2.0 + 1e-10python -m pytest packages/omnibias-graph/tests/test_spectral_jax.py -k test_normalized_spectrum_in_0_2 -qRead the implementation
def normalized_laplacian(adjacency: Array) -> Array:
r"""Symmetric normalized Laplacian ``L_sym = I - D^{-1/2} A D^{-1/2}``."""
_check_adjacency(adjacency)
d = adjacency.sum(axis=-1)
d_inv_sqrt = jnp.where(d > 0, 1.0 / jnp.sqrt(d), jnp.zeros_like(d))
a_norm = d_inv_sqrt[:, None] * adjacency * d_inv_sqrt[None, :]
n = adjacency.shape[0]
return jnp.eye(n, dtype=adjacency.dtype) - a_normOther public import paths
omnibias.graph.jax.ops.normalized_laplacianomnibias.graph.jax.ops.spectral.normalized_laplacian
random_walk_laplacian
omnibias.graph.jax.ops.random_walk_laplacianSource ↗random_walk_laplacian(adjacency: Array) -> ArrayRandom-walk Laplacian L_rw = I - D^{-1} A.
Parameters
| Name | Type & default | Contract |
|---|---|---|
adjacencypositional-or-keyword | ArrayRequired | See the operation contract and implementation below. |
ArrayExecuted regression · laplacian parity
Recorded coverage confirms this test executed the API body. 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_laplacian_parity(seed: int, name: str) -> None:
m = _sym_adjacency(seed)
_assert_close(getattr(GT, name)(torch.tensor(m)), getattr(GJ, name)(jnp.asarray(m)))python -m pytest "packages/omnibias-graph/tests/test_cross_backend.py::test_laplacian_parity[random_walk_laplacian-0]" -qRead the implementation
def random_walk_laplacian(adjacency: Array) -> Array:
r"""Random-walk Laplacian ``L_rw = I - D^{-1} A``."""
_check_adjacency(adjacency)
d = adjacency.sum(axis=-1)
d_inv = jnp.where(d > 0, 1.0 / d, jnp.zeros_like(d))
n = adjacency.shape[0]
return jnp.eye(n, dtype=adjacency.dtype) - d_inv[:, None] * adjacencyOther public import paths
omnibias.graph.jax.ops.random_walk_laplacianomnibias.graph.jax.ops.spectral.random_walk_laplacian
spectral_clustering_relaxation
omnibias.graph.jax.ops.spectral_clustering_relaxationSource ↗spectral_clustering_relaxation(adjacency: Array, k: int, *, normalized: bool=True) -> CutRelaxationContinuous eigenvector relaxation of the k-way graph cut.
Parameters
| Name | Type & default | Contract |
|---|---|---|
adjacencypositional-or-keyword | ArrayRequired | See the operation contract and implementation below. |
kpositional-or-keyword | intRequired | See the operation contract and implementation below. |
normalizedkeyword-only | boolDefault: True | See the operation contract and implementation below. |
CutRelaxationExplicit validation & failure cases
- When
k < 1, raisesValueError(f'k must be >= 1; got {k}'). - When
k > adjacency.shape[0], raisesValueError(f'k={k} exceeds the number of nodes {adjacency.shape[0]}').
These are explicit source guards. Backend operations may also raise for invalid shapes, dtypes, or unsupported devices.
Executed regression · differentiable through jax grad
Recorded coverage confirms this test executed the API body. 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_differentiable_through_jax_grad() -> None:
a = two_block_sbm(3, 1.0, 0.2)
def cut(x):
return G.spectral_clustering_relaxation(x, k=2, normalized=False).relaxed_cut_value
grad = jax.grad(cut)(a)
assert np.all(np.isfinite(np.asarray(grad)))python -m pytest "packages/omnibias-graph/tests/test_spectral_jax.py::test_differentiable_through_jax_grad" -qRegression example · cut relaxation value
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_cut_relaxation_value() -> None:
a = two_block_sbm(4, 1.0, 0.1)
rel = G.spectral_clustering_relaxation(a, k=2, normalized=True)
evals, _ = G.laplacian_spectrum(a, normalized=True)
assert abs(float(rel.relaxed_cut_value) - float(evals[:2].sum())) < 1e-10python -m pytest packages/omnibias-graph/tests/test_spectral_jax.py -k test_cut_relaxation_value -qRead the implementation
def spectral_clustering_relaxation(
adjacency: Array, k: int, *, normalized: bool = True
) -> CutRelaxation:
r"""Continuous eigenvector relaxation of the ``k``-way graph cut."""
if k < 1:
raise ValueError(f"k must be >= 1; got {k}")
if k > adjacency.shape[0]:
raise ValueError(f"k={k} exceeds the number of nodes {adjacency.shape[0]}")
evals, evecs = laplacian_spectrum(adjacency, normalized=normalized)
return CutRelaxation(
embedding=evecs[:, :k],
relaxed_cut_value=evals[:k].sum(),
eigenvalues=evals[:k],
)Other public import paths
omnibias.graph.jax.ops.spectral_clustering_relaxationomnibias.graph.jax.ops.spectral.spectral_clustering_relaxation
spectral_embedding
omnibias.graph.jax.ops.spectral_embeddingSource ↗spectral_embedding(adjacency: Array, n_components: int, *, normalized: bool=True, drop_first: bool=True) -> ArrayLaplacian-eigenmaps embedding: the smallest non-trivial eigenvectors.
Parameters
| Name | Type & default | Contract |
|---|---|---|
adjacencypositional-or-keyword | ArrayRequired | See the operation contract and implementation below. |
n_componentspositional-or-keyword | intRequired | See the operation contract and implementation below. |
normalizedkeyword-only | boolDefault: True | See the operation contract and implementation below. |
drop_firstkeyword-only | boolDefault: True | See the operation contract and implementation below. |
ArrayExplicit validation & failure cases
- When
n_components < 1, raisesValueError(f'n_components must be >= 1; got {n_components}'). - When
start + n_components > n, raisesValueError(f'cannot take {n_components} components (drop_first={drop_first}) from an {n}-node graph').
These are explicit source guards. Backend operations may also raise for invalid shapes, dtypes, or unsupported devices.
Executed regression · embedding subspace projector parity
Recorded coverage confirms this test executed the API body. 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_embedding_subspace_projector_parity() -> None:
# A graph with a clear spectral gap so the smallest-k subspace is unique.
n_per, k = 5, 2
m = np.full((2 * n_per, 2 * n_per), 0.02)
m[:n_per, :n_per] = 1.0
m[n_per:, n_per:] = 1.0
np.fill_diagonal(m, 0.0)
yt = GT.spectral_embedding(torch.tensor(m), k, normalized=True, drop_first=False).detach().numpy()
yj = np.asarray(GJ.spectral_embedding(jnp.asarray(m), k, normalized=True, drop_first=False))
# Y Y^T (the projector onto the smallest-k eigenspace) is rotation-invariant.
assert np.allclose(yt @ yt.T, yj @ yj.T, rtol=RTOL, atol=1e-9)python -m pytest "packages/omnibias-graph/tests/test_cross_backend.py::test_embedding_subspace_projector_parity" -qRead the implementation
def spectral_embedding(
adjacency: Array,
n_components: int,
*,
normalized: bool = True,
drop_first: bool = True,
) -> Array:
r"""Laplacian-eigenmaps embedding: the smallest non-trivial eigenvectors."""
if n_components < 1:
raise ValueError(f"n_components must be >= 1; got {n_components}")
n = adjacency.shape[0]
start = 1 if drop_first else 0
if start + n_components > n:
raise ValueError(
f"cannot take {n_components} components (drop_first={drop_first}) "
f"from an {n}-node graph"
)
_, evecs = laplacian_spectrum(adjacency, normalized=normalized)
return evecs[:, start : start + n_components]Other public import paths
omnibias.graph.jax.ops.spectral_embeddingomnibias.graph.jax.ops.spectral.spectral_embedding