Skip to content

Commit 988f4ac

Browse files
committed
CI: test_jacobi_svd
1 parent 7b0deb1 commit 988f4ac

File tree

1 file changed

+99
-123
lines changed

1 file changed

+99
-123
lines changed

tests/test_jacobi_svd.py

Lines changed: 99 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,21 @@
22
import numpy as np
33
import pytest
44

5+
full_u = nanoeigenpy.DecompositionOptions.ComputeFullU.value
6+
full_v = nanoeigenpy.DecompositionOptions.ComputeFullV.value
7+
thin_u = nanoeigenpy.DecompositionOptions.ComputeThinU.value
8+
thin_v = nanoeigenpy.DecompositionOptions.ComputeThinV.value
9+
510
_options = [
611
0,
7-
nanoeigenpy.DecompositionOptions.ComputeThinU.value,
8-
nanoeigenpy.DecompositionOptions.ComputeThinV.value,
9-
nanoeigenpy.DecompositionOptions.ComputeFullU.value,
10-
nanoeigenpy.DecompositionOptions.ComputeFullV.value,
11-
nanoeigenpy.DecompositionOptions.ComputeThinU.value
12-
| nanoeigenpy.DecompositionOptions.ComputeThinV.value,
13-
nanoeigenpy.DecompositionOptions.ComputeFullU.value
14-
| nanoeigenpy.DecompositionOptions.ComputeFullV.value,
15-
nanoeigenpy.DecompositionOptions.ComputeThinU.value
16-
| nanoeigenpy.DecompositionOptions.ComputeFullV.value,
17-
nanoeigenpy.DecompositionOptions.ComputeFullU.value
18-
| nanoeigenpy.DecompositionOptions.ComputeThinV.value,
12+
thin_u,
13+
thin_v,
14+
full_u,
15+
full_v,
16+
thin_u | thin_v,
17+
full_u | full_v,
18+
thin_u | full_v,
19+
full_u | thin_v,
1920
]
2021

2122
_classes = [
@@ -34,119 +35,94 @@ def test_jacobi(cls, options):
3435
A = rng.random((dim, dim))
3536
A = (A + A.T) * 0.5 + np.diag(10.0 + rng.random(dim))
3637

37-
if cls == nanoeigenpy.FullPivHhJacobiSVD:
38-
if options != 0 and not (
39-
options
40-
& (
41-
nanoeigenpy.DecompositionOptions.ComputeFullU.value
42-
| nanoeigenpy.DecompositionOptions.ComputeFullV.value
43-
)
44-
):
45-
return
46-
47-
jacobisvd = cls(A, options)
48-
assert jacobisvd.info() == nanoeigenpy.ComputationInfo.Success
49-
50-
if options & (
51-
nanoeigenpy.DecompositionOptions.ComputeThinU.value
52-
| nanoeigenpy.DecompositionOptions.ComputeFullU.value
53-
) and options & (
54-
nanoeigenpy.DecompositionOptions.ComputeThinV.value
55-
| nanoeigenpy.DecompositionOptions.ComputeFullV.value
56-
):
57-
X = rng.random((dim, 20))
58-
B = A @ X
59-
X_est = jacobisvd.solve(B)
60-
assert nanoeigenpy.is_approx(X, X_est)
61-
assert nanoeigenpy.is_approx(A @ X_est, B)
62-
63-
x = rng.random(dim)
64-
b = A @ x
65-
x_est = jacobisvd.solve(b)
66-
assert nanoeigenpy.is_approx(x, x_est)
67-
assert nanoeigenpy.is_approx(A @ x_est, b)
68-
69-
rows = jacobisvd.rows()
70-
cols = jacobisvd.cols()
71-
assert cols == dim
72-
assert rows == dim
73-
74-
_jacobisvd_compute = jacobisvd.compute(A)
75-
_jacobisvd_compute_options = jacobisvd.compute(A, options)
76-
77-
rank = jacobisvd.rank()
78-
singularvalues = jacobisvd.singularValues()
79-
nonzerosingularvalues = jacobisvd.nonzeroSingularValues()
80-
assert rank == nonzerosingularvalues
81-
assert len(singularvalues) == dim
82-
assert all(
83-
singularvalues[i] >= singularvalues[i + 1]
84-
for i in range(len(singularvalues) - 1)
38+
skip_case = (
39+
cls == nanoeigenpy.FullPivHhJacobiSVD
40+
and options != 0
41+
and not (options & (full_u | full_v))
8542
)
8643

87-
compute_u = jacobisvd.computeU()
88-
compute_v = jacobisvd.computeV()
89-
expected_compute_u = bool(
90-
options
91-
& (
92-
nanoeigenpy.DecompositionOptions.ComputeThinU.value
93-
| nanoeigenpy.DecompositionOptions.ComputeFullU.value
94-
)
95-
)
96-
expected_compute_v = bool(
97-
options
98-
& (
99-
nanoeigenpy.DecompositionOptions.ComputeThinV.value
100-
| nanoeigenpy.DecompositionOptions.ComputeFullV.value
101-
)
102-
)
103-
assert compute_u == expected_compute_u
104-
assert compute_v == expected_compute_v
105-
106-
if compute_u:
107-
matrixU = jacobisvd.matrixU()
108-
if options & nanoeigenpy.DecompositionOptions.ComputeFullU.value:
109-
assert matrixU.shape == (dim, dim)
110-
elif options & nanoeigenpy.DecompositionOptions.ComputeThinU.value:
111-
assert matrixU.shape == (dim, dim)
112-
assert nanoeigenpy.is_approx(matrixU.T @ matrixU, np.eye(matrixU.shape[1]))
113-
114-
if compute_v:
115-
matrixV = jacobisvd.matrixV()
116-
if options & nanoeigenpy.DecompositionOptions.ComputeFullV.value:
117-
assert matrixV.shape == (dim, dim)
118-
elif options & nanoeigenpy.DecompositionOptions.ComputeThinV.value:
119-
assert matrixV.shape == (dim, dim)
120-
assert nanoeigenpy.is_approx(matrixV.T @ matrixV, np.eye(matrixV.shape[1]))
121-
122-
if compute_u and compute_v:
123-
U = jacobisvd.matrixU()
124-
V = jacobisvd.matrixV()
125-
S = jacobisvd.singularValues()
126-
S_matrix = np.diag(S)
127-
A_reconstructed = U @ S_matrix @ V.T
128-
assert nanoeigenpy.is_approx(A, A_reconstructed)
129-
130-
jacobisvd.setThreshold()
131-
_default_threshold = jacobisvd.threshold()
132-
jacobisvd.setThreshold(1e-8)
133-
assert jacobisvd.threshold() == 1e-8
134-
135-
decomp1 = cls()
136-
decomp2 = cls()
137-
id1 = decomp1.id()
138-
id2 = decomp2.id()
139-
assert id1 != id2
140-
assert id1 == decomp1.id()
141-
assert id2 == decomp2.id()
142-
143-
decomp3 = cls(dim, dim, options)
144-
decomp4 = cls(dim, dim, options)
145-
id3 = decomp3.id()
146-
id4 = decomp4.id()
147-
assert id3 != id4
148-
assert id3 == decomp3.id()
149-
assert id4 == decomp4.id()
44+
if not skip_case:
45+
jacobisvd = cls(A, options)
46+
assert jacobisvd.info() == nanoeigenpy.ComputationInfo.Success
47+
48+
if options & (thin_u | full_u) and options & (thin_v | full_v):
49+
X = rng.random((dim, 20))
50+
B = A @ X
51+
X_est = jacobisvd.solve(B)
52+
assert nanoeigenpy.is_approx(X, X_est)
53+
assert nanoeigenpy.is_approx(A @ X_est, B)
54+
55+
x = rng.random(dim)
56+
b = A @ x
57+
x_est = jacobisvd.solve(b)
58+
assert nanoeigenpy.is_approx(x, x_est)
59+
assert nanoeigenpy.is_approx(A @ x_est, b)
60+
61+
rows = jacobisvd.rows()
62+
cols = jacobisvd.cols()
63+
assert cols == dim
64+
assert rows == dim
65+
66+
_jacobisvd_compute = jacobisvd.compute(A)
67+
_jacobisvd_compute_options = jacobisvd.compute(A, options)
68+
69+
rank = jacobisvd.rank()
70+
singularvalues = jacobisvd.singularValues()
71+
nonzerosingularvalues = jacobisvd.nonzeroSingularValues()
72+
assert rank == nonzerosingularvalues
73+
assert len(singularvalues) == dim
74+
75+
compute_u = jacobisvd.computeU()
76+
compute_v = jacobisvd.computeV()
77+
expected_compute_u = bool(options & (thin_u | full_u))
78+
expected_compute_v = bool(options & (thin_v | full_v))
79+
assert compute_u == expected_compute_u
80+
assert compute_v == expected_compute_v
81+
82+
if compute_u:
83+
matrixU = jacobisvd.matrixU()
84+
if options & full_u:
85+
assert matrixU.shape == (dim, dim)
86+
elif options & thin_u:
87+
assert matrixU.shape == (dim, dim)
88+
assert nanoeigenpy.is_approx(matrixU.T @ matrixU, np.eye(matrixU.shape[1]))
89+
90+
if compute_v:
91+
matrixV = jacobisvd.matrixV()
92+
if options & full_v:
93+
assert matrixV.shape == (dim, dim)
94+
elif options & thin_v:
95+
assert matrixV.shape == (dim, dim)
96+
assert nanoeigenpy.is_approx(matrixV.T @ matrixV, np.eye(matrixV.shape[1]))
97+
98+
if compute_u and compute_v:
99+
U = jacobisvd.matrixU()
100+
V = jacobisvd.matrixV()
101+
S = jacobisvd.singularValues()
102+
S_matrix = np.diag(S)
103+
A_reconstructed = U @ S_matrix @ V.T
104+
assert nanoeigenpy.is_approx(A, A_reconstructed)
105+
106+
jacobisvd.setThreshold()
107+
_default_threshold = jacobisvd.threshold()
108+
jacobisvd.setThreshold(1e-8)
109+
assert jacobisvd.threshold() == 1e-8
110+
111+
decomp1 = cls()
112+
decomp2 = cls()
113+
id1 = decomp1.id()
114+
id2 = decomp2.id()
115+
assert id1 != id2
116+
assert id1 == decomp1.id()
117+
assert id2 == decomp2.id()
118+
119+
decomp3 = cls(dim, dim, options)
120+
decomp4 = cls(dim, dim, options)
121+
id3 = decomp3.id()
122+
id4 = decomp4.id()
123+
assert id3 != id4
124+
assert id3 == decomp3.id()
125+
assert id4 == decomp4.id()
150126

151127

152128
if __name__ == "__main__":

0 commit comments

Comments
 (0)