1+ import warnings
2+
13import numpy as np
24import pytest
35from numpy .typing import NDArray
46
57from qolmat .imputations .rpca .rpca_pcp import RPCAPCP
68from qolmat .utils import utils
79from qolmat .utils .data import generate_artificial_ts
8- from qolmat .utils .exceptions import CostFunctionRPCANotMinimized
910
1011X_complete = np .array ([[1 , 2 ], [3 , 1 ]], dtype = float )
1112X_incomplete = np .array ([[1 , 2 ], [3 , np .nan ], [np .nan , 4 ]], dtype = float )
@@ -41,41 +42,62 @@ def synthetic_temporal_data():
4142 )
4243 ],
4344)
44- def test_check_cost_function_minimized_raise_expection (
45+ def test_check_cost_function_minimized_warning (
46+ obs : NDArray , lr : NDArray , ano : NDArray , lam : float
47+ ):
48+ """Test warning when the cost function is minimized."""
49+ with pytest .warns (UserWarning ):
50+ RPCAPCP ()._check_cost_function_minimized (obs , lr , ano , lam )
51+
52+
53+ @pytest .mark .parametrize (
54+ "obs, lr, ano, lam" ,
55+ [
56+ (
57+ np .array ([[1 , 1 ], [1 , 1 ]], dtype = float ),
58+ np .array ([[0 , 0 ], [0 , 0 ]], dtype = float ),
59+ np .array ([[2 , 2 ], [2 , 2 ]], dtype = float ),
60+ 0 ,
61+ )
62+ ],
63+ )
64+ def test_check_cost_function_minimized_no_warning (
4565 obs : NDArray , lr : NDArray , ano : NDArray , lam : float
4666):
47- function_str = "||D||_* + lam ||A||_1"
48- rpca = RPCAPCP ()
49- with pytest .raises (
50- CostFunctionRPCANotMinimized ,
51- match = "PCA algorithm may provide bad results. "
52- f"{ function_str } is larger at the end "
53- "of the algorithm than at the start." ,
54- ):
55- rpca ._check_cost_function_minimized (obs , lr , ano , lam )
67+ """Test no warning when the cost function is minimized."""
68+ with warnings .catch_warnings (record = True ) as record :
69+ RPCAPCP ()._check_cost_function_minimized (obs , lr , ano , lam )
70+ assert len (record ) == 0
5671
5772
5873@pytest .mark .parametrize ("X" , [X_complete ])
5974def test_rpca_rpca_pcp_get_params_scale (X : NDArray ):
75+ """Test the parameters are well scaled."""
6076 rpca_pcp = RPCAPCP (max_iterations = max_iterations , mu = 0.5 , lam = 0.1 )
6177 result_dict = rpca_pcp .get_params_scale (X )
6278 result = list (result_dict .values ())
6379 params_expected = [1 / 7 , np .sqrt (2 ) / 2 ]
6480 np .testing .assert_allclose (result , params_expected , atol = 1e-4 )
6581
6682
67- # The problem is ill-conditioned and the result depends on the parameter mu
6883@pytest .mark .parametrize ("X, mu" , [(X_complete , small_mu )])
6984def test_rpca_rpca_pcp_zero_lambda_small_mu (X : NDArray , mu : float ):
85+ """Test RPCA PCP results if lambda equals zero.
86+ The problem is ill-conditioned and the result depends
87+ on the parameter mu; case when mu is small.
88+ """
7089 rpca_pcp = RPCAPCP (lam = 0 , mu = mu )
7190 X_result , A_result = rpca_pcp .decompose_rpca_signal (X )
7291 np .testing .assert_allclose (X_result , np .full_like (X , 0 ), atol = 1e-4 )
7392 np .testing .assert_allclose (A_result , X , atol = 1e-4 )
7493
7594
76- # The problem is ill-conditioned and the result depends on the parameter mu
7795@pytest .mark .parametrize ("X, mu" , [(X_complete , large_mu )])
7896def test_rpca_rpca_pcp_zero_lambda_large_mu (X : NDArray , mu : float ):
97+ """Test RPCA PCP results if lambda equals zero.
98+ The problem is ill-conditioned and the result depends
99+ on the parameter mu; case when mu is large.
100+ """
79101 rpca_pcp = RPCAPCP (lam = 0 , mu = mu )
80102 X_result , A_result = rpca_pcp .decompose_rpca_signal (X )
81103 np .testing .assert_allclose (X_result , X , atol = 1e-4 )
@@ -84,13 +106,16 @@ def test_rpca_rpca_pcp_zero_lambda_large_mu(X: NDArray, mu: float):
84106
85107@pytest .mark .parametrize ("X, mu" , [(X_complete , large_mu )])
86108def test_rpca_rpca_pcp_large_lambda_small_mu (X : NDArray , mu : float ):
109+ """Test RPCA PCP results with large lambda and small mu."""
87110 rpca_pcp = RPCAPCP (lam = 1e3 , mu = mu )
88111 X_result , A_result = rpca_pcp .decompose_rpca_signal (X )
89112 np .testing .assert_allclose (X_result , X , atol = 1e-4 )
90113 np .testing .assert_allclose (A_result , np .full_like (X , 0 ), atol = 1e-4 )
91114
92115
93116def test_rpca_temporal_signal (synthetic_temporal_data ):
117+ """Test RPCA PCP results for time series data.
118+ Check if the cost function is smaller at the end than at the start."""
94119 signal = synthetic_temporal_data
95120 period = 100
96121 lam = 0.1
0 commit comments