22import numpy as np
33import 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
152128if __name__ == "__main__" :
0 commit comments