Skip to content

Commit 5df69bb

Browse files
authored
Snapshot test for precision estimation (#160)
* Consistent args in prec-est. Wrote snapshot test * Use natural instead of metis ordering - for reproducibility
1 parent 03fbdde commit 5df69bb

3 files changed

Lines changed: 65 additions & 4 deletions

File tree

graphite_maps/precision_estimation.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ def fit_precision_cholesky(
482482

483483
def fit_precision_cholesky_approximate(
484484
U: NDArray[np.floating],
485-
G: nx.Graph,
485+
Graph_u: nx.Graph,
486486
neighbourhood_expansion: int = 2,
487487
use_tqdm: bool = True,
488488
) -> csc_array:
@@ -512,7 +512,7 @@ def fit_precision_cholesky_approximate(
512512
The optimized sparse Cholesky factor of the precision matrix.
513513
"""
514514
# The k'th power is a "neighborhood expansion", see docs of nx.power
515-
G = nx.power(G, k=neighbourhood_expansion)
515+
G = nx.power(Graph_u, k=neighbourhood_expansion)
516516
G.add_edges_from((n, n) for n in G.nodes()) # Add edges (1, 1), (2, 2), ...
517517

518518
C = optimize_sparse_affine_kr_map(

tests/test_enif.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ def run(U_in):
116116
# Estimate precision matrix
117117
Prec_u = fit_precision_cholesky_approximate(
118118
U=U_in,
119-
G=Graph_u,
119+
Graph_u=Graph_u,
120120
use_tqdm=False,
121121
)
122122
enif = EnIF(Prec_u=Prec_u, Prec_eps=Prec_eps, H=H)
@@ -167,7 +167,7 @@ def test_snapshot_lowlevel():
167167
# Estimate precision matrix
168168
Prec_u = fit_precision_cholesky_approximate(
169169
U=U,
170-
G=Graph_u,
170+
Graph_u=Graph_u,
171171
neighbourhood_expansion=2,
172172
use_tqdm=True,
173173
)

tests/test_precision_estimation.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,71 @@
1+
import networkx as nx
12
import numpy as np
23
import pytest
34
import scipy as sp
45
from graphite_maps import precision_estimation as precest
56
from scipy.optimize import minimize
67

78

9+
def get_precision_data():
10+
rng = np.random.default_rng(8)
11+
n = 10 # Size
12+
density = 0.4
13+
14+
# Create G indicating sparsity pattern
15+
G = rng.uniform(size=(n, n)) < (density / 2)
16+
G = G.T + G
17+
np.fill_diagonal(G, G.diagonal() + 1)
18+
G_matrix = (G > 0).astype(int)
19+
Graph_u = nx.from_scipy_sparse_array(sp.sparse.csc_array(G_matrix))
20+
21+
# Create data U
22+
U = rng.normal(size=(999, n))
23+
24+
return U, Graph_u, G_matrix
25+
26+
27+
def test_snapshot_fit_precision_cholesky():
28+
29+
U, Graph_u, G_matrix = get_precision_data()
30+
31+
# Estimate precision with fit_precision_cholesky.
32+
# Cannot use METIS (not reproducible across OSes), use 'natural'
33+
Prec_est, *_ = precest.fit_precision_cholesky(
34+
U=U, Graph_u=Graph_u, ordering_method="natural"
35+
)
36+
Prec_est = Prec_est.todense()
37+
38+
entries_at_one = Prec_est[G_matrix > 0]
39+
entries_at_zero = Prec_est[G_matrix == 0]
40+
41+
desired = np.array([1.03393041, -0.05494438, 1.02092228, 1.00923821])
42+
np.testing.assert_allclose(entries_at_one[::9], desired, atol=1e-8)
43+
44+
desired = np.array([0.0, 0.0, 0.0, 0.01763788, -0.03135188, 0.0, 0.0, 0.0])
45+
np.testing.assert_allclose(entries_at_zero[::9], desired, atol=1e-8)
46+
47+
48+
def test_snapshot_fit_precision_cholesky_approximate():
49+
50+
U, Graph_u, G_matrix = get_precision_data()
51+
# Estimate precision with fit_precision_cholesky
52+
Prec_est = precest.fit_precision_cholesky_approximate(
53+
U=U, Graph_u=Graph_u, neighbourhood_expansion=2
54+
)
55+
Prec_est = Prec_est.todense()
56+
57+
entries_at_one = Prec_est[G_matrix > 0]
58+
entries_at_zero = Prec_est[G_matrix == 0]
59+
60+
desired = np.array([1.03392773, -0.05606645, 1.022626, 1.00883855])
61+
np.testing.assert_allclose(entries_at_one[::9], desired, atol=1e-8)
62+
63+
desired = np.array(
64+
[0.0, -0.04588378, -0.00330536, -0.00124644, -0.0301345, -0.02301515, 0.0, 0.0]
65+
)
66+
np.testing.assert_allclose(entries_at_zero[::9], desired, atol=1e-8)
67+
68+
869
def test_objective_twice():
970
# A regression test: ensure that two calls return the same result.
1071
rng = np.random.default_rng(42)

0 commit comments

Comments
 (0)