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/basic_qp2/CMakeLists.txt b/tests/basic_qp2/CMakeLists.txt
new file mode 100644
index 0000000..5f7c7d4
--- /dev/null
+++ b/tests/basic_qp2/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_basic_qp2.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/basic_qp2/__init__.py b/tests/basic_qp2/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/basic_qp2/__init__.py
diff --git a/tests/basic_qp2/generate_problem.py b/tests/basic_qp2/generate_problem.py
new file mode 100644
index 0000000..23b48a9
--- /dev/null
+++ b/tests/basic_qp2/generate_problem.py
@@ -0,0 +1,34 @@
+import numpy as np
+from scipy import sparse
+import utils.codegen_utils as cu
+
+P = sparse.triu([[11., 0.], [0., 0.]], format='csc')
+q = np.array([3., 4.])
+
+A = sparse.csc_matrix(np.array([[-1., 0.], [0., -1.], [-1., 3.],
+                                [2., 5.], [3., 4]]))
+l = -np.inf * np.ones(A.shape[0])
+u = np.array([0., 0., -15., 100., 80.])
+
+n = P.shape[0]
+m = A.shape[0]
+
+# New data
+q_new = np.array([1., 1.])
+u_new = np.array([-2., 0., -20., 100., 80.])
+
+# Generate problem solutions
+sols_data = {'x_test': np.array([15., -0.]),
+             'y_test': np.array([0., 508., 168., 0., 0.]),
+             'obj_value_test': 1282.5,
+             'status_test': 'optimal',
+             'q_new': q_new,
+             'u_new': u_new,
+             'x_test_new': np.array([20., -0.]),
+             'y_test_new': np.array([0., 664., 221., 0., 0.]),
+             'obj_value_test_new': 2220.0,
+             'status_test_new': 'optimal'}
+
+
+# Generate problem data
+cu.generate_problem_data(P, q, A, l, u, 'basic_qp2', sols_data)
diff --git a/tests/basic_qp2/test_basic_qp2.h b/tests/basic_qp2/test_basic_qp2.h
new file mode 100644
index 0000000..c3445d2
--- /dev/null
+++ b/tests/basic_qp2/test_basic_qp2.h
@@ -0,0 +1,211 @@
+#include "osqp.h"        // OSQP API
+#include "osqp_tester.h" // Basic testing script header
+
+
+#include "basic_qp2/data.h"
+
+
+void test_basic_qp2_solve()
+{
+  c_int exitflag;
+
+  // Problem settings
+  OSQPSettings *settings = (OSQPSettings *)c_malloc(sizeof(OSQPSettings));
+
+  // Structures
+  OSQPWorkspace *work; // Workspace
+  OSQPData *data;      // Data
+  basic_qp2_sols_data *sols_data;
+
+
+  // Populate data
+  data = generate_problem_basic_qp2();
+  sols_data = generate_problem_basic_qp2_sols_data();
+
+
+  // Define Solver settings as default
+  osqp_set_default_settings(settings);
+  settings->alpha   = 1.6;
+  settings->rho     = 0.1;
+  settings->polish  = 1;
+  settings->verbose = 1;
+
+  // Setup workspace
+  exitflag = osqp_setup(&work, data, settings);
+
+  // Setup correct
+  mu_assert("Basic QP 2 test solve: Setup error!", exitflag == 0);
+
+  // Solve Problem first time
+  osqp_solve(work);
+
+  // Compare solver statuses
+  mu_assert("Basic QP 2 test solve: Error in solver status!",
+            work->info->status_val == sols_data->status_test);
+
+  // Compare primal solutions
+  mu_assert("Basic QP 2 test solve: Error in primal solution!",
+            vec_norm_inf_diff(work->solution->x, sols_data->x_test,
+                              data->n) /
+            vec_norm_inf(sols_data->x_test_new, data->n) < TESTS_TOL);
+
+
+  // Compare dual solutions
+  mu_assert("Basic QP 2 test solve: Error in dual solution!",
+            vec_norm_inf_diff(work->solution->y, sols_data->y_test,
+                              data->m) /
+            vec_norm_inf(sols_data->y_test_new, data->m) < TESTS_TOL);
+
+  // Compare objective values
+  mu_assert("Basic QP 2 test solve: Error in objective value!",
+            c_absval(work->info->obj_val - sols_data->obj_value_test)/(c_absval(sols_data->obj_value_test)) < TESTS_TOL);
+
+  // Clean workspace
+  osqp_cleanup(work);
+
+  // Cleanup settings and data
+  c_free(settings);
+  clean_problem_basic_qp2(data);
+  clean_problem_basic_qp2_sols_data(sols_data);
+}
+
+#ifdef ENABLE_MKL_PARDISO
+void test_basic_qp2_solve_pardiso()
+{
+  c_int exitflag;
+
+  // Problem settings
+  OSQPSettings *settings = (OSQPSettings *)c_malloc(sizeof(OSQPSettings));
+
+  // Structures
+  OSQPWorkspace *work; // Workspace
+  OSQPData *data;      // Data
+  basic_qp2_sols_data *sols_data;
+
+
+  // Populate data
+  data = generate_problem_basic_qp2();
+  sols_data = generate_problem_basic_qp2_sols_data();
+
+
+  // Define Solver settings as default
+  osqp_set_default_settings(settings);
+  settings->alpha         = 1.6;
+  settings->rho           = 0.1;
+  settings->polish        = 1;
+  settings->verbose       = 1;
+  settings->linsys_solver = MKL_PARDISO_SOLVER;
+
+  // Setup workspace
+  exitflag = osqp_setup(&work, data, settings);
+
+  // Setup correct
+  mu_assert("Basic QP 2 test solve: Setup error!", exitflag == 0);
+
+  // Solve Problem first time
+  osqp_solve(work);
+
+  // Compare solver statuses
+  mu_assert("Basic QP 2 test solve: Error in solver status!",
+            work->info->status_val == sols_data->status_test);
+
+  // Compare primal solutions
+  mu_assert("Basic QP 2 test solve: Error in primal solution!",
+            vec_norm_inf_diff(work->solution->x, sols_data->x_test,
+                              data->n) /
+            vec_norm_inf(sols_data->x_test_new, data->n) < TESTS_TOL);
+
+
+  // Compare dual solutions
+  mu_assert("Basic QP 2 test solve: Error in dual solution!",
+            vec_norm_inf_diff(work->solution->y, sols_data->y_test,
+                              data->m) /
+            vec_norm_inf(sols_data->y_test_new, data->m) < TESTS_TOL);
+
+
+  // Compare objective values
+  mu_assert("Basic QP 2 test solve: Error in objective value!",
+            c_absval(work->info->obj_val - sols_data->obj_value_test) <
+            TESTS_TOL);
+
+
+  // Clean workspace
+  osqp_cleanup(work);
+
+  // Cleanup settings and data
+  c_free(settings);
+  clean_problem_basic_qp2(data);
+  clean_problem_basic_qp2_sols_data(sols_data);
+}
+#endif
+
+void test_basic_qp2_update()
+{
+  c_int exitflag;
+
+  // Problem settings
+  OSQPSettings *settings = (OSQPSettings *)c_malloc(sizeof(OSQPSettings));
+
+  // Structures
+  OSQPWorkspace *work; // Workspace
+  OSQPData *data;      // Data
+  basic_qp2_sols_data *sols_data;
+
+
+  // Populate data
+  data = generate_problem_basic_qp2();
+  sols_data = generate_problem_basic_qp2_sols_data();
+
+
+  // Define Solver settings as default
+  osqp_set_default_settings(settings);
+  settings->alpha = 1.6;
+
+  settings->warm_start = 1;
+  settings->polish     = 1;
+  settings->verbose    = 1;
+
+  // Setup workspace
+  exitflag = osqp_setup(&work, data, settings);
+
+  // Setup correct
+  mu_assert("Basic QP 2 test update: Setup error!", exitflag == 0);
+
+
+  // Modify linear cost and upper bound
+  osqp_update_lin_cost(work, sols_data->q_new);
+  osqp_update_upper_bound(work, sols_data->u_new);
+
+  // Solve Problem second time(with different data now)
+  osqp_solve(work);
+
+  // Compare solver statuses
+  mu_assert("Basic QP 2 test update: Error in solver status!",
+            work->info->status_val == sols_data->status_test_new);
+
+  // Compare primal solutions
+  mu_assert("Basic QP 2 test update: Error in primal solution!",
+            vec_norm_inf_diff(work->solution->x, sols_data->x_test_new,
+                              data->n) /
+            vec_norm_inf(sols_data->x_test_new, data->n) < TESTS_TOL);
+
+  // Compare dual solutions
+  mu_assert("Basic QP 2 test update: Error in dual solution!",
+            vec_norm_inf_diff(work->solution->y, sols_data->y_test_new,
+                              data->m) /
+            vec_norm_inf(sols_data->y_test_new, data->m) < TESTS_TOL);
+
+
+  // Compare objective values
+  mu_assert("Basic QP 2 test update: Error in objective value!",
+            c_absval(
+              work->info->obj_val - sols_data->obj_value_test_new)/(c_absval(sols_data->obj_value_test_new)) < TESTS_TOL);
+
+  // Clean workspace
+  osqp_cleanup(work);
+
+  // Cleanup settings and data
+  c_free(settings);
+  clean_problem_basic_qp2(data);
+  clean_problem_basic_qp2_sols_data(sols_data);
+}