1 /**
2 * @brief Convex Quadratic Programming library
3 *
4 * From:
5 * http://ra.uni-trier.de/~huebner/software.html
6 *
7 * ----------------------------------------------------------------------
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * ----------------------------------------------------------------------
22 *
23 * @author Ewgenij Hübner
24 *
25 * $$
26 */
27
28 #include <gsl/gsl_math.h>
29 #include <gsl/gsl_vector.h>
30 #include <gsl/gsl_matrix.h>
31 #include <gsl/gsl_blas.h>
32 #include <gsl/gsl_permutation.h>
33 #include <gsl/gsl_linalg.h>
34
35 #include "gsl_cqp.h"
36 #include "initial_point.h"
37
38 static void
39 print_vectors(const gsl_vector*,const gsl_vector*,const gsl_vector*,const gsl_vector*);
40
41 static double
42 compute_gap_infeasible_points(const gsl_cqp_data * cqp, const gsl_vector *x, const gsl_vector *y, const gsl_vector *z);
43
44
45 static int
46 compute_residuals(const gsl_cqp_data * cqp, const gsl_vector *x, const gsl_vector *y, const gsl_vector *z, const gsl_vector *s,
47 gsl_vector *r);
48
49 static int
50 build_kkt_matrix(const gsl_cqp_data * cqp, const gsl_vector *z, const gsl_vector *s, gsl_matrix *kkt_matrix);
51
52 double
53 step_length(const gsl_vector *s, const gsl_vector *z, const gsl_vector *delta_s, const gsl_vector *delta_z);
54
55 double
56 gsl_vector_max_norm(const gsl_vector *v);
57
58 double
59 gsl_matrix_max_norm(const gsl_matrix *M);
60
61 typedef struct
62 {
63
64 size_t n; /* dimension of the problem*/
65 size_t me; /* number of the equality constraints*/
66 size_t mi; /* number of the inequality constraints */
67 gsl_vector *s; /* Slack vector for the constrain: Cx+s = d */
68
69 gsl_matrix *kkt_matrix;
70 gsl_vector *r; /* the vector of the right-hand side in the kkt-system: r=(r_Q,r_A,r_C) */
71
72 double tau; /* a constant for the Mehrotra's heuristic */
73
74 /* gondzio's parameters */
75 size_t k_max; /*maximal number of corrections */
76 double beta_min, beta_max; /* relatibe threhold values for outlier compl. products */
77 double delta_alpha; /* the required increas of stepsize */
78 double gamma; /* the minimum acceptable increase of stepsize */
79
80 double data_norm; /* norm of the problem data */
81
82 }
83 mg_pdip_state;
84
85 static int
mg_pdip_alloc(void * vstate,size_t n,size_t me,size_t mi)86 mg_pdip_alloc (void *vstate, size_t n, size_t me, size_t mi)
87 {
88 mg_pdip_state * state = (mg_pdip_state *) vstate;
89
90 state->s = gsl_vector_alloc(mi);
91 if(state->s == 0)
92 {
93 GSL_ERROR_VAL ("failed to initialize space for the slack vector s", GSL_ENOMEM, 0);
94 }
95
96 state->kkt_matrix = gsl_matrix_calloc(n+me+mi, n+me+mi);
97 if(state->kkt_matrix == 0)
98 {
99 gsl_vector_free(state->s);
100 GSL_ERROR_VAL ("failed to initialize space for the KKT-Matrix", GSL_ENOMEM, 0);
101 }
102
103 state->r = gsl_vector_alloc(state->kkt_matrix->size1);
104 if(state->r == 0)
105 {
106 gsl_matrix_free(state->kkt_matrix);
107 gsl_vector_free(state->s);
108 GSL_ERROR_VAL ("failed to initialize space for right-hand side of the KKT-System", GSL_ENOMEM, 0);
109 }
110
111 return GSL_SUCCESS;
112 }
113
114 static int
mg_pdip_set(void * vstate,const gsl_cqp_data * cqp,gsl_vector * x,gsl_vector * y,gsl_vector * z,double * gap,double * residuals_norm,double * data_norm,double * infeasibility,double * infeasibility_min)115 mg_pdip_set (void *vstate, const gsl_cqp_data *cqp, gsl_vector *x, gsl_vector *y, gsl_vector *z,
116 double *gap, double *residuals_norm, double *data_norm, double *infeasibility, double *infeasibility_min)
117 {
118 int status;
119 size_t i, j, debug=0;
120
121
122 mg_pdip_state *state = (mg_pdip_state *) vstate;
123
124 /* Initial points */
125 if( cqp->A->size1 != 0 )
126 status = pdip_initial_point_feasible_x(cqp->A, cqp->b, x);
127 else
128 gsl_vector_set_zero(x);
129
130 status = pdip_initial_point_feasible_s(cqp->C, cqp->d, x, state->s);
131 if( cqp->A->size1 != 0 )
132 status = pdip_initial_point_y(cqp->Q, cqp->q, cqp->A, x, y);
133 status = pdip_initial_point_z(z);
134 status = pdip_initial_point_strict_feasible(z, state->s);
135
136
137 /* Dualtity gap */
138 status = gsl_blas_ddot(z, state->s, gap);
139 *gap /= (double) cqp->C->size1;
140
141
142 status = build_kkt_matrix(cqp, z, state->s, state->kkt_matrix);
143
144
145
146 state->tau = 3.0;
147
148 /* for the convergence conditions */
149 /* data_norm = ||Q,A,C,q,b,d||_{infinity} */
150 *data_norm = gsl_matrix_max_norm(cqp->Q);
151
152 if( cqp->A->size1 != 0 )
153 *data_norm = GSL_MAX_DBL(*data_norm, gsl_matrix_max_norm(cqp->A));
154
155 *data_norm = GSL_MAX_DBL(*data_norm, gsl_matrix_max_norm(cqp->C));
156
157 *data_norm = GSL_MAX_DBL(*data_norm, gsl_vector_max_norm(cqp->q));
158
159 if( cqp->A->size1 != 0 )
160 *data_norm = GSL_MAX_DBL(*data_norm, gsl_vector_max_norm(cqp->b));
161
162 *data_norm = GSL_MAX_DBL(*data_norm, gsl_vector_max_norm(cqp->d));
163
164 state->data_norm = *data_norm;
165
166 /* ||r||_{infinity}=||r_Q, r_A, r_C||_{infinity} */
167 status = compute_residuals(cqp, x, y, z, state->s, state->r);
168 *residuals_norm = gsl_vector_max_norm(state->r);
169
170
171
172 *infeasibility = (*residuals_norm+compute_gap_infeasible_points(cqp, x, y, z))/(state->data_norm);
173 *infeasibility_min = *infeasibility;
174
175 /* Gondzio's paameters */
176 state->k_max = 0;
177 state->beta_min = 0.1;
178 state->beta_max = 10.0;
179 state->delta_alpha = 0.1;
180 state->gamma = 0.1;
181
182 if(debug)
183 {
184 printf("\nStart points:\n");
185 print_vectors(x, y, z, state->s);
186 printf("\nDuality gap: %e\n",*gap);
187
188 printf("\nKKT-matrix:\n");
189 for(i=0; i<state->kkt_matrix->size1; i++)
190 {
191 for(j=0; j<state->kkt_matrix->size2; j++)
192 printf("%4.2f ",gsl_matrix_get(state->kkt_matrix,i,j));
193 printf("\n");
194 }
195 printf("\n");
196 }
197
198 return GSL_SUCCESS;
199 }
200
201
202 static int
mg_pdip_iterate(void * vstate,const gsl_cqp_data * cqp,gsl_vector * x,gsl_vector * y,gsl_vector * z,double * gap,double * residuals_norm,double * infeasibility,double * infeasibility_min)203 mg_pdip_iterate (void *vstate, const gsl_cqp_data *cqp, gsl_vector *x, gsl_vector *y, gsl_vector *z,
204 double *gap, double *residuals_norm, double *infeasibility, double *infeasibility_min)
205 {
206 size_t i, j, debug=0;
207 int status, signum;
208 double sigma, alpha, alpha_gondzio;
209 double tmp_v, tmp_vt, tmp_d;
210
211 gsl_vector_view r_block, delta_block;
212
213 mg_pdip_state *state = (mg_pdip_state *) vstate;
214
215 gsl_permutation * p;
216
217 gsl_vector * delta;
218 gsl_vector * delta_s;
219
220 gsl_vector * r_zs;
221
222 gsl_vector * delta_gondzio;
223 gsl_vector * delta_s_gondzio;
224
225
226 p = gsl_permutation_alloc(state->kkt_matrix->size1);
227 if(p == 0)
228 {
229 GSL_ERROR_VAL ("failed to initialize space for permutation vector", GSL_ENOMEM, 0);
230 }
231
232 delta = gsl_vector_alloc(state->kkt_matrix->size2);
233 if(delta == 0)
234 {
235 gsl_permutation_free(p);
236 GSL_ERROR_VAL ("failed to initialize space for predictor step", GSL_ENOMEM, 0);
237 }
238 delta_gondzio = gsl_vector_alloc(state->kkt_matrix->size2);
239 if(delta_gondzio == 0)
240 {
241 gsl_vector_free(delta);
242 gsl_permutation_free(p);
243 GSL_ERROR_VAL ("failed to initialize space for predictor step", GSL_ENOMEM, 0);
244 }
245
246 delta_s_gondzio = gsl_vector_alloc(z->size);
247 if(delta_s_gondzio == 0)
248 {
249 gsl_vector_free(delta_gondzio);
250 gsl_vector_free(delta);
251 gsl_permutation_free(p);
252 GSL_ERROR_VAL ("failed to initialize space for LM s", GSL_ENOMEM, 0);
253 }
254
255 delta_s = gsl_vector_alloc(z->size);
256 if(delta_s == 0)
257 {
258 gsl_vector_free(delta_s_gondzio);
259 gsl_vector_free(delta_gondzio);
260 gsl_vector_free(delta);
261 gsl_permutation_free(p);
262 GSL_ERROR_VAL ("failed to initialize space for LM s", GSL_ENOMEM, 0);
263 }
264
265 r_zs = gsl_vector_alloc(z->size);
266 if(r_zs == 0)
267 {
268 gsl_vector_free(delta_s);
269 gsl_vector_free(delta_s_gondzio);
270 gsl_vector_free(delta_gondzio);
271 gsl_vector_free(delta);
272 gsl_permutation_free(p);
273 GSL_ERROR_VAL ("failed to initialize space for LM s", GSL_ENOMEM, 0);
274 }
275
276 /* the right-hand side of the KKT-system: r = -(r_Q, r_A, r_C+Z^{-1}*r_zs) */
277 /* the vecors of variables: delta = (delta_x, -delta_y, -delta_z) */
278 /* delta_s for the slack variable s: delta_s = Z^{-1}(-r_zs - S*delta_z) */
279
280 /********* Predictor Step ******************/
281 /* in the predictor step: r_zs = ZSe */
282 r_block = gsl_vector_subvector(state->r, cqp->Q->size1+cqp->A->size1, cqp->C->size1);
283 status = gsl_blas_daxpy(1.0, state->s, &r_block.vector);
284 gsl_blas_dscal(-1.0, state->r);
285
286 /* solve the KKT-system: */
287 /* evaluate the LU-decomposition of the KKT-matrix*/
288 status = gsl_linalg_LU_decomp(state->kkt_matrix, p, &signum);
289 /* find the predictor step */
290 status = gsl_linalg_LU_solve(state->kkt_matrix, p, state->r, delta);
291
292 for(i=0; i<delta_s->size; i++)
293 {
294 /* find delta_s for the slack variable s: delta_s = Z^{-1}(-r_zs - S*delta_z) */
295 gsl_vector_set(delta_s, i, gsl_vector_get(state->s,i)*
296 (gsl_vector_get(delta,cqp->Q->size2+cqp->A->size1+i)/gsl_vector_get(z,i)-1.0));
297
298 }
299
300 /* find the stepsize of the predictor step */
301 delta_block = gsl_vector_subvector(delta, cqp->Q->size1+cqp->A->size1, cqp->C->size1);
302 alpha = step_length(state->s, z, delta_s, &delta_block.vector);
303
304
305 if(debug)
306 {
307 printf("\n *** Predictor Step ***\n");
308 printf("\nthe right-hand side of the KKT-system:\n");
309 for(i=0; i<state->r->size; i++)
310 printf("r[%d]=%f ",(int)i,gsl_vector_get(state->r,i));
311 printf("\n");
312 printf("\nsolution (delta_x,-delta_y,-delta_z):\n");
313 for(i=0; i<delta->size; i++)
314 printf("%6.3f ",gsl_vector_get(delta,i));
315 printf("\n");
316 printf("\ndelta_s\n");
317 for(i=0; i<delta_s->size; i++)
318 printf("%6.3f ",gsl_vector_get(delta_s,i));
319 printf("\n");
320 printf("the stepsize for the predictor step=%f\n",alpha);
321 }
322
323
324
325 /************ Evaluation of the centering parameter sigma ***************/
326 /* sigma = (gap_aff/gap)^tau */
327 sigma = 0.0;
328 for(i=0; i<z->size; i++)
329 {
330 sigma += (gsl_vector_get(z,i) - alpha*gsl_vector_get(delta, cqp->Q->size2+cqp->A->size1+i))*
331 (gsl_vector_get(state->s,i) + alpha*gsl_vector_get(delta_s,i));
332 }
333 sigma /= (cqp->C->size1*(*gap));
334 sigma = pow(sigma, state->tau);
335
336 if(debug)
337 printf("the centering parameter sigma =%f\n",sigma);
338
339
340 /************ Corrector Step ******************/
341
342 /* modify the right-hand side of the kkt-system in oder to find the Mehrotra's corrector step */
343
344 r_block = gsl_vector_subvector(state->r, cqp->Q->size1+cqp->A->size1, cqp->C->size1);
345 for(i=0; i<cqp->C->size1; i++)
346 {
347 tmp_d = -sigma*(*gap)-gsl_vector_get(delta, cqp->Q->size2+cqp->A->size1+i)*gsl_vector_get(delta_s, i);
348 gsl_vector_set(r_zs, i, gsl_vector_get(z,i)*gsl_vector_get(state->s,i)+tmp_d);
349 gsl_vector_set(&r_block.vector, i, gsl_vector_get(&r_block.vector, i)-tmp_d/gsl_vector_get(z,i));
350 }
351
352 /* find the corrector step */
353 status = gsl_linalg_LU_solve(state->kkt_matrix, p, state->r, delta);
354
355
356 for(i=0; i<delta_s->size; i++)
357 {
358 /* delta_s = Z^{-1}*(-r_zs-S*delta_z) */
359 gsl_vector_set(delta_s, i, (-gsl_vector_get(r_zs,i)+gsl_vector_get(delta,cqp->Q->size2+cqp->A->size1+i)
360 *gsl_vector_get(state->s, i))/gsl_vector_get(z,i));
361 }
362
363 /* evaluate the stepsize */
364 delta_block = gsl_vector_subvector(delta, cqp->Q->size1+cqp->A->size1, cqp->C->size1);
365 alpha = step_length(state->s, z, delta_s, &delta_block.vector);
366
367 if(debug)
368 {
369 printf("\n *** Corrector Step ***\n");
370 printf("the right-hand side:\n");
371 for(i=0; i<state->r->size; i++)
372 printf("r[%d]=%f ",(int)i,gsl_vector_get(state->r,i));
373 printf("\n");
374 for(i=0; i<delta->size; i++)
375 printf("%6.3f ",gsl_vector_get(delta,i));
376 printf("\n");
377 printf("\ndelta_s\n");
378 for(i=0; i<delta_s->size; i++)
379 printf("%6.3f ",gsl_vector_get(delta_s,i));
380 printf("\n");
381 printf("the stepsize for the corrector step=%f\n",alpha);
382 }
383
384
385 /* Gondzio's centrality correction steps */
386
387 i=0;
388 while(i<state->k_max)
389 {
390
391 alpha_gondzio = GSL_MIN_DBL(alpha+state->delta_alpha, 1.0);
392 r_block = gsl_vector_subvector(state->r, cqp->Q->size1+cqp->A->size1, cqp->C->size1);
393
394 for(j=0; j<z->size; j++)
395 {
396 tmp_v = (gsl_vector_get(z,j)-alpha_gondzio*gsl_vector_get(delta,cqp->Q->size1+cqp->A->size1+j))*
397 (gsl_vector_get(state->s,j)+alpha_gondzio*gsl_vector_get(delta_s,j));
398 tmp_vt = GSL_MIN_DBL(GSL_MAX_DBL(tmp_v,state->beta_min*sigma*(*gap)),state->beta_max*sigma*(*gap));
399 gsl_vector_set(r_zs, j, gsl_vector_get(r_zs,j)-(tmp_vt-tmp_v));
400 gsl_vector_set(&r_block.vector, j, gsl_vector_get(&r_block.vector,j)+(tmp_vt-tmp_v)/gsl_vector_get(z,j));
401 }
402
403 status = gsl_linalg_LU_solve(state->kkt_matrix, p, state->r, delta_gondzio);
404 for(j=0; j<delta_s->size; j++)
405 {
406 gsl_vector_set(delta_s_gondzio, j, (-gsl_vector_get(r_zs,j)+gsl_vector_get(delta_gondzio,cqp->Q->size2+cqp->A->size1+j)
407 *gsl_vector_get(state->s, j))/gsl_vector_get(z,j));
408 }
409
410 /* evaluate the stepsize */
411 delta_block = gsl_vector_subvector(delta_gondzio, cqp->Q->size1+cqp->A->size1, cqp->C->size1);
412 alpha_gondzio = step_length(state->s, z, delta_s, &delta_block.vector);
413
414 if(alpha_gondzio >= alpha+state->gamma*state->delta_alpha)
415 {
416 i++;
417 alpha = alpha_gondzio;
418 status = gsl_blas_dcopy(delta_gondzio, delta);
419 status = gsl_blas_dcopy(delta_s_gondzio, delta_s);
420 }
421 else
422 break;
423
424 }
425
426 /* heuristic for step length */
427 alpha = GSL_MIN_DBL(0.995*alpha, 1.0);
428
429 /* Update */
430 /* x^k = x^k + alpha*delta_x */
431 delta_block = gsl_vector_subvector(delta, 0, cqp->Q->size1);
432 status = gsl_blas_daxpy(alpha, &delta_block.vector, x);
433
434 /* y^k = y^k - alpha*(-delta_y) */
435 if( y != 0 ) {
436 delta_block = gsl_vector_subvector(delta, cqp->Q->size1, cqp->A->size1);
437 status = gsl_blas_daxpy(-alpha, &delta_block.vector, y);
438 }
439
440 /* z^k = z^k - alpha*(-delta_z) */
441 delta_block = gsl_vector_subvector(delta, cqp->Q->size1+cqp->A->size1, cqp->C->size1);
442 status = gsl_blas_daxpy(-alpha, &delta_block.vector, z);
443
444 /* s^k = s^k + alpha*(delta_s) */
445 status = gsl_blas_daxpy(alpha, delta_s, state->s);
446
447
448 /* duality gap */
449 status = gsl_blas_ddot(z, state->s, gap);
450 *gap /= cqp->C->size1;
451
452 /* data for the next iteration */
453 status = compute_residuals(cqp, x, y, z, state->s, state->r);
454 *residuals_norm = gsl_vector_max_norm(state->r);
455
456 status = build_kkt_matrix(cqp, z, state->s, state->kkt_matrix);
457
458 /* for the infeasibility test */
459 *infeasibility = (*residuals_norm+compute_gap_infeasible_points(cqp, x, y, z))/(state->data_norm);
460 *infeasibility_min = GSL_MIN_DBL(*infeasibility, *infeasibility_min);
461
462
463 if(debug)
464 {
465 printf("current iteration points\n");
466 print_vectors(x, y, z, state->s);
467
468 printf("\nduality gap: %e\n",*gap);
469 }
470
471 gsl_permutation_free(p);
472 gsl_vector_free(delta);
473 gsl_vector_free(delta_gondzio);
474 gsl_vector_free(delta_s_gondzio);
475 gsl_vector_free(delta_s);
476 gsl_vector_free(r_zs);
477
478
479 return GSL_SUCCESS;
480 }
481
482 static void
mg_pdip_free(void * vstate)483 mg_pdip_free (void *vstate)
484 {
485 mg_pdip_state *state = (mg_pdip_state *) vstate;
486
487 gsl_vector_free(state->s);
488 gsl_matrix_free(state->kkt_matrix);
489 gsl_vector_free(state->r);
490 }
491
492 /*
493 static int
494 mg_pdip_restart (void *vstate)
495 {
496 mg_pdip_state *state = (mg_pdip_state *) vstate;
497
498 return GSL_SUCCESS;
499 }
500 */
501
502
503
504 static int
compute_residuals(const gsl_cqp_data * cqp,const gsl_vector * x,const gsl_vector * y,const gsl_vector * z,const gsl_vector * s,gsl_vector * r)505 compute_residuals(const gsl_cqp_data * cqp, const gsl_vector *x, const gsl_vector *y, const gsl_vector *z, const gsl_vector *s,
506 gsl_vector *r)
507 {
508
509 int status;
510 gsl_vector_view r_block;
511
512 /*gsl_cqp_geconstraints * constraints = (gsl_cqp_geconstraints *) cqp->constraints;*/
513
514 /* r_Q=Qx+q-A^ty-C^tz */
515 r_block = gsl_vector_subvector(r, 0, cqp->Q->size1);
516 status = gsl_blas_dcopy(cqp->q, &r_block.vector);
517 status = gsl_blas_dsymv(CblasUpper, 1.0, cqp->Q, x, 1.0, &r_block.vector);
518 /*status = gsl_blas_dgemv(CblasNoTrans, 1.0, cqp->Q, x, 1.0, r_Q);*/
519 if( cqp->A->size1 != 0 )
520 status = gsl_blas_dgemv(CblasTrans, -1.0, cqp->A, y, 1.0, &r_block.vector);
521 status = gsl_blas_dgemv(CblasTrans, -1.0, cqp->C, z, 1.0, &r_block.vector);
522
523 /* r_A=Ax-b */
524 if( cqp->A->size1 != 0 ) {
525 r_block = gsl_vector_subvector(r, cqp->Q->size1, cqp->A->size1);
526 status = gsl_blas_dcopy(cqp->b, &r_block.vector);
527 status = gsl_blas_dgemv(CblasNoTrans, 1.0, cqp->A, x, -1.0, &r_block.vector);
528 }
529
530 /* r_C=Cx-s-d */
531 r_block = gsl_vector_subvector(r, cqp->Q->size1+cqp->A->size1, cqp->C->size1);
532 status = gsl_blas_dcopy(s, &r_block.vector);
533 status = gsl_blas_daxpy(1.0, cqp->d, &r_block.vector);
534 status = gsl_blas_dgemv(CblasNoTrans, 1.0, cqp->C, x, -1.0, &r_block.vector);
535
536 return GSL_SUCCESS;
537 }
538
539 static int
build_kkt_matrix(const gsl_cqp_data * cqp,const gsl_vector * z,const gsl_vector * s,gsl_matrix * kkt_matrix)540 build_kkt_matrix(const gsl_cqp_data * cqp, const gsl_vector *z, const gsl_vector *s, gsl_matrix * kkt_matrix)
541 {
542 size_t i;
543
544 int status;
545
546 gsl_matrix_view kkt_block;
547
548
549 /*KKT - Matrix
550
551 |Q A^t C^t |
552 kkt_matrix =|A 0 0 |
553 |C 0 -Z^{-1}S|
554
555 */
556 /* 1. Block */
557 kkt_block = gsl_matrix_submatrix(kkt_matrix, 0, 0, cqp->Q->size1, cqp->Q->size2);
558 status = gsl_matrix_memcpy(&kkt_block.matrix, cqp->Q);
559
560 /* 2. Block */
561 if( cqp->A->size1 != 0 ) {
562 kkt_block = gsl_matrix_submatrix(kkt_matrix, 0, cqp->Q->size2, cqp->A->size2, cqp->A->size1);
563 status = gsl_matrix_transpose_memcpy(&kkt_block.matrix, cqp->A);
564 }
565
566 /* 3. Block */
567 kkt_block = gsl_matrix_submatrix(kkt_matrix, 0, cqp->Q->size2+cqp->A->size1, cqp->C->size2, cqp->C->size1);
568 status = gsl_matrix_transpose_memcpy(&kkt_block.matrix, cqp->C);
569
570 /* 4. Block */
571 if( cqp->A->size1 != 0 ) {
572 kkt_block = gsl_matrix_submatrix(kkt_matrix, cqp->Q->size1, 0, cqp->A->size1, cqp->A->size2);
573 status = gsl_matrix_memcpy(&kkt_block.matrix, cqp->A);
574 }
575
576 /* 5. Block */
577 kkt_block = gsl_matrix_submatrix(kkt_matrix, cqp->Q->size1+cqp->A->size1, 0, cqp->C->size1, cqp->C->size2);
578 status = gsl_matrix_memcpy(&kkt_block.matrix, cqp->C);
579
580 /* Null Block */
581 kkt_block = gsl_matrix_submatrix(kkt_matrix, cqp->Q->size1, cqp->Q->size2, cqp->A->size1+cqp->C->size1, cqp->A->size1+cqp->C->size1);
582 gsl_matrix_set_zero(&kkt_block.matrix);
583
584 /* 6. Block */
585 for(i=cqp->Q->size1+cqp->A->size1; i<kkt_matrix->size1; i++)
586 {
587 gsl_matrix_set(kkt_matrix, i,i, -gsl_vector_get(s, i-(cqp->Q->size1+cqp->A->size1))/
588 gsl_vector_get(z, i-(cqp->Q->size1+cqp->A->size1)));
589 }
590
591 return GSL_SUCCESS;
592
593 }
594
595 double
step_length(const gsl_vector * s,const gsl_vector * z,const gsl_vector * delta_s,const gsl_vector * delta_z)596 step_length(const gsl_vector *s, const gsl_vector *z, const gsl_vector *delta_s, const gsl_vector *delta_z)
597 {
598 double alpha = 1.0;
599 size_t i;
600
601 for(i=0; i<delta_s->size; i++)
602 {
603 if(gsl_vector_get(delta_z,i) > 0.0)
604 alpha = GSL_MIN_DBL(alpha, gsl_vector_get(z,i)/gsl_vector_get(delta_z,i));
605
606 if(gsl_vector_get(delta_s,i) < 0.0)
607 alpha = GSL_MIN_DBL(alpha, -gsl_vector_get(s,i)/gsl_vector_get(delta_s,i));
608
609 }
610
611 return alpha;
612 }
613
614
615 static double
compute_gap_infeasible_points(const gsl_cqp_data * cqp,const gsl_vector * x,const gsl_vector * y,const gsl_vector * z)616 compute_gap_infeasible_points(const gsl_cqp_data *cqp, const gsl_vector *x, const gsl_vector *y, const gsl_vector *z)
617 {
618
619
620 double g, tmp_d;
621 int status;
622
623 gsl_vector * tmp_v = gsl_vector_alloc(cqp->q->size);
624
625 status = gsl_blas_dcopy(cqp->q, tmp_v);
626 status = gsl_blas_dsymv(CblasUpper, 1.0, cqp->Q, x, 1.0, tmp_v);
627 status = gsl_blas_ddot(x, tmp_v, &g);
628
629 if( cqp->A->size1 != 0 ) {
630 status = gsl_blas_ddot(cqp->b, y, &tmp_d);
631 g -= tmp_d;
632 }
633
634 status = gsl_blas_ddot(cqp->d, z, &tmp_d);
635 g -= tmp_d;
636
637 gsl_vector_free(tmp_v);
638
639 return g;
640 }
641
642 double
gsl_matrix_max_norm(const gsl_matrix * M)643 gsl_matrix_max_norm(const gsl_matrix *M)
644 {
645 size_t i,j;
646 double max_norm = 0.0;
647
648 for(i=0; i<M->size1; i++)
649 for(j=0; j<M->size2; j++)
650 max_norm = GSL_MAX_DBL(max_norm, fabs(gsl_matrix_get(M, i, j)));
651
652 return max_norm;
653
654 }
655
656 double
gsl_vector_max_norm(const gsl_vector * v)657 gsl_vector_max_norm(const gsl_vector *v)
658 {
659 size_t i;
660 double max_norm = fabs(gsl_vector_get(v,0));
661
662 for(i=1; i<v->size; i++)
663 max_norm = GSL_MAX_DBL(max_norm, fabs(gsl_vector_get(v,i)));
664
665 return max_norm;
666 }
667
668
669 static void
print_vectors(const gsl_vector * x,const gsl_vector * y,const gsl_vector * z,const gsl_vector * s)670 print_vectors(const gsl_vector * x, const gsl_vector * y, const gsl_vector * z, const gsl_vector * s)
671 {
672 size_t i;
673
674 printf("\nx[1 x %d]:\n",(int)x->size);
675 for(i=0; i<x->size; i++)
676 printf("%f ",gsl_vector_get(x,i));
677 printf("\n");
678
679 if( y != NULL ) {
680 printf("\ny[1 x %d]: (LM zu Ax=b)\n",(int)y->size);
681 for(i=0; i<y->size; i++)
682 printf("%f ",gsl_vector_get(y,i));
683 printf("\n");
684 }
685
686 printf("\nz[1 x %d]: (LM zu Cx>=d)\n",(int)z->size);
687 for(i=0; i<z->size; i++)
688 printf("%f ",gsl_vector_get(z,i));
689 printf("\n");
690
691 printf("\ns[1 x %d]: (Slack zu Cx>=d)\n",(int)s->size);
692 for(i=0; i<s->size; i++)
693 printf("%f ",gsl_vector_get(s,i));
694 printf("\n");
695
696 }
697
698
699
700 static const gsl_cqpminimizer_type mg_pdip_type = {
701 "mg_pdip", /* name of the method: Mehrotra-Gondzio primal-dual interior point method*/
702 sizeof (mg_pdip_state),
703 &mg_pdip_alloc,
704 &mg_pdip_set,
705 &mg_pdip_iterate,
706 /* &mg_pdip_restart, */
707 &mg_pdip_free
708 };
709
710 const gsl_cqpminimizer_type
711 * gsl_cqpminimizer_mg_pdip = &mg_pdip_type;
712
713