Squashed 'third_party/osqp/' content from commit 33454b3e23
Change-Id: I056df0582ca06664e86554c341a94c47ab932001
git-subtree-dir: third_party/osqp
git-subtree-split: 33454b3e236f1f44193bfbbb6b8c8e71f8f04e9a
Signed-off-by: Austin Schuh <austin.linux@gmail.com>
diff --git a/tests/update_matrices/CMakeLists.txt b/tests/update_matrices/CMakeLists.txt
new file mode 100644
index 0000000..2d10bd8
--- /dev/null
+++ b/tests/update_matrices/CMakeLists.txt
@@ -0,0 +1,13 @@
+get_directory_property(headers
+ DIRECTORY ${PROJECT_SOURCE_DIR}/tests
+ DEFINITION headers)
+
+set(headers ${headers}
+${CMAKE_CURRENT_SOURCE_DIR}/test_update_matrices.h PARENT_SCOPE)
+
+get_directory_property(codegen_headers
+ DIRECTORY ${PROJECT_SOURCE_DIR}/tests
+ DEFINITION codegen_headers)
+
+set(codegen_headers ${codegen_headers}
+ ${CMAKE_CURRENT_SOURCE_DIR}/data.h PARENT_SCOPE)
diff --git a/tests/update_matrices/__init__.py b/tests/update_matrices/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/update_matrices/__init__.py
diff --git a/tests/update_matrices/generate_problem.py b/tests/update_matrices/generate_problem.py
new file mode 100644
index 0000000..d801fc7
--- /dev/null
+++ b/tests/update_matrices/generate_problem.py
@@ -0,0 +1,109 @@
+import numpy as np
+from scipy import sparse
+import utils.codegen_utils as cu
+from numpy.random import Generator, PCG64
+
+# Set random seed for reproducibility
+rg = Generator(PCG64(2))
+
+# Define tests
+n = 5
+m = 8
+test_form_KKT_n = n
+test_form_KKT_m = m
+p = 0.7
+
+test_form_KKT_A = sparse.random(test_form_KKT_m, test_form_KKT_n, density=p, format='csc', random_state=rg)
+test_form_KKT_P = sparse.random(n, n, density=p, random_state=rg)
+test_form_KKT_P = (test_form_KKT_P @ test_form_KKT_P.T).tocsc() + sparse.eye(n, format='csc')
+test_form_KKT_Pu = sparse.triu(test_form_KKT_P, format='csc')
+test_form_KKT_rho = 1.6
+test_form_KKT_sigma = 0.1
+test_form_KKT_KKT = sparse.bmat([[test_form_KKT_P + test_form_KKT_sigma *
+ sparse.eye(test_form_KKT_n), test_form_KKT_A.T],
+ [test_form_KKT_A, -1./test_form_KKT_rho *
+ sparse.eye(test_form_KKT_m)]], format='csc')
+test_form_KKT_KKTu = sparse.triu(test_form_KKT_KKT, format='csc')
+
+
+# Create new P, A and KKT
+test_form_KKT_A_new = test_form_KKT_A.copy()
+test_form_KKT_A_new.data += rg.standard_normal(test_form_KKT_A_new.nnz)
+test_form_KKT_Pu_new = test_form_KKT_Pu.copy()
+test_form_KKT_Pu_new.data += 0.1 * rg.standard_normal(test_form_KKT_Pu_new.nnz)
+test_form_KKT_P_new = test_form_KKT_Pu_new + test_form_KKT_Pu_new.T - sparse.diags(test_form_KKT_Pu_new.diagonal())
+
+test_form_KKT_KKT_new = sparse.bmat([[test_form_KKT_P_new + test_form_KKT_sigma *
+ sparse.eye(test_form_KKT_n), test_form_KKT_A_new.T],
+ [test_form_KKT_A_new, -1./test_form_KKT_rho *
+ sparse.eye(test_form_KKT_m)]], format='csc')
+test_form_KKT_KKTu_new = sparse.triu(test_form_KKT_KKT_new, format='csc')
+
+
+# Test solve problem with initial P and A
+test_solve_P = test_form_KKT_P.copy()
+test_solve_Pu = test_form_KKT_Pu.copy()
+test_solve_q = rg.standard_normal(n)
+test_solve_A = test_form_KKT_A.copy()
+test_solve_l = -30 + rg.standard_normal(m)
+test_solve_u = 30 + rg.standard_normal(m)
+
+
+# Define new P
+test_solve_P_new = test_form_KKT_P_new.copy()
+test_solve_Pu_new = test_form_KKT_Pu_new.copy()
+
+
+# Define new A
+test_solve_A_new = test_form_KKT_A_new.copy()
+
+
+# Generate test data and solutions
+data = {'test_form_KKT_n': test_form_KKT_n,
+ 'test_form_KKT_m': test_form_KKT_m,
+ 'test_form_KKT_A': test_form_KKT_A,
+ 'test_form_KKT_Pu': test_form_KKT_Pu,
+ 'test_form_KKT_rho': test_form_KKT_rho,
+ 'test_form_KKT_sigma': test_form_KKT_sigma,
+ 'test_form_KKT_KKT': test_form_KKT_KKT,
+ 'test_form_KKT_KKTu': test_form_KKT_KKTu,
+ 'test_form_KKT_A_new': test_form_KKT_A_new,
+ 'test_form_KKT_Pu_new': test_form_KKT_Pu_new,
+ 'test_form_KKT_KKT_new': test_form_KKT_KKT_new,
+ 'test_form_KKT_KKTu_new': test_form_KKT_KKTu_new,
+ 'test_solve_Pu': test_solve_Pu,
+ 'test_solve_q': test_solve_q,
+ 'test_solve_A': test_solve_A,
+ 'test_solve_l': test_solve_l,
+ 'test_solve_u': test_solve_u,
+ 'n': n,
+ 'm': m,
+ 'test_solve_x': np.array([-4.61725223e-01, 7.97298788e-01,
+ 5.55470173e-04, 3.37603740e-01,
+ -1.14060693e+00]),
+ 'test_solve_y': np.zeros(m),
+ 'test_solve_obj_value': -1.885431747787806,
+ 'test_solve_status': 'optimal',
+ 'test_solve_Pu_new': test_solve_Pu_new,
+ 'test_solve_P_new_x': np.array([-0.48845963, 0.70997599, -0.09017696,
+ 0.33176037, -1.01867464]),
+ 'test_solve_P_new_y': np.zeros(m),
+ 'test_solve_P_new_obj_value': -1.7649689689774013,
+ 'test_solve_P_new_status': 'optimal',
+ 'test_solve_A_new': test_solve_A_new,
+ 'test_solve_A_new_x': np.array([-4.61725223e-01, 7.97298788e-01,
+ 5.55470173e-04, 3.37603740e-01,
+ -1.14060693e+00]),
+ 'test_solve_A_new_y': np.zeros(m),
+ 'test_solve_A_new_obj_value': -1.8854317477878062,
+ 'test_solve_A_new_status': 'optimal',
+ 'test_solve_P_A_new_x': np.array([-0.48845963, 0.70997599, -0.09017696,
+ 0.33176037, -1.01867464]),
+ 'test_solve_P_A_new_y': np.zeros(m),
+ 'test_solve_P_A_new_obj_value': -1.764968968977401,
+ 'test_solve_P_A_new_status': 'optimal'
+ }
+
+
+# Generate test data
+cu.generate_data('update_matrices', data)
diff --git a/tests/update_matrices/test_update_matrices.h b/tests/update_matrices/test_update_matrices.h
new file mode 100644
index 0000000..bb347a6
--- /dev/null
+++ b/tests/update_matrices/test_update_matrices.h
@@ -0,0 +1,471 @@
+#include <stdio.h>
+#include "osqp.h"
+#include "cs.h"
+#include "util.h"
+#include "osqp_tester.h"
+#include "kkt.h"
+#include "lin_sys.h"
+
+
+#include "update_matrices/data.h"
+
+
+void 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);
+}
+
+void 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);
+
+ // 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);
+
+
+ // 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);
+}
+
+#ifdef ENABLE_MKL_PARDISO
+void 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 = (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;
+ 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_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 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_int*)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);
+
+
+ // 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);
+}
+#endif
\ No newline at end of file