blob: bb347a6347ef923619ee1056f0a59b8dbab2ae75 [file] [log] [blame]
Austin Schuh9049e202022-02-20 17:34:16 -08001#include <stdio.h>
2#include "osqp.h"
3#include "cs.h"
4#include "util.h"
5#include "osqp_tester.h"
6#include "kkt.h"
7#include "lin_sys.h"
8
9
10#include "update_matrices/data.h"
11
12
13void test_form_KKT() {
14 update_matrices_sols_data *data;
15 c_float sigma, *rho_vec, *rho_inv_vec;
16 c_int m, *PtoKKT, *AtoKKT, *Pdiag_idx, Pdiag_n;
17 csc *KKT;
18
19 // Load problem data
20 data = generate_problem_update_matrices_sols_data();
21
22 // Define rho_vec and sigma to form KKT
23 sigma = data->test_form_KKT_sigma;
24 m = data->test_form_KKT_A->m;
25 rho_vec = (c_float*) c_calloc(m, sizeof(c_float));
26 rho_inv_vec = (c_float*) c_calloc(m, sizeof(c_float));
27 vec_add_scalar(rho_vec, data->test_form_KKT_rho, m);
28 vec_ew_recipr(rho_vec, rho_inv_vec, m);
29
30 // Allocate vectors of indices
31 PtoKKT = (c_int*) c_malloc((data->test_form_KKT_Pu->p[data->test_form_KKT_Pu->n]) *
32 sizeof(c_int));
33 AtoKKT = (c_int*) c_malloc((data->test_form_KKT_A->p[data->test_form_KKT_A->n]) *
34 sizeof(c_int));
35
36 // Form KKT matrix storing the index vectors
37 KKT = form_KKT(data->test_form_KKT_Pu,
38 data->test_form_KKT_A,
39 0,
40 sigma,
41 rho_inv_vec,
42 PtoKKT,
43 AtoKKT,
44 &Pdiag_idx,
45 &Pdiag_n,
46 OSQP_NULL);
47
48 // Assert if KKT matrix is the same as predicted one
49 mu_assert("Update matrices: error in forming KKT matrix!",
50 is_eq_csc(KKT, data->test_form_KKT_KKTu, TESTS_TOL));
51
52 // Update KKT matrix with new P and new A
53 update_KKT_P(KKT, data->test_form_KKT_Pu_new, PtoKKT, sigma, Pdiag_idx,
54 Pdiag_n);
55 update_KKT_A(KKT, data->test_form_KKT_A_new, AtoKKT);
56
57
58 // Assert if KKT matrix is the same as predicted one
59 mu_assert("Update matrices: error in updating KKT matrix!",
60 is_eq_csc(KKT, data->test_form_KKT_KKTu_new, TESTS_TOL));
61
62
63 // Cleanup
64 clean_problem_update_matrices_sols_data(data);
65 c_free(Pdiag_idx);
66 csc_spfree(KKT);
67 c_free(rho_vec);
68 c_free(rho_inv_vec);
69 c_free(AtoKKT);
70 c_free(PtoKKT);
71}
72
73void test_update() {
74 c_int i, nnzP, nnzA;
75 update_matrices_sols_data *data;
76 OSQPData *problem;
77 OSQPWorkspace *work;
78 OSQPSettings *settings;
79 c_int exitflag;
80
81 // Update matrix P
82 c_int *Px_new_idx;
83
84 // Update matrix A
85 c_int *Ax_new_idx;
86
87 // Load problem data
88 data = generate_problem_update_matrices_sols_data();
89
90 // Generate first problem data
91 problem = (OSQPData*) c_malloc(sizeof(OSQPData));
92 problem->P = data->test_solve_Pu;
93 problem->q = data->test_solve_q;
94 problem->A = data->test_solve_A;
95 problem->l = data->test_solve_l;
96 problem->u = data->test_solve_u;
97 problem->n = data->test_solve_Pu->n;
98 problem->m = data->test_solve_A->m;
99
100
101 // Define Solver settings as default
102 // Problem settings
103 settings = (OSQPSettings *)c_malloc(sizeof(OSQPSettings));
104 osqp_set_default_settings(settings);
105 settings->max_iter = 1000;
106 settings->alpha = 1.6;
107 settings->verbose = 1;
108
109 // Setup workspace
110 exitflag = osqp_setup(&work, problem, settings);
111
112 // Setup correct
113 mu_assert("Update matrices: original problem, setup error!", exitflag == 0);
114
115 // Solve Problem
116 osqp_solve(work);
117
118 // Compare solver statuses
119 mu_assert("Update matrices: original problem, error in solver status!",
120 work->info->status_val == data->test_solve_status);
121
122 // Compare primal solutions
123 mu_assert("Update matrices: original problem, error in primal solution!",
124 vec_norm_inf_diff(work->solution->x, data->test_solve_x,
125 data->n) < TESTS_TOL);
126
127 // Compare dual solutions
128 mu_assert("Update matrices: original problem, error in dual solution!",
129 vec_norm_inf_diff(work->solution->y, data->test_solve_y,
130 data->m) < TESTS_TOL);
131
132
133 // Update P
134 nnzP = data->test_solve_Pu->p[data->test_solve_Pu->n];
135 Px_new_idx = (c_int*) c_malloc(nnzP * sizeof(c_int));
136
137 // Generate indices going from beginning to end of P
138 for (i = 0; i < nnzP; i++) {
139 Px_new_idx[i] = i;
140 }
141
142 osqp_update_P(work, data->test_solve_Pu_new->x, Px_new_idx, nnzP);
143
144 // Solve Problem
145 osqp_solve(work);
146
147 // Compare solver statuses
148 mu_assert("Update matrices: problem with updating P, error in solver status!",
149 work->info->status_val == data->test_solve_P_new_status);
150
151 // Compare primal solutions
152 mu_assert("Update matrices: problem with updating P, error in primal solution!",
153 vec_norm_inf_diff(work->solution->x, data->test_solve_P_new_x,
154 data->n) < TESTS_TOL);
155
156 // Compare dual solutions
157 mu_assert("Update matrices: problem with updating P, error in dual solution!",
158 vec_norm_inf_diff(work->solution->y, data->test_solve_P_new_y,
159 data->m) < TESTS_TOL);
160
161 // Cleanup and setup workspace
162 osqp_cleanup(work);
163 exitflag = osqp_setup(&work, problem, settings);
164
165
166 // Update P (all indices)
167 osqp_update_P(work, data->test_solve_Pu_new->x, OSQP_NULL, nnzP);
168
169 // Solve Problem
170 osqp_solve(work);
171
172 // Compare solver statuses
173 mu_assert("Update matrices: problem with updating P (all indices), error in solver status!",
174 work->info->status_val == data->test_solve_P_new_status);
175
176 // Compare primal solutions
177 mu_assert("Update matrices: problem with updating P (all indices), error in primal solution!",
178 vec_norm_inf_diff(work->solution->x, data->test_solve_P_new_x,
179 data->n) < TESTS_TOL);
180
181 // Compare dual solutions
182 mu_assert("Update matrices: problem with updating P (all indices), error in dual solution!",
183 vec_norm_inf_diff(work->solution->y, data->test_solve_P_new_y,
184 data->m) < TESTS_TOL);
185
186 // Cleanup and setup workspace
187 osqp_cleanup(work);
188 exitflag = osqp_setup(&work, problem, settings);
189
190
191 // Update A
192 nnzA = data->test_solve_A->p[data->test_solve_A->n];
193 Ax_new_idx = (c_int*) c_malloc(nnzA * sizeof(c_int));
194
195 // Generate indices going from beginning to end of A
196 for (i = 0; i < nnzA; i++) {
197 Ax_new_idx[i] = i;
198 }
199
200 osqp_update_A(work, data->test_solve_A_new->x, Ax_new_idx, nnzA);
201
202 // Solve Problem
203 osqp_solve(work);
204
205 // Compare solver statuses
206 mu_assert("Update matrices: problem with updating A, error in solver status!",
207 work->info->status_val == data->test_solve_A_new_status);
208
209 // Compare primal solutions
210 mu_assert("Update matrices: problem with updating A, error in primal solution!",
211 vec_norm_inf_diff(work->solution->x, data->test_solve_A_new_x,
212 data->n) < TESTS_TOL);
213
214 // Compare dual solutions
215 mu_assert("Update matrices: problem with updating A, error in dual solution!",
216 vec_norm_inf_diff(work->solution->y, data->test_solve_A_new_y,
217 data->m) < TESTS_TOL);
218
219 // Cleanup and setup workspace
220 osqp_cleanup(work);
221 exitflag = osqp_setup(&work, problem, settings);
222
223
224 // Update A (all indices)
225 osqp_update_A(work, data->test_solve_A_new->x, OSQP_NULL, nnzA);
226
227 // Solve Problem
228 osqp_solve(work);
229
230 // Compare solver statuses
231 mu_assert("Update matrices: problem with updating A (all indices), error in solver status!",
232 work->info->status_val == data->test_solve_A_new_status);
233
234 // Compare primal solutions
235 mu_assert("Update matrices: problem with updating A (all indices), error in primal solution!",
236 vec_norm_inf_diff(work->solution->x, data->test_solve_A_new_x,
237 data->n) < TESTS_TOL);
238
239 // Compare dual solutions
240 mu_assert("Update matrices: problem with updating A (all indices), error in dual solution!",
241 vec_norm_inf_diff(work->solution->y, data->test_solve_A_new_y,
242 data->m) < TESTS_TOL);
243
244
245 // Cleanup and setup workspace
246 osqp_cleanup(work);
247 exitflag = osqp_setup(&work, problem, settings);
248
249 // Update P and A
250 osqp_update_P_A(work, data->test_solve_Pu_new->x, Px_new_idx, nnzP,
251 data->test_solve_A_new->x, Ax_new_idx, nnzA);
252
253 // Solve Problem
254 osqp_solve(work);
255
256 // Compare solver statuses
257 mu_assert(
258 "Update matrices: problem with updating P and A, error in solver status!",
259 work->info->status_val == data->test_solve_P_A_new_status);
260
261 // Compare primal solutions
262 mu_assert(
263 "Update matrices: problem with updating P and A, error in primal solution!",
264 vec_norm_inf_diff(work->solution->x, data->test_solve_P_A_new_x,
265 data->n) < TESTS_TOL);
266
267 // Compare dual solutions
268 mu_assert(
269 "Update matrices: problem with updating P and A, error in dual solution!",
270 vec_norm_inf_diff(work->solution->y, data->test_solve_P_A_new_y,
271 data->m) < TESTS_TOL);
272
273 // Cleanup and setup workspace
274 osqp_cleanup(work);
275 exitflag = osqp_setup(&work, problem, settings);
276
277
278 // Update P and A (all indices)
279 osqp_update_P_A(work, data->test_solve_Pu_new->x, OSQP_NULL, nnzP,
280 data->test_solve_A_new->x, OSQP_NULL, nnzA);
281
282 // Solve Problem
283 osqp_solve(work);
284
285 // Compare solver statuses
286 mu_assert(
287 "Update matrices: problem with updating P and A (all indices), error in solver status!",
288 work->info->status_val == data->test_solve_P_A_new_status);
289
290 // Compare primal solutions
291 mu_assert(
292 "Update matrices: problem with updating P and A (all indices), error in primal solution!",
293 vec_norm_inf_diff(work->solution->x, data->test_solve_P_A_new_x,
294 data->n) < TESTS_TOL);
295
296 // Compare dual solutions
297 mu_assert(
298 "Update matrices: problem with updating P and A (all indices), error in dual solution!",
299 vec_norm_inf_diff(work->solution->y, data->test_solve_P_A_new_y,
300 data->m) < TESTS_TOL);
301
302
303 // Cleanup problems
304 osqp_cleanup(work);
305 clean_problem_update_matrices_sols_data(data);
306 c_free(problem);
307 c_free(settings);
308 c_free(Ax_new_idx);
309 c_free(Px_new_idx);
310}
311
312#ifdef ENABLE_MKL_PARDISO
313void test_update_pardiso() {
314 c_int i, nnzP, nnzA, exitflag;
315 update_matrices_sols_data *data;
316 OSQPData *problem;
317 OSQPWorkspace *work;
318 OSQPSettings *settings;
319
320 // Update matrix P
321 c_int *Px_new_idx;
322
323 // Update matrix A
324 c_int *Ax_new_idx;
325
326 // Load problem data
327 data = generate_problem_update_matrices_sols_data();
328
329 // Generate first problem data
330 problem = (OSQPData*)c_malloc(sizeof(OSQPData));
331 problem->P = data->test_solve_Pu;
332 problem->q = data->test_solve_q;
333 problem->A = data->test_solve_A;
334 problem->l = data->test_solve_l;
335 problem->u = data->test_solve_u;
336 problem->n = data->test_solve_Pu->n;
337 problem->m = data->test_solve_A->m;
338
339
340 // Define Solver settings as default
341 // Problem settings
342 settings = (OSQPSettings *)c_malloc(sizeof(OSQPSettings));
343 osqp_set_default_settings(settings);
344 settings->max_iter = 1000;
345 settings->alpha = 1.6;
346 settings->verbose = 1;
347 settings->linsys_solver = MKL_PARDISO_SOLVER;
348
349 // Setup workspace
350 exitflag = osqp_setup(&work, problem, settings);
351
352 // Setup correct
353 mu_assert("Update matrices: original problem, setup error!", exitflag == 0);
354
355 // Solve Problem
356 osqp_solve(work);
357
358 // Compare solver statuses
359 mu_assert("Update matrices: original problem, error in solver status!",
360 work->info->status_val == data->test_solve_status);
361
362 // Compare primal solutions
363 mu_assert("Update matrices: original problem, error in primal solution!",
364 vec_norm_inf_diff(work->solution->x, data->test_solve_x,
365 data->n) < TESTS_TOL);
366
367 // Compare dual solutions
368 mu_assert("Update matrices: original problem, error in dual solution!",
369 vec_norm_inf_diff(work->solution->y, data->test_solve_y,
370 data->m) < TESTS_TOL);
371
372
373 // Update P
374 nnzP = data->test_solve_Pu->p[data->test_solve_Pu->n];
375 Px_new_idx = (c_int*)c_malloc(nnzP * sizeof(c_int)); // Generate indices going from
376 // beginning to end of P
377
378 for (i = 0; i < nnzP; i++) {
379 Px_new_idx[i] = i;
380 }
381
382 osqp_update_P(work, data->test_solve_Pu_new->x, Px_new_idx, nnzP);
383
384 // Solve Problem
385 osqp_solve(work);
386
387 // Compare solver statuses
388 mu_assert("Update matrices: problem with P updated, error in solver status!",
389 work->info->status_val == data->test_solve_P_new_status);
390
391 // Compare primal solutions
392 mu_assert("Update matrices: problem with P updated, error in primal solution!",
393 vec_norm_inf_diff(work->solution->x, data->test_solve_P_new_x,
394 data->n) < TESTS_TOL);
395
396 // Compare dual solutions
397 mu_assert("Update matrices: problem with P updated, error in dual solution!",
398 vec_norm_inf_diff(work->solution->y, data->test_solve_P_new_y,
399 data->m) < TESTS_TOL);
400
401
402 // Update A
403 nnzA = data->test_solve_A->p[data->test_solve_A->n];
404 Ax_new_idx = (c_int*)c_malloc(nnzA * sizeof(c_int)); // Generate indices going from
405 // beginning to end of P
406
407 for (i = 0; i < nnzA; i++) {
408 Ax_new_idx[i] = i;
409 }
410
411 // Cleanup and setup workspace
412 osqp_cleanup(work);
413 exitflag = osqp_setup(&work, problem, settings);
414
415 osqp_update_A(work, data->test_solve_A_new->x, Ax_new_idx, nnzA);
416
417 // Solve Problem
418 osqp_solve(work);
419
420 // Compare solver statuses
421 mu_assert("Update matrices: problem with A updated, error in solver status!",
422 work->info->status_val == data->test_solve_A_new_status);
423
424 // Compare primal solutions
425 mu_assert("Update matrices: problem with A updated, error in primal solution!",
426 vec_norm_inf_diff(work->solution->x, data->test_solve_A_new_x,
427 data->n) < TESTS_TOL);
428
429 // Compare dual solutions
430 mu_assert("Update matrices: problem with A updated, error in dual solution!",
431 vec_norm_inf_diff(work->solution->y, data->test_solve_A_new_y,
432 data->m) < TESTS_TOL);
433
434
435 // Cleanup and setup workspace
436 osqp_cleanup(work);
437 exitflag = osqp_setup(&work, problem, settings);
438
439 osqp_update_P_A(work, data->test_solve_Pu_new->x, Px_new_idx, nnzP,
440 data->test_solve_A_new->x, Ax_new_idx, nnzA);
441
442 // Solve Problem
443 osqp_solve(work);
444
445 // Compare solver statuses
446 mu_assert(
447 "Update matrices: problem with P and A updated, error in solver status!",
448 work->info->status_val == data->test_solve_P_A_new_status);
449
450 // Compare primal solutions
451 mu_assert(
452 "Update matrices: problem with P and A updated, error in primal solution!",
453 vec_norm_inf_diff(work->solution->x, data->test_solve_P_A_new_x,
454 data->n) < TESTS_TOL);
455
456 // Compare dual solutions
457 mu_assert(
458 "Update matrices: problem with P and A updated, error in dual solution!",
459 vec_norm_inf_diff(work->solution->y, data->test_solve_P_A_new_y,
460 data->m) < TESTS_TOL);
461
462
463 // Cleanup problems
464 osqp_cleanup(work);
465 clean_problem_update_matrices_sols_data(data);
466 c_free(problem);
467 c_free(settings);
468 c_free(Ax_new_idx);
469 c_free(Px_new_idx);
470}
471#endif