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