1 /* glpapi10.c (solution checking routines) */
3 /***********************************************************************
4 * This code is part of GLPK (GNU Linear Programming Kit).
6 * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
7 * 2009, 2010 Andrew Makhorin, Department for Applied Informatics,
8 * Moscow Aviation Institute, Moscow, Russia. All rights reserved.
9 * E-mail: <mao@gnu.org>.
11 * GLPK is free software: you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
16 * GLPK is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
19 * License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with GLPK. If not, see <http://www.gnu.org/licenses/>.
23 ***********************************************************************/
27 void _glp_check_kkt(glp_prob *P, int sol, int cond, double *_ae_max,
28 int *_ae_ind, double *_re_max, int *_re_ind)
29 { /* check feasibility and optimality conditions */
35 int i, j, ae_ind, re_ind;
36 double e, sp, sn, t, ae_max, re_max;
37 if (!(sol == GLP_SOL || sol == GLP_IPT || sol == GLP_MIP))
38 xerror("glp_check_kkt: sol = %d; invalid solution indicator\n",
40 if (!(cond == GLP_KKT_PE || cond == GLP_KKT_PB ||
41 cond == GLP_KKT_DE || cond == GLP_KKT_DB ||
43 xerror("glp_check_kkt: cond = %d; invalid condition indicator "
45 ae_max = re_max = 0.0;
47 if (cond == GLP_KKT_PE)
48 { /* xR - A * xS = 0 */
49 for (i = 1; i <= m; i++)
55 else if (sol == GLP_IPT)
57 else if (sol == GLP_MIP)
61 if (t >= 0.0) sp += t; else sn -= t;
62 for (aij = row->ptr; aij != NULL; aij = aij->r_next)
64 /* t := - a[i,j] * xS[j] */
66 t = - aij->val * col->prim;
67 else if (sol == GLP_IPT)
68 t = - aij->val * col->pval;
69 else if (sol == GLP_MIP)
70 t = - aij->val * col->mipx;
73 if (t >= 0.0) sp += t; else sn -= t;
78 ae_max = e, ae_ind = i;
82 re_max = e, re_ind = i;
85 else if (cond == GLP_KKT_PB)
86 { /* lR <= xR <= uR */
87 for (i = 1; i <= m; i++)
92 else if (sol == GLP_IPT)
94 else if (sol == GLP_MIP)
98 /* check lower bound */
99 if (row->type == GLP_LO || row->type == GLP_DB ||
102 { /* absolute error */
105 ae_max = e, ae_ind = i;
107 e /= (1.0 + fabs(row->lb));
109 re_max = e, re_ind = i;
112 /* check upper bound */
113 if (row->type == GLP_UP || row->type == GLP_DB ||
116 { /* absolute error */
119 ae_max = e, ae_ind = i;
121 e /= (1.0 + fabs(row->ub));
123 re_max = e, re_ind = i;
128 for (j = 1; j <= n; j++)
133 else if (sol == GLP_IPT)
135 else if (sol == GLP_MIP)
139 /* check lower bound */
140 if (col->type == GLP_LO || col->type == GLP_DB ||
143 { /* absolute error */
146 ae_max = e, ae_ind = m+j;
148 e /= (1.0 + fabs(col->lb));
150 re_max = e, re_ind = m+j;
153 /* check upper bound */
154 if (col->type == GLP_UP || col->type == GLP_DB ||
157 { /* absolute error */
160 ae_max = e, ae_ind = m+j;
162 e /= (1.0 + fabs(col->ub));
164 re_max = e, re_ind = m+j;
169 else if (cond == GLP_KKT_DE)
170 { /* A' * (lambdaR - cR) + (lambdaS - cS) = 0 */
171 for (j = 1; j <= n; j++)
174 /* t := lambdaS[j] - cS[j] */
176 t = col->dual - col->coef;
177 else if (sol == GLP_IPT)
178 t = col->dval - col->coef;
181 if (t >= 0.0) sp += t; else sn -= t;
182 for (aij = col->ptr; aij != NULL; aij = aij->c_next)
184 /* t := a[i,j] * (lambdaR[i] - cR[i]) */
186 t = aij->val * row->dual;
187 else if (sol == GLP_IPT)
188 t = aij->val * row->dval;
191 if (t >= 0.0) sp += t; else sn -= t;
196 ae_max = e, ae_ind = m+j;
198 e /= (1.0 + sp + sn);
200 re_max = e, re_ind = m+j;
203 else if (cond == GLP_KKT_DB)
204 { /* check lambdaR */
205 for (i = 1; i <= m; i++)
207 /* t := lambdaR[i] */
210 else if (sol == GLP_IPT)
215 if (P->dir == GLP_MIN)
217 else if (P->dir == GLP_MAX)
221 /* check for positivity */
222 if (row->type == GLP_FR || row->type == GLP_LO)
226 ae_max = re_max = e, ae_ind = re_ind = i;
229 /* check for negativity */
230 if (row->type == GLP_FR || row->type == GLP_UP)
234 ae_max = re_max = e, ae_ind = re_ind = i;
239 for (j = 1; j <= n; j++)
241 /* t := lambdaS[j] */
244 else if (sol == GLP_IPT)
249 if (P->dir == GLP_MIN)
251 else if (P->dir == GLP_MAX)
255 /* check for positivity */
256 if (col->type == GLP_FR || col->type == GLP_LO)
260 ae_max = re_max = e, ae_ind = re_ind = m+j;
263 /* check for negativity */
264 if (col->type == GLP_FR || col->type == GLP_UP)
268 ae_max = re_max = e, ae_ind = re_ind = m+j;
274 xassert(cond != cond);
275 if (_ae_max != NULL) *_ae_max = ae_max;
276 if (_ae_ind != NULL) *_ae_ind = ae_ind;
277 if (_re_max != NULL) *_re_max = re_max;
278 if (_re_ind != NULL) *_re_ind = re_ind;