123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488 |
- #include <stdio.h>
- #include "osqp.h"
- #include "cs.h"
- #include "util.h"
- #include "minunit.h"
- #include "kkt.h"
- #include "lin_sys.h"
- #include "update_matrices/data.h"
- static const char* test_form_KKT() {
- update_matrices_sols_data *data;
- c_float sigma, *rho_vec, *rho_inv_vec;
- c_int m, *PtoKKT, *AtoKKT, *Pdiag_idx, Pdiag_n;
- csc *KKT;
- // Load problem data
- data = generate_problem_update_matrices_sols_data();
- // Define rho_vec and sigma to form KKT
- sigma = data->test_form_KKT_sigma;
- m = data->test_form_KKT_A->m;
- rho_vec = (c_float*) c_calloc(m, sizeof(c_float));
- rho_inv_vec = (c_float*) c_calloc(m, sizeof(c_float));
- vec_add_scalar(rho_vec, data->test_form_KKT_rho, m);
- vec_ew_recipr(rho_vec, rho_inv_vec, m);
- // Allocate vectors of indices
- PtoKKT = (c_int*) c_malloc((data->test_form_KKT_Pu->p[data->test_form_KKT_Pu->n]) *
- sizeof(c_int));
- AtoKKT = (c_int*) c_malloc((data->test_form_KKT_A->p[data->test_form_KKT_A->n]) *
- sizeof(c_int));
- // Form KKT matrix storing the index vectors
- KKT = form_KKT(data->test_form_KKT_Pu,
- data->test_form_KKT_A,
- 0,
- sigma,
- rho_inv_vec,
- PtoKKT,
- AtoKKT,
- &Pdiag_idx,
- &Pdiag_n,
- OSQP_NULL);
- // Assert if KKT matrix is the same as predicted one
- mu_assert("Update matrices: error in forming KKT matrix!",
- is_eq_csc(KKT, data->test_form_KKT_KKTu, TESTS_TOL));
- // Update KKT matrix with new P and new A
- update_KKT_P(KKT, data->test_form_KKT_Pu_new, PtoKKT, sigma, Pdiag_idx,
- Pdiag_n);
- update_KKT_A(KKT, data->test_form_KKT_A_new, AtoKKT);
- // Assert if KKT matrix is the same as predicted one
- mu_assert("Update matrices: error in updating KKT matrix!",
- is_eq_csc(KKT, data->test_form_KKT_KKTu_new, TESTS_TOL));
- // Cleanup
- clean_problem_update_matrices_sols_data(data);
- c_free(Pdiag_idx);
- csc_spfree(KKT);
- c_free(rho_vec);
- c_free(rho_inv_vec);
- c_free(AtoKKT);
- c_free(PtoKKT);
- return 0;
- }
- static const char* test_update() {
- c_int i, nnzP, nnzA;
- update_matrices_sols_data *data;
- OSQPData *problem;
- OSQPWorkspace *work;
- OSQPSettings *settings;
- c_int exitflag;
- // Update matrix P
- c_int *Px_new_idx;
- // Update matrix A
- c_int *Ax_new_idx;
- // Load problem data
- data = generate_problem_update_matrices_sols_data();
- // Generate first problem data
- problem = (OSQPData*) c_malloc(sizeof(OSQPData));
- problem->P = data->test_solve_Pu;
- problem->q = data->test_solve_q;
- problem->A = data->test_solve_A;
- problem->l = data->test_solve_l;
- problem->u = data->test_solve_u;
- problem->n = data->test_solve_Pu->n;
- problem->m = data->test_solve_A->m;
- // Define Solver settings as default
- // Problem settings
- settings = (OSQPSettings *)c_malloc(sizeof(OSQPSettings));
- osqp_set_default_settings(settings);
- settings->max_iter = 1000;
- settings->alpha = 1.6;
- settings->verbose = 1;
- // Setup workspace
- exitflag = osqp_setup(&work, problem, settings);
- // Setup correct
- mu_assert("Update matrices: original problem, setup error!", exitflag == 0);
- // Solve Problem
- osqp_solve(work);
- // Compare solver statuses
- mu_assert("Update matrices: original problem, error in solver status!",
- work->info->status_val == data->test_solve_status);
- // Compare primal solutions
- mu_assert("Update matrices: original problem, error in primal solution!",
- vec_norm_inf_diff(work->solution->x, data->test_solve_x,
- data->n) < TESTS_TOL);
- // Compare dual solutions
- mu_assert("Update matrices: original problem, error in dual solution!",
- vec_norm_inf_diff(work->solution->y, data->test_solve_y,
- data->m) < TESTS_TOL);
- // Update P
- nnzP = data->test_solve_Pu->p[data->test_solve_Pu->n];
- Px_new_idx = (c_int*) c_malloc(nnzP * sizeof(c_int));
- // Generate indices going from beginning to end of P
- for (i = 0; i < nnzP; i++) {
- Px_new_idx[i] = i;
- }
- osqp_update_P(work, data->test_solve_Pu_new->x, Px_new_idx, nnzP);
- // Solve Problem
- osqp_solve(work);
- // Compare solver statuses
- mu_assert("Update matrices: problem with updating P, error in solver status!",
- work->info->status_val == data->test_solve_P_new_status);
- // Compare primal solutions
- mu_assert("Update matrices: problem with updating P, error in primal solution!",
- vec_norm_inf_diff(work->solution->x, data->test_solve_P_new_x,
- data->n) < TESTS_TOL);
- // Compare dual solutions
- mu_assert("Update matrices: problem with updating P, error in dual solution!",
- vec_norm_inf_diff(work->solution->y, data->test_solve_P_new_y,
- data->m) < TESTS_TOL);
- // Cleanup and setup workspace
- osqp_cleanup(work);
- exitflag = osqp_setup(&work, problem, settings);
- // Update P (all indices)
- osqp_update_P(work, data->test_solve_Pu_new->x, OSQP_NULL, nnzP);
- // Solve Problem
- osqp_solve(work);
- // Compare solver statuses
- mu_assert("Update matrices: problem with updating P (all indices), error in solver status!",
- work->info->status_val == data->test_solve_P_new_status);
- // Compare primal solutions
- mu_assert("Update matrices: problem with updating P (all indices), error in primal solution!",
- vec_norm_inf_diff(work->solution->x, data->test_solve_P_new_x,
- data->n) < TESTS_TOL);
- // Compare dual solutions
- mu_assert("Update matrices: problem with updating P (all indices), error in dual solution!",
- vec_norm_inf_diff(work->solution->y, data->test_solve_P_new_y,
- data->m) < TESTS_TOL);
- // Cleanup and setup workspace
- osqp_cleanup(work);
- exitflag = osqp_setup(&work, problem, settings);
- // Update A
- nnzA = data->test_solve_A->p[data->test_solve_A->n];
- Ax_new_idx = (c_int*) c_malloc(nnzA * sizeof(c_int));
- // Generate indices going from beginning to end of A
- for (i = 0; i < nnzA; i++) {
- Ax_new_idx[i] = i;
- }
- osqp_update_A(work, data->test_solve_A_new->x, Ax_new_idx, nnzA);
- // Solve Problem
- osqp_solve(work);
- // Compare solver statuses
- mu_assert("Update matrices: problem with updating A, error in solver status!",
- work->info->status_val == data->test_solve_A_new_status);
- // Compare primal solutions
- mu_assert("Update matrices: problem with updating A, error in primal solution!",
- vec_norm_inf_diff(work->solution->x, data->test_solve_A_new_x,
- data->n) < TESTS_TOL);
- // Compare dual solutions
- mu_assert("Update matrices: problem with updating A, error in dual solution!",
- vec_norm_inf_diff(work->solution->y, data->test_solve_A_new_y,
- data->m) < TESTS_TOL);
- // Cleanup and setup workspace
- osqp_cleanup(work);
- exitflag = osqp_setup(&work, problem, settings);
- // Update A (all indices)
- osqp_update_A(work, data->test_solve_A_new->x, OSQP_NULL, nnzA);
- // Solve Problem
- osqp_solve(work);
- // Compare solver statuses
- mu_assert("Update matrices: problem with updating A (all indices), error in solver status!",
- work->info->status_val == data->test_solve_A_new_status);
- // Compare primal solutions
- mu_assert("Update matrices: problem with updating A (all indices), error in primal solution!",
- vec_norm_inf_diff(work->solution->x, data->test_solve_A_new_x,
- data->n) < TESTS_TOL);
- // Compare dual solutions
- mu_assert("Update matrices: problem with updating A (all indices), error in dual solution!",
- vec_norm_inf_diff(work->solution->y, data->test_solve_A_new_y,
- data->m) < TESTS_TOL);
- // Cleanup and setup workspace
- osqp_cleanup(work);
- exitflag = osqp_setup(&work, problem, settings);
- // Update P and A
- osqp_update_P_A(work, data->test_solve_Pu_new->x, Px_new_idx, nnzP,
- data->test_solve_A_new->x, Ax_new_idx, nnzA);
- // Solve Problem
- osqp_solve(work);
- // Compare solver statuses
- mu_assert(
- "Update matrices: problem with updating P and A, error in solver status!",
- work->info->status_val == data->test_solve_P_A_new_status);
- // Compare primal solutions
- mu_assert(
- "Update matrices: problem with updating P and A, error in primal solution!",
- vec_norm_inf_diff(work->solution->x, data->test_solve_P_A_new_x,
- data->n) < TESTS_TOL);
- // Compare dual solutions
- mu_assert(
- "Update matrices: problem with updating P and A, error in dual solution!",
- vec_norm_inf_diff(work->solution->y, data->test_solve_P_A_new_y,
- data->m) < TESTS_TOL * TESTS_TOL);
- // Cleanup and setup workspace
- osqp_cleanup(work);
- exitflag = osqp_setup(&work, problem, settings);
- // Update P and A (all indices)
- osqp_update_P_A(work, data->test_solve_Pu_new->x, OSQP_NULL, nnzP,
- data->test_solve_A_new->x, OSQP_NULL, nnzA);
- // Solve Problem
- osqp_solve(work);
- // Compare solver statuses
- mu_assert(
- "Update matrices: problem with updating P and A (all indices), error in solver status!",
- work->info->status_val == data->test_solve_P_A_new_status);
- // Compare primal solutions
- mu_assert(
- "Update matrices: problem with updating P and A (all indices), error in primal solution!",
- vec_norm_inf_diff(work->solution->x, data->test_solve_P_A_new_x,
- data->n) < TESTS_TOL);
- // Compare dual solutions
- mu_assert(
- "Update matrices: problem with updating P and A (all indices), error in dual solution!",
- vec_norm_inf_diff(work->solution->y, data->test_solve_P_A_new_y,
- data->m) < TESTS_TOL * TESTS_TOL);
- // Cleanup problems
- osqp_cleanup(work);
- clean_problem_update_matrices_sols_data(data);
- c_free(problem);
- c_free(settings);
- c_free(Ax_new_idx);
- c_free(Px_new_idx);
- return 0;
- }
- #ifdef ENABLE_MKL_PARDISO
- static char* test_update_pardiso() {
- c_int i, nnzP, nnzA, exitflag;
- update_matrices_sols_data *data;
- OSQPData *problem;
- OSQPWorkspace *work;
- OSQPSettings *settings;
- // Update matrix P
- c_int *Px_new_idx;
- // Update matrix A
- c_int *Ax_new_idx;
- // Load problem data
- data = generate_problem_update_matrices_sols_data();
- // Generate first problem data
- problem = c_malloc(sizeof(OSQPData));
- problem->P = data->test_solve_Pu;
- problem->q = data->test_solve_q;
- problem->A = data->test_solve_A;
- problem->l = data->test_solve_l;
- problem->u = data->test_solve_u;
- problem->n = data->test_solve_Pu->n;
- problem->m = data->test_solve_A->m;
- // Define Solver settings as default
- // Problem settings
- settings = (OSQPSettings *)c_malloc(sizeof(OSQPSettings));
- osqp_set_default_settings(settings);
- settings->max_iter = 1000;
- settings->alpha = 1.6;
- settings->verbose = 1;
- settings->linsys_solver = MKL_PARDISO_SOLVER;
- // Setup workspace
- exitflag = osqp_setup(&work, problem, settings);
- // Setup correct
- mu_assert("Update matrices: original problem, setup error!", exitflag == 0);
- // Solve Problem
- osqp_solve(work);
- // Compare solver statuses
- mu_assert("Update matrices: original problem, error in solver status!",
- work->info->status_val == data->test_solve_status);
- // Compare primal solutions
- mu_assert("Update matrices: original problem, error in primal solution!",
- vec_norm_inf_diff(work->solution->x, data->test_solve_x,
- data->n) < TESTS_TOL);
- // Compare dual solutions
- mu_assert("Update matrices: original problem, error in dual solution!",
- vec_norm_inf_diff(work->solution->y, data->test_solve_y,
- data->m) < TESTS_TOL);
- // Update P
- nnzP = data->test_solve_Pu->p[data->test_solve_Pu->n];
- Px_new_idx = c_malloc(nnzP * sizeof(c_int)); // Generate indices going from
- // beginning to end of P
- for (i = 0; i < nnzP; i++) {
- Px_new_idx[i] = i;
- }
- osqp_update_P(work, data->test_solve_Pu_new->x, Px_new_idx, nnzP);
- // Solve Problem
- osqp_solve(work);
- // Compare solver statuses
- mu_assert("Update matrices: problem with P updated, error in solver status!",
- work->info->status_val == data->test_solve_P_new_status);
- // Compare primal solutions
- mu_assert("Update matrices: problem with P updated, error in primal solution!",
- vec_norm_inf_diff(work->solution->x, data->test_solve_P_new_x,
- data->n) < TESTS_TOL);
- // Compare dual solutions
- mu_assert("Update matrices: problem with P updated, error in dual solution!",
- vec_norm_inf_diff(work->solution->y, data->test_solve_P_new_y,
- data->m) < TESTS_TOL);
- // Update A
- nnzA = data->test_solve_A->p[data->test_solve_A->n];
- Ax_new_idx = c_malloc(nnzA * sizeof(c_int)); // Generate indices going from
- // beginning to end of P
- for (i = 0; i < nnzA; i++) {
- Ax_new_idx[i] = i;
- }
- // Cleanup and setup workspace
- osqp_cleanup(work);
- exitflag = osqp_setup(&work, problem, settings);
- osqp_update_A(work, data->test_solve_A_new->x, Ax_new_idx, nnzA);
- // Solve Problem
- osqp_solve(work);
- // Compare solver statuses
- mu_assert("Update matrices: problem with A updated, error in solver status!",
- work->info->status_val == data->test_solve_A_new_status);
- // Compare primal solutions
- mu_assert("Update matrices: problem with A updated, error in primal solution!",
- vec_norm_inf_diff(work->solution->x, data->test_solve_A_new_x,
- data->n) < TESTS_TOL);
- // Compare dual solutions
- mu_assert("Update matrices: problem with A updated, error in dual solution!",
- vec_norm_inf_diff(work->solution->y, data->test_solve_A_new_y,
- data->m) < TESTS_TOL);
- // Cleanup and setup workspace
- osqp_cleanup(work);
- exitflag = osqp_setup(&work, problem, settings);
- osqp_update_P_A(work, data->test_solve_Pu_new->x, Px_new_idx, nnzP,
- data->test_solve_A_new->x, Ax_new_idx, nnzA);
- // Solve Problem
- osqp_solve(work);
- // Compare solver statuses
- mu_assert(
- "Update matrices: problem with P and A updated, error in solver status!",
- work->info->status_val == data->test_solve_P_A_new_status);
- // Compare primal solutions
- mu_assert(
- "Update matrices: problem with P and A updated, error in primal solution!",
- vec_norm_inf_diff(work->solution->x, data->test_solve_P_A_new_x,
- data->n) < TESTS_TOL);
- // Compare dual solutions
- mu_assert(
- "Update matrices: problem with P and A updated, error in dual solution!",
- vec_norm_inf_diff(work->solution->y, data->test_solve_P_A_new_y,
- data->m) < TESTS_TOL * TESTS_TOL);
- // Cleanup problems
- osqp_cleanup(work);
- clean_problem_update_matrices_sols_data(data);
- c_free(problem);
- c_free(settings);
- c_free(Ax_new_idx);
- c_free(Px_new_idx);
- return 0;
- }
- #endif
- static const char* test_update_matrices()
- {
- mu_run_test(test_form_KKT);
- mu_run_test(test_update);
- #ifdef ENABLE_MKL_PARDISO
- mu_run_test(test_update_pardiso);
- #endif
- return 0;
- }
|