#include #include "osqp.h" #include "minunit.h" #include "lin_alg/data.h" static const char* test_constr_sparse_mat() { c_float *Adns; // Conversion to dense matrix lin_alg_sols_data *data = generate_problem_lin_alg_sols_data(); // Convert sparse to dense Adns = csc_to_dns(data->test_sp_matrix_A); // Compute norm of the elementwise difference with mu_assert("Linear algebra tests: error in constructing sparse/dense matrix!", vec_norm_inf_diff(Adns, data->test_sp_matrix_Adns, data->test_sp_matrix_A->m * data->test_sp_matrix_A->n) < TESTS_TOL); // Free memory c_free(Adns); // because of vars from file matrices.h clean_problem_lin_alg_sols_data(data); return 0; } static const char* test_vec_operations() { c_float norm_inf, vecprod; // normInf; c_float *ew_reciprocal; c_float *add_scaled; c_float *vec_ew_max_vec_test, *vec_ew_min_vec_test; lin_alg_sols_data *data = generate_problem_lin_alg_sols_data(); // Add scaled add_scaled = vec_copy(data->test_vec_ops_v1, data->test_vec_ops_n); vec_add_scaled(add_scaled, add_scaled, data->test_vec_ops_v2, data->test_vec_ops_n, data->test_vec_ops_sc); mu_assert( "Linear algebra tests: error in vector operation, adding scaled vector", vec_norm_inf_diff(add_scaled, data->test_vec_ops_add_scaled, data->test_vec_ops_n) < TESTS_TOL); // Norm_inf of the difference mu_assert( "Linear algebra tests: error in vector operation, norm_inf of difference", c_absval(vec_norm_inf_diff(data->test_vec_ops_v1, data->test_vec_ops_v2, data->test_vec_ops_n) - data->test_vec_ops_norm_inf_diff) < TESTS_TOL); // norm_inf norm_inf = vec_norm_inf(data->test_vec_ops_v1, data->test_vec_ops_n); mu_assert("Linear algebra tests: error in vector operation, norm_inf", c_absval(norm_inf - data->test_vec_ops_norm_inf) < TESTS_TOL); // Elementwise reciprocal ew_reciprocal = (c_float *)c_malloc(data->test_vec_ops_n * sizeof(c_float)); vec_ew_recipr(data->test_vec_ops_v1, ew_reciprocal, data->test_vec_ops_n); mu_assert( "Linear algebra tests: error in vector operation, elementwise reciprocal", vec_norm_inf_diff(ew_reciprocal, data->test_vec_ops_ew_reciprocal, data->test_vec_ops_n) < TESTS_TOL); // Vector product vecprod = vec_prod(data->test_vec_ops_v1, data->test_vec_ops_v2, data->test_vec_ops_n); mu_assert("Linear algebra tests: error in vector operation, vector product", c_absval(vecprod - data->test_vec_ops_vec_prod) < TESTS_TOL); // Elementwise maximum between two vectors vec_ew_max_vec_test = (c_float *)c_malloc(data->test_vec_ops_n * sizeof(c_float)); vec_ew_max_vec(data->test_vec_ops_v1, data->test_vec_ops_v2, vec_ew_max_vec_test, data->test_vec_ops_n); mu_assert( "Linear algebra tests: error in vector operation, elementwise maximum between vectors", vec_norm_inf_diff(vec_ew_max_vec_test, data->test_vec_ops_ew_max_vec, data ->test_vec_ops_n) < TESTS_TOL); // Elementwise minimum between two vectors vec_ew_min_vec_test = (c_float *)c_malloc(data->test_vec_ops_n * sizeof(c_float)); vec_ew_min_vec(data->test_vec_ops_v1, data->test_vec_ops_v2, vec_ew_min_vec_test, data->test_vec_ops_n); mu_assert( "Linear algebra tests: error in vector operation, elementwise minimum between vectors", vec_norm_inf_diff(vec_ew_min_vec_test, data->test_vec_ops_ew_min_vec, data ->test_vec_ops_n) < TESTS_TOL); // cleanup c_free(add_scaled); c_free(ew_reciprocal); c_free(vec_ew_min_vec_test); c_free(vec_ew_max_vec_test); clean_problem_lin_alg_sols_data(data); return 0; } static const char* test_mat_operations() { csc *Ad, *dA; // Matrices used for tests // csc *A_ewsq, *A_ewabs; // Matrices used for tests c_int exitflag = 0; // c_float trace, fro_sq; c_float *inf_norm_cols_rows_test; lin_alg_sols_data *data = generate_problem_lin_alg_sols_data(); // Copy matrices Ad = copy_csc_mat(data->test_mat_ops_A); dA = copy_csc_mat(data->test_mat_ops_A); // Premultiply matrix A mat_premult_diag(dA, data->test_mat_ops_d); mu_assert( "Linear algebra tests: error in matrix operation, premultiply diagonal", is_eq_csc(dA, data->test_mat_ops_prem_diag, TESTS_TOL)); // Postmultiply matrix A mat_postmult_diag(Ad, data->test_mat_ops_d); mu_assert( "Linear algebra tests: error in matrix operation, postmultiply diagonal", is_eq_csc(Ad, data->test_mat_ops_postm_diag, TESTS_TOL)); // Maximum norm over columns inf_norm_cols_rows_test = (c_float *)c_malloc(data->test_mat_ops_n * sizeof(c_float)); mat_inf_norm_cols(data->test_mat_ops_A, inf_norm_cols_rows_test); mu_assert( "Linear algebra tests: error in matrix operation, max norm over columns", vec_norm_inf_diff(inf_norm_cols_rows_test, data->test_mat_ops_inf_norm_cols, data ->test_mat_ops_n) < TESTS_TOL); // Maximum norm over rows mat_inf_norm_rows(data->test_mat_ops_A, inf_norm_cols_rows_test); mu_assert("Linear algebra tests: error in matrix operation, max norm over rows", vec_norm_inf_diff(inf_norm_cols_rows_test, data->test_mat_ops_inf_norm_rows, data ->test_mat_ops_n) < TESTS_TOL); // cleanup c_free(inf_norm_cols_rows_test); csc_spfree(Ad); csc_spfree(dA); clean_problem_lin_alg_sols_data(data); return 0; } static const char* test_mat_vec_multiplication() { c_float *Ax, *ATy, *Px, *Ax_cum, *ATy_cum, *Px_cum; lin_alg_sols_data *data = generate_problem_lin_alg_sols_data(); // Allocate vectors Ax = (c_float *)c_malloc(data->test_mat_vec_m * sizeof(c_float)); ATy = (c_float *)c_malloc(data->test_mat_vec_n * sizeof(c_float)); Px = (c_float *)c_malloc(data->test_mat_vec_n * sizeof(c_float)); // Matrix-vector multiplication: y = Ax mat_vec(data->test_mat_vec_A, data->test_mat_vec_x, Ax, 0); mu_assert( "Linear algebra tests: error in matrix-vector operation, matrix-vector multiplication", vec_norm_inf_diff(Ax, data->test_mat_vec_Ax, data->test_mat_vec_m) < TESTS_TOL); // Cumulative matrix-vector multiplication: y += Ax Ax_cum = vec_copy(data->test_mat_vec_y, data->test_mat_vec_m); mat_vec(data->test_mat_vec_A, data->test_mat_vec_x, Ax_cum, 1); mu_assert( "Linear algebra tests: error in matrix-vector operation, cumulative matrix-vector multiplication", vec_norm_inf_diff(Ax_cum, data->test_mat_vec_Ax_cum, data->test_mat_vec_m) < TESTS_TOL); // Matrix-transpose-vector multiplication: x = A'*y mat_tpose_vec(data->test_mat_vec_A, data->test_mat_vec_y, ATy, 0, 0); mu_assert( "Linear algebra tests: error in matrix-vector operation, matrix-transpose-vector multiplication", vec_norm_inf_diff(ATy, data->test_mat_vec_ATy, data->test_mat_vec_n) < TESTS_TOL); // Cumulative matrix-transpose-vector multiplication: x += A'*y ATy_cum = vec_copy(data->test_mat_vec_x, data->test_mat_vec_n); mat_tpose_vec(data->test_mat_vec_A, data->test_mat_vec_y, ATy_cum, 1, 0); mu_assert( "Linear algebra tests: error in matrix-vector operation, cumulative matrix-transpose-vector multiplication", vec_norm_inf_diff(ATy_cum, data->test_mat_vec_ATy_cum, data->test_mat_vec_n) < TESTS_TOL); // Symmetric-matrix-vector multiplication (only upper part is stored) mat_vec(data->test_mat_vec_Pu, data->test_mat_vec_x, Px, 0); // upper // traingular // part mat_tpose_vec(data->test_mat_vec_Pu, data->test_mat_vec_x, Px, 1, 1); // lower // traingular // part // (without // diagonal) mu_assert( "Linear algebra tests: error in matrix-vector operation, symmetric matrix-vector multiplication", vec_norm_inf_diff(Px, data->test_mat_vec_Px, data->test_mat_vec_n) < TESTS_TOL); // Cumulative symmetric-matrix-vector multiplication Px_cum = vec_copy(data->test_mat_vec_x, data->test_mat_vec_n); mat_vec(data->test_mat_vec_Pu, data->test_mat_vec_x, Px_cum, 1); // upper // traingular // part mat_tpose_vec(data->test_mat_vec_Pu, data->test_mat_vec_x, Px_cum, 1, 1); // lower // traingular // part // (without // diagonal) mu_assert( "Linear algebra tests: error in matrix-vector operation, cumulative symmetric matrix-vector multiplication", vec_norm_inf_diff(Px_cum, data->test_mat_vec_Px_cum, data->test_mat_vec_n) < TESTS_TOL); // cleanup c_free(Ax); c_free(ATy); c_free(Px); c_free(Ax_cum); c_free(ATy_cum); c_free(Px_cum); clean_problem_lin_alg_sols_data(data); return 0; } static const char* test_extract_upper_triangular() { c_float *inf_norm_cols_test; lin_alg_sols_data *data = generate_problem_lin_alg_sols_data(); // Extract upper triangular part csc *Ptriu = csc_to_triu(data->test_mat_extr_triu_P); mu_assert("Linear algebra tests: error in forming upper triangular matrix!", is_eq_csc(data->test_mat_extr_triu_Pu, Ptriu, TESTS_TOL)); // Compute infinity norm over columns of the original matrix by using the // upper triangular part only inf_norm_cols_test = (c_float *)c_malloc(data->test_mat_extr_triu_n * sizeof(c_float)); mat_inf_norm_cols_sym_triu(Ptriu, inf_norm_cols_test); mu_assert( "Linear algebra tests: error in forming upper triangular matrix, infinity norm over columns", vec_norm_inf_diff(inf_norm_cols_test, data->test_mat_extr_triu_P_inf_norm_cols, data->test_mat_extr_triu_n) < TESTS_TOL); // Cleanup c_free(inf_norm_cols_test); csc_spfree(Ptriu); clean_problem_lin_alg_sols_data(data); return 0; } static const char* test_quad_form_upper_triang() { c_float quad_form_t; lin_alg_sols_data *data = generate_problem_lin_alg_sols_data(); // Compute quadratic form quad_form_t = quad_form(data->test_qpform_Pu, data->test_qpform_x); mu_assert( "Linear algebra tests: error in computing quadratic form using upper triangular matrix!", (c_absval(quad_form_t - data->test_qpform_value) < TESTS_TOL)); // cleanup clean_problem_lin_alg_sols_data(data); return 0; } static const char* test_lin_alg() { mu_run_test(test_constr_sparse_mat); mu_run_test(test_vec_operations); mu_run_test(test_mat_operations); mu_run_test(test_mat_vec_multiplication); mu_run_test(test_extract_upper_triangular); mu_run_test(test_quad_form_upper_triang); return 0; }