src/glpapi10.c
author Alpar Juttner <alpar@cs.elte.hu>
Mon, 06 Dec 2010 13:09:21 +0100
changeset 1 c445c931472f
permissions -rw-r--r--
Import glpk-4.45

- Generated files and doc/notes are removed
alpar@1
     1
/* glpapi10.c (solution checking routines) */
alpar@1
     2
alpar@1
     3
/***********************************************************************
alpar@1
     4
*  This code is part of GLPK (GNU Linear Programming Kit).
alpar@1
     5
*
alpar@1
     6
*  Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
alpar@1
     7
*  2009, 2010 Andrew Makhorin, Department for Applied Informatics,
alpar@1
     8
*  Moscow Aviation Institute, Moscow, Russia. All rights reserved.
alpar@1
     9
*  E-mail: <mao@gnu.org>.
alpar@1
    10
*
alpar@1
    11
*  GLPK is free software: you can redistribute it and/or modify it
alpar@1
    12
*  under the terms of the GNU General Public License as published by
alpar@1
    13
*  the Free Software Foundation, either version 3 of the License, or
alpar@1
    14
*  (at your option) any later version.
alpar@1
    15
*
alpar@1
    16
*  GLPK is distributed in the hope that it will be useful, but WITHOUT
alpar@1
    17
*  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
alpar@1
    18
*  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
alpar@1
    19
*  License for more details.
alpar@1
    20
*
alpar@1
    21
*  You should have received a copy of the GNU General Public License
alpar@1
    22
*  along with GLPK. If not, see <http://www.gnu.org/licenses/>.
alpar@1
    23
***********************************************************************/
alpar@1
    24
alpar@1
    25
#include "glpapi.h"
alpar@1
    26
alpar@1
    27
void _glp_check_kkt(glp_prob *P, int sol, int cond, double *_ae_max,
alpar@1
    28
      int *_ae_ind, double *_re_max, int *_re_ind)
alpar@1
    29
{     /* check feasibility and optimality conditions */
alpar@1
    30
      int m = P->m;
alpar@1
    31
      int n = P->n;
alpar@1
    32
      GLPROW *row;
alpar@1
    33
      GLPCOL *col;
alpar@1
    34
      GLPAIJ *aij;
alpar@1
    35
      int i, j, ae_ind, re_ind;
alpar@1
    36
      double e, sp, sn, t, ae_max, re_max;
alpar@1
    37
      if (!(sol == GLP_SOL || sol == GLP_IPT || sol == GLP_MIP))
alpar@1
    38
         xerror("glp_check_kkt: sol = %d; invalid solution indicator\n",
alpar@1
    39
            sol);
alpar@1
    40
      if (!(cond == GLP_KKT_PE || cond == GLP_KKT_PB ||
alpar@1
    41
            cond == GLP_KKT_DE || cond == GLP_KKT_DB ||
alpar@1
    42
            cond == GLP_KKT_CS))
alpar@1
    43
         xerror("glp_check_kkt: cond = %d; invalid condition indicator "
alpar@1
    44
            "\n", cond);
alpar@1
    45
      ae_max = re_max = 0.0;
alpar@1
    46
      ae_ind = re_ind = 0;
alpar@1
    47
      if (cond == GLP_KKT_PE)
alpar@1
    48
      {  /* xR - A * xS = 0 */
alpar@1
    49
         for (i = 1; i <= m; i++)
alpar@1
    50
         {  row = P->row[i];
alpar@1
    51
            sp = sn = 0.0;
alpar@1
    52
            /* t := xR[i] */
alpar@1
    53
            if (sol == GLP_SOL)
alpar@1
    54
               t = row->prim;
alpar@1
    55
            else if (sol == GLP_IPT)
alpar@1
    56
               t = row->pval;
alpar@1
    57
            else if (sol == GLP_MIP)
alpar@1
    58
               t = row->mipx;
alpar@1
    59
            else
alpar@1
    60
               xassert(sol != sol);
alpar@1
    61
            if (t >= 0.0) sp += t; else sn -= t;
alpar@1
    62
            for (aij = row->ptr; aij != NULL; aij = aij->r_next)
alpar@1
    63
            {  col = aij->col;
alpar@1
    64
               /* t := - a[i,j] * xS[j] */
alpar@1
    65
               if (sol == GLP_SOL)
alpar@1
    66
                  t = - aij->val * col->prim;
alpar@1
    67
               else if (sol == GLP_IPT)
alpar@1
    68
                  t = - aij->val * col->pval;
alpar@1
    69
               else if (sol == GLP_MIP)
alpar@1
    70
                  t = - aij->val * col->mipx;
alpar@1
    71
               else
alpar@1
    72
                  xassert(sol != sol);
alpar@1
    73
               if (t >= 0.0) sp += t; else sn -= t;
alpar@1
    74
            }
alpar@1
    75
            /* absolute error */
alpar@1
    76
            e = fabs(sp - sn);
alpar@1
    77
            if (ae_max < e)
alpar@1
    78
               ae_max = e, ae_ind = i;
alpar@1
    79
            /* relative error */
alpar@1
    80
            e /= (1.0 + sp + sn);
alpar@1
    81
            if (re_max < e)
alpar@1
    82
               re_max = e, re_ind = i;
alpar@1
    83
         }
alpar@1
    84
      }
alpar@1
    85
      else if (cond == GLP_KKT_PB)
alpar@1
    86
      {  /* lR <= xR <= uR */
alpar@1
    87
         for (i = 1; i <= m; i++)
alpar@1
    88
         {  row = P->row[i];
alpar@1
    89
            /* t := xR[i] */
alpar@1
    90
            if (sol == GLP_SOL)
alpar@1
    91
               t = row->prim;
alpar@1
    92
            else if (sol == GLP_IPT)
alpar@1
    93
               t = row->pval;
alpar@1
    94
            else if (sol == GLP_MIP)
alpar@1
    95
               t = row->mipx;
alpar@1
    96
            else
alpar@1
    97
               xassert(sol != sol);
alpar@1
    98
            /* check lower bound */
alpar@1
    99
            if (row->type == GLP_LO || row->type == GLP_DB ||
alpar@1
   100
                row->type == GLP_FX)
alpar@1
   101
            {  if (t < row->lb)
alpar@1
   102
               {  /* absolute error */
alpar@1
   103
                  e = row->lb - t;
alpar@1
   104
                  if (ae_max < e)
alpar@1
   105
                     ae_max = e, ae_ind = i;
alpar@1
   106
                  /* relative error */
alpar@1
   107
                  e /= (1.0 + fabs(row->lb));
alpar@1
   108
                  if (re_max < e)
alpar@1
   109
                     re_max = e, re_ind = i;
alpar@1
   110
               }
alpar@1
   111
            }
alpar@1
   112
            /* check upper bound */
alpar@1
   113
            if (row->type == GLP_UP || row->type == GLP_DB ||
alpar@1
   114
                row->type == GLP_FX)
alpar@1
   115
            {  if (t > row->ub)
alpar@1
   116
               {  /* absolute error */
alpar@1
   117
                  e = t - row->ub;
alpar@1
   118
                  if (ae_max < e)
alpar@1
   119
                     ae_max = e, ae_ind = i;
alpar@1
   120
                  /* relative error */
alpar@1
   121
                  e /= (1.0 + fabs(row->ub));
alpar@1
   122
                  if (re_max < e)
alpar@1
   123
                     re_max = e, re_ind = i;
alpar@1
   124
               }
alpar@1
   125
            }
alpar@1
   126
         }
alpar@1
   127
         /* lS <= xS <= uS */
alpar@1
   128
         for (j = 1; j <= n; j++)
alpar@1
   129
         {  col = P->col[j];
alpar@1
   130
            /* t := xS[j] */
alpar@1
   131
            if (sol == GLP_SOL)
alpar@1
   132
               t = col->prim;
alpar@1
   133
            else if (sol == GLP_IPT)
alpar@1
   134
               t = col->pval;
alpar@1
   135
            else if (sol == GLP_MIP)
alpar@1
   136
               t = col->mipx;
alpar@1
   137
            else
alpar@1
   138
               xassert(sol != sol);
alpar@1
   139
            /* check lower bound */
alpar@1
   140
            if (col->type == GLP_LO || col->type == GLP_DB ||
alpar@1
   141
                col->type == GLP_FX)
alpar@1
   142
            {  if (t < col->lb)
alpar@1
   143
               {  /* absolute error */
alpar@1
   144
                  e = col->lb - t;
alpar@1
   145
                  if (ae_max < e)
alpar@1
   146
                     ae_max = e, ae_ind = m+j;
alpar@1
   147
                  /* relative error */
alpar@1
   148
                  e /= (1.0 + fabs(col->lb));
alpar@1
   149
                  if (re_max < e)
alpar@1
   150
                     re_max = e, re_ind = m+j;
alpar@1
   151
               }
alpar@1
   152
            }
alpar@1
   153
            /* check upper bound */
alpar@1
   154
            if (col->type == GLP_UP || col->type == GLP_DB ||
alpar@1
   155
                col->type == GLP_FX)
alpar@1
   156
            {  if (t > col->ub)
alpar@1
   157
               {  /* absolute error */
alpar@1
   158
                  e = t - col->ub;
alpar@1
   159
                  if (ae_max < e)
alpar@1
   160
                     ae_max = e, ae_ind = m+j;
alpar@1
   161
                  /* relative error */
alpar@1
   162
                  e /= (1.0 + fabs(col->ub));
alpar@1
   163
                  if (re_max < e)
alpar@1
   164
                     re_max = e, re_ind = m+j;
alpar@1
   165
               }
alpar@1
   166
            }
alpar@1
   167
         }
alpar@1
   168
      }
alpar@1
   169
      else if (cond == GLP_KKT_DE)
alpar@1
   170
      {  /* A' * (lambdaR - cR) + (lambdaS - cS) = 0 */
alpar@1
   171
         for (j = 1; j <= n; j++)
alpar@1
   172
         {  col = P->col[j];
alpar@1
   173
            sp = sn = 0.0;
alpar@1
   174
            /* t := lambdaS[j] - cS[j] */
alpar@1
   175
            if (sol == GLP_SOL)
alpar@1
   176
               t = col->dual - col->coef;
alpar@1
   177
            else if (sol == GLP_IPT)
alpar@1
   178
               t = col->dval - col->coef;
alpar@1
   179
            else
alpar@1
   180
               xassert(sol != sol);
alpar@1
   181
            if (t >= 0.0) sp += t; else sn -= t;
alpar@1
   182
            for (aij = col->ptr; aij != NULL; aij = aij->c_next)
alpar@1
   183
            {  row = aij->row;
alpar@1
   184
               /* t := a[i,j] * (lambdaR[i] - cR[i]) */
alpar@1
   185
               if (sol == GLP_SOL)
alpar@1
   186
                  t = aij->val * row->dual;
alpar@1
   187
               else if (sol == GLP_IPT)
alpar@1
   188
                  t = aij->val * row->dval;
alpar@1
   189
               else
alpar@1
   190
                  xassert(sol != sol);
alpar@1
   191
               if (t >= 0.0) sp += t; else sn -= t;
alpar@1
   192
            }
alpar@1
   193
            /* absolute error */
alpar@1
   194
            e = fabs(sp - sn);
alpar@1
   195
            if (ae_max < e)
alpar@1
   196
               ae_max = e, ae_ind = m+j;
alpar@1
   197
            /* relative error */
alpar@1
   198
            e /= (1.0 + sp + sn);
alpar@1
   199
            if (re_max < e)
alpar@1
   200
               re_max = e, re_ind = m+j;
alpar@1
   201
         }
alpar@1
   202
      }
alpar@1
   203
      else if (cond == GLP_KKT_DB)
alpar@1
   204
      {  /* check lambdaR */
alpar@1
   205
         for (i = 1; i <= m; i++)
alpar@1
   206
         {  row = P->row[i];
alpar@1
   207
            /* t := lambdaR[i] */
alpar@1
   208
            if (sol == GLP_SOL)
alpar@1
   209
               t = row->dual;
alpar@1
   210
            else if (sol == GLP_IPT)
alpar@1
   211
               t = row->dval;
alpar@1
   212
            else
alpar@1
   213
               xassert(sol != sol);
alpar@1
   214
            /* correct sign */
alpar@1
   215
            if (P->dir == GLP_MIN)
alpar@1
   216
               t = + t;
alpar@1
   217
            else if (P->dir == GLP_MAX)
alpar@1
   218
               t = - t;
alpar@1
   219
            else
alpar@1
   220
               xassert(P != P);
alpar@1
   221
            /* check for positivity */
alpar@1
   222
            if (row->type == GLP_FR || row->type == GLP_LO)
alpar@1
   223
            {  if (t < 0.0)
alpar@1
   224
               {  e = - t;
alpar@1
   225
                  if (ae_max < e)
alpar@1
   226
                     ae_max = re_max = e, ae_ind = re_ind = i;
alpar@1
   227
               }
alpar@1
   228
            }
alpar@1
   229
            /* check for negativity */
alpar@1
   230
            if (row->type == GLP_FR || row->type == GLP_UP)
alpar@1
   231
            {  if (t > 0.0)
alpar@1
   232
               {  e = + t;
alpar@1
   233
                  if (ae_max < e)
alpar@1
   234
                     ae_max = re_max = e, ae_ind = re_ind = i;
alpar@1
   235
               }
alpar@1
   236
            }
alpar@1
   237
         }
alpar@1
   238
         /* check lambdaS */
alpar@1
   239
         for (j = 1; j <= n; j++)
alpar@1
   240
         {  col = P->col[j];
alpar@1
   241
            /* t := lambdaS[j] */
alpar@1
   242
            if (sol == GLP_SOL)
alpar@1
   243
               t = col->dual;
alpar@1
   244
            else if (sol == GLP_IPT)
alpar@1
   245
               t = col->dval;
alpar@1
   246
            else
alpar@1
   247
               xassert(sol != sol);
alpar@1
   248
            /* correct sign */
alpar@1
   249
            if (P->dir == GLP_MIN)
alpar@1
   250
               t = + t;
alpar@1
   251
            else if (P->dir == GLP_MAX)
alpar@1
   252
               t = - t;
alpar@1
   253
            else
alpar@1
   254
               xassert(P != P);
alpar@1
   255
            /* check for positivity */
alpar@1
   256
            if (col->type == GLP_FR || col->type == GLP_LO)
alpar@1
   257
            {  if (t < 0.0)
alpar@1
   258
               {  e = - t;
alpar@1
   259
                  if (ae_max < e)
alpar@1
   260
                     ae_max = re_max = e, ae_ind = re_ind = m+j;
alpar@1
   261
               }
alpar@1
   262
            }
alpar@1
   263
            /* check for negativity */
alpar@1
   264
            if (col->type == GLP_FR || col->type == GLP_UP)
alpar@1
   265
            {  if (t > 0.0)
alpar@1
   266
               {  e = + t;
alpar@1
   267
                  if (ae_max < e)
alpar@1
   268
                     ae_max = re_max = e, ae_ind = re_ind = m+j;
alpar@1
   269
               }
alpar@1
   270
            }
alpar@1
   271
         }
alpar@1
   272
      }
alpar@1
   273
      else
alpar@1
   274
         xassert(cond != cond);
alpar@1
   275
      if (_ae_max != NULL) *_ae_max = ae_max;
alpar@1
   276
      if (_ae_ind != NULL) *_ae_ind = ae_ind;
alpar@1
   277
      if (_re_max != NULL) *_re_max = re_max;
alpar@1
   278
      if (_re_ind != NULL) *_re_ind = re_ind;
alpar@1
   279
      return;
alpar@1
   280
}
alpar@1
   281
alpar@1
   282
/* eof */