blob: f9d52095b4f2cf1e8f046a406ca2efb06333e410 [file] [log] [blame]
Austin Schuh16ce3c72018-01-28 16:17:08 -08001/**************************************************************************************************
2* *
3* This file is part of HPIPM. *
4* *
5* HPIPM -- High Performance Interior Point Method. *
6* Copyright (C) 2017 by Gianluca Frison. *
7* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. *
8* All rights reserved. *
9* *
10* HPMPC is free software; you can redistribute it and/or *
11* modify it under the terms of the GNU Lesser General Public *
12* License as published by the Free Software Foundation; either *
13* version 2.1 of the License, or (at your option) any later version. *
14* *
15* HPMPC is distributed in the hope that it will be useful, *
16* but WITHOUT ANY WARRANTY; without even the implied warranty of *
17* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
18* See the GNU Lesser General Public License for more details. *
19* *
20* You should have received a copy of the GNU Lesser General Public *
21* License along with HPMPC; if not, write to the Free Software *
22* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
23* *
24* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de *
25* *
26**************************************************************************************************/
27
28#include <stdlib.h>
29#include <stdio.h>
30#include <math.h>
31#include <sys/time.h>
32
33#include <blasfeo_target.h>
34#include <blasfeo_common.h>
35#include <blasfeo_v_aux_ext_dep.h>
36#include <blasfeo_s_aux_ext_dep.h>
37#include <blasfeo_i_aux_ext_dep.h>
38#include <blasfeo_s_aux.h>
39#include <blasfeo_s_blas.h>
40
41#include "../include/hpipm_s_ocp_qp.h"
42#include "../include/hpipm_s_ocp_qp_sol.h"
43#include "../include/hpipm_s_ocp_qp_ipm_hard.h"
44
45#include "s_tools.h"
46
47
48
49#define KEEP_X0 0
50
51// printing
52#define PRINT 1
53
54/************************************************
55Mass-spring system: nx/2 masses connected each other with springs (in a row), and the first and the last one to walls. nu (<=nx) controls act on the first nu masses. The system is sampled with sampling time Ts.
56************************************************/
57void mass_spring_system(float Ts, int nx, int nu, int N, float *A, float *B, float *b, float *x0)
58 {
59
60 int nx2 = nx*nx;
61
62 int info = 0;
63
64 int pp = nx/2; // number of masses
65
66/************************************************
67* build the continuous time system
68************************************************/
69
70 float *T; s_zeros(&T, pp, pp);
71 int ii;
72 for(ii=0; ii<pp; ii++) T[ii*(pp+1)] = -2;
73 for(ii=0; ii<pp-1; ii++) T[ii*(pp+1)+1] = 1;
74 for(ii=1; ii<pp; ii++) T[ii*(pp+1)-1] = 1;
75
76 float *Z; s_zeros(&Z, pp, pp);
77 float *I; s_zeros(&I, pp, pp); for(ii=0; ii<pp; ii++) I[ii*(pp+1)]=1.0; // = eye(pp);
78 float *Ac; s_zeros(&Ac, nx, nx);
79 smcopy(pp, pp, Z, pp, Ac, nx);
80 smcopy(pp, pp, T, pp, Ac+pp, nx);
81 smcopy(pp, pp, I, pp, Ac+pp*nx, nx);
82 smcopy(pp, pp, Z, pp, Ac+pp*(nx+1), nx);
83 free(T);
84 free(Z);
85 free(I);
86
87 s_zeros(&I, nu, nu); for(ii=0; ii<nu; ii++) I[ii*(nu+1)]=1.0; //I = eye(nu);
88 float *Bc; s_zeros(&Bc, nx, nu);
89 smcopy(nu, nu, I, nu, Bc+pp, nx);
90 free(I);
91
92/************************************************
93* compute the discrete time system
94************************************************/
95
96 float *bb; s_zeros(&bb, nx, 1);
97 smcopy(nx, 1, bb, nx, b, nx);
98
99 smcopy(nx, nx, Ac, nx, A, nx);
100 sscal_3l(nx2, Ts, A);
101 expm(nx, A);
102
103 s_zeros(&T, nx, nx);
104 s_zeros(&I, nx, nx); for(ii=0; ii<nx; ii++) I[ii*(nx+1)]=1.0; //I = eye(nx);
105 smcopy(nx, nx, A, nx, T, nx);
106 saxpy_3l(nx2, -1.0, I, T);
107 sgemm_nn_3l(nx, nu, nx, T, nx, Bc, nx, B, nx);
108 free(T);
109 free(I);
110
111 int *ipiv = (int *) malloc(nx*sizeof(int));
112 sgesv_3l(nx, nu, Ac, nx, ipiv, B, nx, &info);
113 free(ipiv);
114
115 free(Ac);
116 free(Bc);
117 free(bb);
118
119
120/************************************************
121* initial state
122************************************************/
123
124 if(nx==4)
125 {
126 x0[0] = 5;
127 x0[1] = 10;
128 x0[2] = 15;
129 x0[3] = 20;
130 }
131 else
132 {
133 int jj;
134 for(jj=0; jj<nx; jj++)
135 x0[jj] = 1;
136 }
137
138 }
139
140
141
142int main()
143 {
144
145
146 // local variables
147
148 int ii, jj;
149
150 int rep, nrep=1000;
151
152 struct timeval tv0, tv1;
153
154
155
156 // problem size
157
158 int nx_ = 16; // number of states (it has to be even for the mass-spring system test problem)
159 int nu_ = 7; // number of inputs (controllers) (it has to be at least 1 and at most nx/2 for the mass-spring system test problem)
160 int N = 5; // horizon lenght
161
162
163
164 // stage-wise variant size
165
166 int nx[N+1];
167#if KEEP_X0
168 nx[0] = nx_;
169#else
170 nx[0] = 0;
171#endif
172 for(ii=1; ii<=N; ii++)
173 nx[ii] = nx_;
174// nx[N] = 0;
175
176 int nu[N+1];
177 for(ii=0; ii<N; ii++)
178 nu[ii] = nu_;
179 nu[N] = 0;
180
181#if 1
182 int nb[N+1];
183#if KEEP_X0
184 nb[0] = nu[0]+nx[0]/2;
185#else
186 nb[0] = nu[0];
187#endif
188 for(ii=1; ii<N; ii++)
189 nb[ii] = nu[1]+nx[1]/2;
190 nb[N] = nx[N]/2;
191
192 int ng[N+1];
193 ng[0] = 0;
194 for(ii=1; ii<N; ii++)
195 ng[ii] = 0;
196 ng[N] = 0;
197#elif 0
198 int nb[N+1];
199 nb[0] = 0;
200 for(ii=1; ii<N; ii++)
201 nb[ii] = 0;
202 nb[N] = 0;
203
204 int ng[N+1];
205#if KEEP_X0
206 ng[0] = nu[0]+nx[0]/2;
207#else
208 ng[0] = nu[0];
209#endif
210 for(ii=1; ii<N; ii++)
211 ng[ii] = nu[1]+nx[1]/2;
212 ng[N] = nx[N]/2;
213#else
214 int nb[N+1];
215 nb[0] = nu[0] + nx[0]/2;
216 for(ii=1; ii<N; ii++)
217 nb[ii] = nu[ii] + nx[ii]/2;
218 nb[N] = nu[N] + nx[N]/2;
219
220 int ng[N+1];
221#if KEEP_X0
222 ng[0] = nx[0]/2;
223#else
224 ng[0] = 0;
225#endif
226 for(ii=1; ii<N; ii++)
227 ng[ii] = nx[1]/2;
228 ng[N] = nx[N]/2;
229#endif
230
231/************************************************
232* dynamical system
233************************************************/
234
235 float *A; s_zeros(&A, nx_, nx_); // states update matrix
236
237 float *B; s_zeros(&B, nx_, nu_); // inputs matrix
238
239 float *b; s_zeros(&b, nx_, 1); // states offset
240 float *x0; s_zeros(&x0, nx_, 1); // initial state
241
242 float Ts = 0.5; // sampling time
243 mass_spring_system(Ts, nx_, nu_, N, A, B, b, x0);
244
245 for(jj=0; jj<nx_; jj++)
246 b[jj] = 0.1;
247
248 for(jj=0; jj<nx_; jj++)
249 x0[jj] = 0;
250 x0[0] = 2.5;
251 x0[1] = 2.5;
252
253 float *b0; s_zeros(&b0, nx_, 1);
254 sgemv_n_3l(nx_, nx_, A, nx_, x0, b0);
255 saxpy_3l(nx_, 1.0, b, b0);
256
257#if PRINT
258 s_print_mat(nx_, nx_, A, nx_);
259 s_print_mat(nx_, nu_, B, nu_);
260 s_print_mat(1, nx_, b, 1);
261 s_print_mat(1, nx_, x0, 1);
262 s_print_mat(1, nx_, b0, 1);
263#endif
264
265/************************************************
266* cost function
267************************************************/
268
269 float *Q; s_zeros(&Q, nx_, nx_);
270 for(ii=0; ii<nx_; ii++) Q[ii*(nx_+1)] = 1.0;
271
272 float *R; s_zeros(&R, nu_, nu_);
273 for(ii=0; ii<nu_; ii++) R[ii*(nu_+1)] = 2.0;
274
275 float *S; s_zeros(&S, nu_, nx_);
276
277 float *q; s_zeros(&q, nx_, 1);
278 for(ii=0; ii<nx_; ii++) q[ii] = 0.1;
279
280 float *r; s_zeros(&r, nu_, 1);
281 for(ii=0; ii<nu_; ii++) r[ii] = 0.2;
282
283 float *r0; s_zeros(&r0, nu_, 1);
284 sgemv_n_3l(nu_, nx_, S, nu_, x0, r0);
285 saxpy_3l(nu_, 1.0, r, r0);
286
287#if PRINT
288 s_print_mat(nx_, nx_, Q, nx_);
289 s_print_mat(nu_, nu_, R, nu_);
290 s_print_mat(nu_, nx_, S, nu_);
291 s_print_mat(1, nx_, q, 1);
292 s_print_mat(1, nu_, r, 1);
293 s_print_mat(1, nu_, r0, 1);
294#endif
295
296 // maximum element in cost functions
297 float mu0 = 2.0;
298
299/************************************************
300* box & general constraints
301************************************************/
302
303 int *idxb0; int_zeros(&idxb0, nb[0], 1);
304 float *d_lb0; s_zeros(&d_lb0, nb[0], 1);
305 float *d_ub0; s_zeros(&d_ub0, nb[0], 1);
306 float *d_lg0; s_zeros(&d_lg0, ng[0], 1);
307 float *d_ug0; s_zeros(&d_ug0, ng[0], 1);
308 for(ii=0; ii<nb[0]; ii++)
309 {
310 if(ii<nu[0]) // input
311 {
312 d_lb0[ii] = - 0.5; // umin
313 d_ub0[ii] = 0.5; // umax
314 }
315 else // state
316 {
317 d_lb0[ii] = - 4.0; // xmin
318 d_ub0[ii] = 4.0; // xmax
319 }
320 idxb0[ii] = ii;
321 }
322 for(ii=0; ii<ng[0]; ii++)
323 {
324 if(ii<nu[0]-nb[0]) // input
325 {
326 d_lg0[ii] = - 0.5; // umin
327 d_ug0[ii] = 0.5; // umax
328 }
329 else // state
330 {
331 d_lg0[ii] = - 4.0; // xmin
332 d_ug0[ii] = 4.0; // xmax
333 }
334 }
335
336 int *idxb1; int_zeros(&idxb1, nb[1], 1);
337 float *d_lb1; s_zeros(&d_lb1, nb[1], 1);
338 float *d_ub1; s_zeros(&d_ub1, nb[1], 1);
339 float *d_lg1; s_zeros(&d_lg1, ng[1], 1);
340 float *d_ug1; s_zeros(&d_ug1, ng[1], 1);
341 for(ii=0; ii<nb[1]; ii++)
342 {
343 if(ii<nu[1]) // input
344 {
345 d_lb1[ii] = - 0.5; // umin
346 d_ub1[ii] = 0.5; // umax
347 }
348 else // state
349 {
350 d_lb1[ii] = - 4.0; // xmin
351 d_ub1[ii] = 4.0; // xmax
352 }
353 idxb1[ii] = ii;
354 }
355 for(ii=0; ii<ng[1]; ii++)
356 {
357 if(ii<nu[1]-nb[1]) // input
358 {
359 d_lg1[ii] = - 0.5; // umin
360 d_ug1[ii] = 0.5; // umax
361 }
362 else // state
363 {
364 d_lg1[ii] = - 4.0; // xmin
365 d_ug1[ii] = 4.0; // xmax
366 }
367 }
368
369
370 int *idxbN; int_zeros(&idxbN, nb[N], 1);
371 float *d_lbN; s_zeros(&d_lbN, nb[N], 1);
372 float *d_ubN; s_zeros(&d_ubN, nb[N], 1);
373 float *d_lgN; s_zeros(&d_lgN, ng[N], 1);
374 float *d_ugN; s_zeros(&d_ugN, ng[N], 1);
375 for(ii=0; ii<nb[N]; ii++)
376 {
377 d_lbN[ii] = - 4.0; // xmin
378 d_ubN[ii] = 4.0; // xmax
379 idxbN[ii] = ii;
380 }
381 for(ii=0; ii<ng[N]; ii++)
382 {
383 d_lgN[ii] = - 4.0; // dmin
384 d_ugN[ii] = 4.0; // dmax
385 }
386
387 float *C0; s_zeros(&C0, ng[0], nx[0]);
388 float *D0; s_zeros(&D0, ng[0], nu[0]);
389 for(ii=0; ii<nu[0]-nb[0] & ii<ng[0]; ii++)
390 D0[ii+(nb[0]+ii)*ng[0]] = 1.0;
391 for(; ii<ng[0]; ii++)
392 C0[ii+(nb[0]+ii-nu[0])*ng[0]] = 1.0;
393
394 float *C1; s_zeros(&C1, ng[1], nx[1]);
395 float *D1; s_zeros(&D1, ng[1], nu[1]);
396 for(ii=0; ii<nu[1]-nb[1] & ii<ng[1]; ii++)
397 D1[ii+(nb[1]+ii)*ng[1]] = 1.0;
398 for(; ii<ng[1]; ii++)
399 C1[ii+(nb[1]+ii-nu[1])*ng[1]] = 1.0;
400
401 float *CN; s_zeros(&CN, ng[N], nx[N]);
402 float *DN; s_zeros(&DN, ng[N], nu[N]);
403 for(ii=0; ii<nu[N]-nb[N] & ii<ng[N]; ii++)
404 DN[ii+(nb[N]+ii)*ng[N]] = 1.0;
405 for(; ii<ng[N]; ii++)
406 CN[ii+(nb[N]+ii-nu[N])*ng[N]] = 1.0;
407
408#if PRINT
409 // box constraints
410 int_print_mat(1, nb[0], idxb0, 1);
411 s_print_mat(1, nb[0], d_lb0, 1);
412 s_print_mat(1, nb[0], d_ub0, 1);
413 int_print_mat(1, nb[1], idxb1, 1);
414 s_print_mat(1, nb[1], d_lb1, 1);
415 s_print_mat(1, nb[1], d_ub1, 1);
416 int_print_mat(1, nb[N], idxbN, 1);
417 s_print_mat(1, nb[N], d_lbN, 1);
418 s_print_mat(1, nb[N], d_ubN, 1);
419 // general constraints
420 s_print_mat(1, ng[0], d_lg0, 1);
421 s_print_mat(1, ng[0], d_ug0, 1);
422 s_print_mat(ng[0], nu[0], D0, ng[0]);
423 s_print_mat(ng[0], nx[0], C0, ng[0]);
424 s_print_mat(1, ng[1], d_lg1, 1);
425 s_print_mat(1, ng[1], d_ug1, 1);
426 s_print_mat(ng[1], nu[1], D1, ng[1]);
427 s_print_mat(ng[1], nx[1], C1, ng[1]);
428 s_print_mat(1, ng[N], d_lgN, 1);
429 s_print_mat(1, ng[N], d_ugN, 1);
430 s_print_mat(ng[N], nu[N], DN, ng[N]);
431 s_print_mat(ng[N], nx[N], CN, ng[N]);
432#endif
433
434/************************************************
435* array of matrices
436************************************************/
437
438 float *hA[N];
439 float *hB[N];
440 float *hb[N];
441 float *hQ[N+1];
442 float *hS[N+1];
443 float *hR[N+1];
444 float *hq[N+1];
445 float *hr[N+1];
446 float *hd_lb[N+1];
447 float *hd_ub[N+1];
448 float *hd_lg[N+1];
449 float *hd_ug[N+1];
450 float *hC[N+1];
451 float *hD[N+1];
452 int *hidxb[N+1];
453
454 hA[0] = A;
455 hB[0] = B;
456 hb[0] = b0;
457 hQ[0] = Q;
458 hS[0] = S;
459 hR[0] = R;
460 hq[0] = q;
461 hr[0] = r0;
462 hidxb[0] = idxb0;
463 hd_lb[0] = d_lb0;
464 hd_ub[0] = d_ub0;
465 hd_lg[0] = d_lg0;
466 hd_ug[0] = d_ug0;
467 hC[0] = C0;
468 hD[0] = D0;
469 for(ii=1; ii<N; ii++)
470 {
471 hA[ii] = A;
472 hB[ii] = B;
473 hb[ii] = b;
474 hQ[ii] = Q;
475 hS[ii] = S;
476 hR[ii] = R;
477 hq[ii] = q;
478 hr[ii] = r;
479 hidxb[ii] = idxb1;
480 hd_lb[ii] = d_lb1;
481 hd_ub[ii] = d_ub1;
482 hd_lg[ii] = d_lg1;
483 hd_ug[ii] = d_ug1;
484 hC[ii] = C1;
485 hD[ii] = D1;
486 }
487 hQ[N] = Q;
488 hS[N] = S;
489 hR[N] = R;
490 hq[N] = q;
491 hr[N] = r;
492 hidxb[N] = idxbN;
493 hd_lb[N] = d_lbN;
494 hd_ub[N] = d_ubN;
495 hd_lg[N] = d_lgN;
496 hd_ug[N] = d_ugN;
497 hC[N] = CN;
498 hD[N] = DN;
499
500/************************************************
501* ocp qp
502************************************************/
503
504 int qp_size = s_memsize_ocp_qp(N, nx, nu, nb, ng);
505 printf("\nqp size = %d\n", qp_size);
506 void *qp_mem = malloc(qp_size);
507
508 struct s_ocp_qp qp;
509 s_create_ocp_qp(N, nx, nu, nb, ng, &qp, qp_mem);
510 s_cvt_colmaj_to_ocp_qp(hA, hB, hb, hQ, hS, hR, hq, hr, hidxb, hd_lb, hd_ub, hC, hD, hd_lg, hd_ug, &qp);
511#if 0
512 printf("\nN = %d\n", qp.N);
513 for(ii=0; ii<N; ii++)
514 s_print_strmat(qp.nu[ii]+qp.nx[ii]+1, qp.nx[ii+1], qp.BAbt+ii, 0, 0);
515 for(ii=0; ii<N; ii++)
516 s_print_tran_strvec(qp.nx[ii+1], qp.b+ii, 0);
517 for(ii=0; ii<=N; ii++)
518 s_print_strmat(qp.nu[ii]+qp.nx[ii]+1, qp.nu[ii]+qp.nx[ii], qp.RSQrq+ii, 0, 0);
519 for(ii=0; ii<=N; ii++)
520 s_print_tran_strvec(qp.nu[ii]+qp.nx[ii], qp.rq+ii, 0);
521 for(ii=0; ii<=N; ii++)
522 int_print_mat(1, nb[ii], qp.idxb[ii], 1);
523 for(ii=0; ii<=N; ii++)
524 s_print_tran_strvec(qp.nb[ii], qp.d_lb+ii, 0);
525 for(ii=0; ii<=N; ii++)
526 s_print_tran_strvec(qp.nb[ii], qp.d_ub+ii, 0);
527 for(ii=0; ii<=N; ii++)
528 s_print_strmat(qp.nu[ii]+qp.nx[ii], qp.ng[ii], qp.DCt+ii, 0, 0);
529 for(ii=0; ii<=N; ii++)
530 s_print_tran_strvec(qp.ng[ii], qp.d_lg+ii, 0);
531 for(ii=0; ii<=N; ii++)
532 s_print_tran_strvec(qp.ng[ii], qp.d_ug+ii, 0);
533 return;
534#endif
535
536/************************************************
537* ocp qp
538************************************************/
539
540 int qp_sol_size = s_memsize_ocp_qp_sol(N, nx, nu, nb, ng);
541 printf("\nqp sol size = %d\n", qp_sol_size);
542 void *qp_sol_mem = malloc(qp_sol_size);
543
544 struct s_ocp_qp_sol qp_sol;
545 s_create_ocp_qp_sol(N, nx, nu, nb, ng, &qp_sol, qp_sol_mem);
546
547/************************************************
548* ipm
549************************************************/
550
551 struct s_ipm_hard_ocp_qp_arg arg;
552 arg.alpha_min = 1e-8;
553 arg.mu_max = 1e-12;
554 arg.iter_max = 20;
555 arg.mu0 = 2.0;
556
557 int ipm_size = s_memsize_ipm_hard_ocp_qp(&qp, &arg);
558 printf("\nipm size = %d\n", ipm_size);
559 void *ipm_mem = malloc(ipm_size);
560
561 struct s_ipm_hard_ocp_qp_workspace workspace;
562 s_create_ipm_hard_ocp_qp(&qp, &arg, &workspace, ipm_mem);
563
564 gettimeofday(&tv0, NULL); // start
565
566 for(rep=0; rep<nrep; rep++)
567 {
568// s_solve_ipm_hard_ocp_qp(&qp, &qp_sol, &workspace);
569 s_solve_ipm2_hard_ocp_qp(&qp, &qp_sol, &workspace);
570 }
571
572 gettimeofday(&tv1, NULL); // stop
573
574 float time_ocp_ipm = (tv1.tv_sec-tv0.tv_sec)/(nrep+0.0)+(tv1.tv_usec-tv0.tv_usec)/(nrep*1e6);
575
576#if 1
577 printf("\nsolution\n\n");
578 printf("\nux\n");
579 for(ii=0; ii<=N; ii++)
580 s_print_tran_strvec(nu[ii]+nx[ii], qp_sol.ux+ii, 0);
581 printf("\npi\n");
582 for(ii=0; ii<N; ii++)
583 s_print_tran_strvec(nx[ii+1], qp_sol.pi+ii, 0);
584 printf("\nlam_lb\n");
585 for(ii=0; ii<=N; ii++)
586 s_print_tran_strvec(nb[ii], qp_sol.lam_lb+ii, 0);
587 printf("\nlam_ub\n");
588 for(ii=0; ii<=N; ii++)
589 s_print_tran_strvec(nb[ii], qp_sol.lam_ub+ii, 0);
590 printf("\nlam_lg\n");
591 for(ii=0; ii<=N; ii++)
592 s_print_tran_strvec(ng[ii], qp_sol.lam_lg+ii, 0);
593 printf("\nlam_ug\n");
594 for(ii=0; ii<=N; ii++)
595 s_print_tran_strvec(ng[ii], qp_sol.lam_ug+ii, 0);
596 printf("\nt_lb\n");
597 for(ii=0; ii<=N; ii++)
598 s_print_tran_strvec(nb[ii], qp_sol.t_lb+ii, 0);
599 printf("\nt_ub\n");
600 for(ii=0; ii<=N; ii++)
601 s_print_tran_strvec(nb[ii], qp_sol.t_ub+ii, 0);
602 printf("\nt_lg\n");
603 for(ii=0; ii<=N; ii++)
604 s_print_tran_strvec(ng[ii], qp_sol.t_lg+ii, 0);
605 printf("\nt_ug\n");
606 for(ii=0; ii<=N; ii++)
607 s_print_tran_strvec(ng[ii], qp_sol.t_ug+ii, 0);
608
609 printf("\nresiduals\n\n");
610 printf("\nres_g\n");
611 for(ii=0; ii<=N; ii++)
612 s_print_e_tran_strvec(nu[ii]+nx[ii], workspace.res_g+ii, 0);
613 printf("\nres_b\n");
614 for(ii=0; ii<N; ii++)
615 s_print_e_tran_strvec(nx[ii+1], workspace.res_b+ii, 0);
616 printf("\nres_m_lb\n");
617 for(ii=0; ii<=N; ii++)
618 s_print_e_tran_strvec(nb[ii], workspace.res_m_lb+ii, 0);
619 printf("\nres_m_ub\n");
620 for(ii=0; ii<=N; ii++)
621 s_print_e_tran_strvec(nb[ii], workspace.res_m_ub+ii, 0);
622 printf("\nres_m_lg\n");
623 for(ii=0; ii<=N; ii++)
624 s_print_e_tran_strvec(ng[ii], workspace.res_m_lg+ii, 0);
625 printf("\nres_m_ug\n");
626 for(ii=0; ii<=N; ii++)
627 s_print_e_tran_strvec(ng[ii], workspace.res_m_ug+ii, 0);
628 printf("\nres_d_lb\n");
629 for(ii=0; ii<=N; ii++)
630 s_print_e_tran_strvec(nb[ii], workspace.res_d_lb+ii, 0);
631 printf("\nres_d_ub\n");
632 for(ii=0; ii<=N; ii++)
633 s_print_e_tran_strvec(nb[ii], workspace.res_d_ub+ii, 0);
634 printf("\nres_d_lg\n");
635 for(ii=0; ii<=N; ii++)
636 s_print_e_tran_strvec(ng[ii], workspace.res_d_lg+ii, 0);
637 printf("\nres_d_ug\n");
638 for(ii=0; ii<=N; ii++)
639 s_print_e_tran_strvec(ng[ii], workspace.res_d_ug+ii, 0);
640 printf("\nres_mu\n");
641 printf("\n%e\n\n", workspace.res_mu);
642#endif
643
644 printf("\nipm iter = %d\n", workspace.iter);
645 printf("\nalpha_aff\tmu_aff\t\tsigma\t\talpha\t\tmu\n");
646 s_print_e_tran_mat(5, workspace.iter, workspace.stat, 5);
647
648 printf("\nocp ipm time = %e [s]\n\n", time_ocp_ipm);
649
650/************************************************
651* free memory
652************************************************/
653
654 s_free(A);
655 s_free(B);
656 s_free(b);
657 s_free(x0);
658 s_free(Q);
659 s_free(R);
660 s_free(S);
661 s_free(q);
662 s_free(r);
663 s_free(r0);
664 int_free(idxb0);
665 s_free(d_lb0);
666 s_free(d_ub0);
667 int_free(idxb1);
668 s_free(d_lb1);
669 s_free(d_ub1);
670 int_free(idxbN);
671 s_free(d_lbN);
672 s_free(d_ubN);
673 s_free(C0);
674 s_free(D0);
675 s_free(d_lg0);
676 s_free(d_ug0);
677 s_free(C1);
678 s_free(D1);
679 s_free(d_lg1);
680 s_free(d_ug1);
681 s_free(CN);
682 s_free(DN);
683 s_free(d_lgN);
684 s_free(d_ugN);
685
686 free(qp_mem);
687 free(qp_sol_mem);
688 free(ipm_mem);
689
690/************************************************
691* return
692************************************************/
693
694 return 0;
695
696 }