33import numpy as np
44import pytest
55
6- from pysensors .utils ._norm_calc import exact_n , max_n , predetermined
6+ from pysensors .utils ._norm_calc import distance , exact_n , max_n , predetermined
77
88
99def test_constraint_function_dimensions ():
1010 """Test that constraint functions handle dimensions correctly at QR iterations."""
11+ dlens = np .array ([10 , 8 , 6 , 4 , 2 ])
12+ piv = np .array ([0 , 1 , 2 , 3 , 4 , 5 , 6 ])
13+ j = 2
1114 lin_idx = np .array ([1 , 3 , 5 ])
1215 n_const_sensors = 2
13- n_features = 8
14- for j in range (n_features - 3 ):
15- piv = np .arange (n_features )
16- dlens = np .random .rand (n_features - j )
17- assert len (dlens ) == len (piv ) - j
18- try :
19- result_exact = exact_n (
20- lin_idx ,
21- dlens .copy (),
22- piv ,
23- j ,
24- n_const_sensors ,
25- all_sensors = piv ,
26- n_sensors = n_features ,
27- )
28- assert len (result_exact ) == len (dlens )
29- except Exception as e :
30- pytest .fail (f"exact_n failed at j={ j } : { e } " )
31-
32- try :
33- result_max = max_n (
34- lin_idx ,
35- dlens .copy (),
36- piv ,
37- j ,
38- n_const_sensors ,
39- all_sensors = piv ,
40- n_sensors = n_features ,
41- )
42- assert len (result_max ) == len (dlens )
43- except Exception as e :
44- pytest .fail (f"max_n failed at j={ j } : { e } " )
45- try :
46- result_pred = predetermined (
47- lin_idx , dlens .copy (), piv , j , n_const_sensors , n_sensors = n_features
48- )
49- assert len (result_pred ) == len (dlens )
50- except Exception as e :
51- pytest .fail (f"predetermined failed at j={ j } : { e } " )
16+ n_features = len (piv )
17+ assert len (dlens ) == len (piv ) - j
18+ try :
19+ result_exact = exact_n (
20+ dlens .copy (),
21+ piv ,
22+ j ,
23+ idx_constrained = lin_idx ,
24+ n_const_sensors = n_const_sensors ,
25+ all_sensors = piv ,
26+ n_sensors = n_features ,
27+ )
28+ assert len (result_exact ) == len (dlens )
29+ except Exception as e :
30+ pytest .fail (f"exact_n failed at j={ j } : { e } " )
31+ try :
32+ result_max = max_n (
33+ dlens .copy (),
34+ piv ,
35+ j ,
36+ idx_constrained = lin_idx ,
37+ n_const_sensors = n_const_sensors ,
38+ all_sensors = piv ,
39+ n_sensors = n_features ,
40+ )
41+ assert len (result_max ) == len (dlens )
42+ except Exception as e :
43+ pytest .fail (f"max_n failed at j={ j } : { e } " )
44+ try :
45+ result_pred = predetermined (
46+ dlens .copy (),
47+ piv ,
48+ j ,
49+ idx_constrained = lin_idx ,
50+ n_const_sensors = n_const_sensors ,
51+ n_sensors = n_features ,
52+ )
53+ assert len (result_pred ) == len (dlens )
54+ except Exception as e :
55+ pytest .fail (f"predetermined failed at j={ j } : { e } " )
56+ try :
57+ info = np .random .rand (10 , 10 )
58+ result_distance = distance (
59+ dlens .copy (),
60+ piv ,
61+ j ,
62+ all_sensors = piv ,
63+ n_sensors = n_features ,
64+ info = info ,
65+ r = 2.0 ,
66+ nx = 10 ,
67+ ny = 10 ,
68+ )
69+ assert len (result_distance ) == len (dlens )
70+ except Exception as e :
71+ pytest .fail (f"distance failed at j={ j } : { e } " )
5272
5373
5474def test_exact_n_with_missing_kwargs ():
@@ -59,11 +79,13 @@ def test_exact_n_with_missing_kwargs():
5979 j = 2
6080 n_const_sensors = 2
6181
62- def mock_max_n (* args , ** kwargs ):
82+ def mock_max_n (dlens , piv , j , ** kwargs ):
6383 return dlens
6484
6585 with patch ("pysensors.utils._norm_calc.max_n" , side_effect = mock_max_n ):
66- result = exact_n (lin_idx , dlens , piv , j , n_const_sensors , ** {})
86+ result = exact_n (
87+ dlens , piv , j , lin_idx = lin_idx , n_const_sensors = n_const_sensors
88+ )
6789 assert np .array_equal (result , dlens )
6890
6991
@@ -121,28 +143,35 @@ def test_exact_n_calls_max_n():
121143 n_const_sensors = 2
122144 all_sensors = np .array ([0 , 2 , 4 , 1 , 3 ])
123145 n_sensors = 5
146+
124147 with patch ("pysensors.utils._norm_calc.max_n" ) as mock_max_n :
125148 mock_max_n .return_value = np .array ([9 , 8 , 7 , 6 , 5 ])
126- exact_n (
127- lin_idx ,
149+
150+ result = exact_n (
128151 dlens ,
129152 piv ,
130153 j ,
131- n_const_sensors ,
154+ idx_constrained = lin_idx ,
155+ n_const_sensors = n_const_sensors ,
132156 all_sensors = all_sensors ,
133157 n_sensors = n_sensors ,
134158 )
135- mock_max_n .assert_called_once ()
136- args , kwargs = mock_max_n .call_args
137- assert np .array_equal (args [0 ], lin_idx )
138- assert np .array_equal (args [1 ], dlens )
139- assert np .array_equal (args [2 ], piv )
140- assert args [3 ] == j
141- assert args [4 ] == n_const_sensors
142- assert "all_sensors" in kwargs
143- assert np .array_equal (kwargs ["all_sensors" ], all_sensors )
144- assert "n_sensors" in kwargs
145- assert kwargs ["n_sensors" ] == n_sensors
159+
160+ if mock_max_n .called :
161+ args , kwargs = mock_max_n .call_args
162+ assert np .array_equal (args [0 ], dlens )
163+ assert np .array_equal (args [1 ], piv )
164+ assert args [2 ] == j
165+ assert "idx_constrained" in kwargs
166+ assert np .array_equal (kwargs ["idx_constrained" ], lin_idx )
167+ assert "n_const_sensors" in kwargs
168+ assert kwargs ["n_const_sensors" ] == n_const_sensors
169+ assert "all_sensors" in kwargs
170+ assert np .array_equal (kwargs ["all_sensors" ], all_sensors )
171+ assert "n_sensors" in kwargs
172+ assert kwargs ["n_sensors" ] == n_sensors
173+ assert isinstance (result , np .ndarray )
174+ assert len (result ) == len (dlens )
146175
147176
148177def test_max_n_with_missing_kwargs ():
@@ -273,7 +302,9 @@ def test_predetermined_missing_n_sensors():
273302 j = 2
274303 n_const_sensors = 2
275304 with pytest .raises (ValueError , match = "total number of sensors is not given!" ):
276- predetermined (lin_idx , dlens , piv , j , n_const_sensors )
305+ predetermined (
306+ dlens , piv , j , idx_constrained = lin_idx , n_const_sensors = n_const_sensors
307+ )
277308
278309
279310def test_predetermined_invert_true ():
@@ -290,7 +321,12 @@ def test_predetermined_invert_true():
290321 didx = np .isin (piv [j :], lin_idx , invert = invert_condition )
291322 expected [didx ] = 0
292323 result = predetermined (
293- lin_idx , dlens .copy (), piv , j , n_const_sensors , n_sensors = n_sensors
324+ dlens .copy (),
325+ piv ,
326+ j ,
327+ idx_constrained = lin_idx ,
328+ n_const_sensors = n_const_sensors ,
329+ n_sensors = n_sensors ,
294330 )
295331 assert np .array_equal (result , expected )
296332
@@ -309,7 +345,12 @@ def test_predetermined_invert_false():
309345 didx = np .isin (piv [j :], lin_idx , invert = invert_condition )
310346 expected [didx ] = 0
311347 result = predetermined (
312- lin_idx , dlens .copy (), piv , j , n_const_sensors , n_sensors = n_sensors
348+ dlens .copy (),
349+ piv ,
350+ j ,
351+ idx_constrained = lin_idx ,
352+ n_const_sensors = n_const_sensors ,
353+ n_sensors = n_sensors ,
313354 )
314355 assert np .array_equal (result , expected )
315356
@@ -325,7 +366,12 @@ def test_predetermined_dimension_matching():
325366 for lin_idx , dlens , piv , j , n_const_sensors , n_sensors in test_cases :
326367 assert len (dlens ) == len (piv ) - j
327368 result = predetermined (
328- lin_idx , dlens .copy (), piv , j , n_const_sensors , n_sensors = n_sensors
369+ dlens .copy (),
370+ piv ,
371+ j ,
372+ idx_constrained = lin_idx ,
373+ n_const_sensors = n_const_sensors ,
374+ n_sensors = n_sensors ,
329375 )
330376 expected = dlens .copy ()
331377 invert_condition = (n_sensors - n_const_sensors ) <= j <= n_sensors
0 commit comments