src/glpios02.c
author Alpar Juttner <alpar@cs.elte.hu>
Sun, 05 Dec 2010 17:35:23 +0100
changeset 2 4c8956a7bdf4
permissions -rw-r--r--
Set up CMAKE build environment
alpar@1
     1
/* glpios02.c (preprocess current subproblem) */
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 "glpios.h"
alpar@1
    26
alpar@1
    27
/***********************************************************************
alpar@1
    28
*  prepare_row_info - prepare row info to determine implied bounds
alpar@1
    29
*
alpar@1
    30
*  Given a row (linear form)
alpar@1
    31
*
alpar@1
    32
*      n
alpar@1
    33
*     sum a[j] * x[j]                                                (1)
alpar@1
    34
*     j=1
alpar@1
    35
*
alpar@1
    36
*  and bounds of columns (variables)
alpar@1
    37
*
alpar@1
    38
*     l[j] <= x[j] <= u[j]                                           (2)
alpar@1
    39
*
alpar@1
    40
*  this routine computes f_min, j_min, f_max, j_max needed to determine
alpar@1
    41
*  implied bounds.
alpar@1
    42
*
alpar@1
    43
*  ALGORITHM
alpar@1
    44
*
alpar@1
    45
*  Let J+ = {j : a[j] > 0} and J- = {j : a[j] < 0}.
alpar@1
    46
*
alpar@1
    47
*  Parameters f_min and j_min are computed as follows:
alpar@1
    48
*
alpar@1
    49
*  1) if there is no x[k] such that k in J+ and l[k] = -inf or k in J-
alpar@1
    50
*     and u[k] = +inf, then
alpar@1
    51
*
alpar@1
    52
*     f_min :=   sum   a[j] * l[j] +   sum   a[j] * u[j]
alpar@1
    53
*              j in J+               j in J-
alpar@1
    54
*                                                                    (3)
alpar@1
    55
*     j_min := 0
alpar@1
    56
*
alpar@1
    57
*  2) if there is exactly one x[k] such that k in J+ and l[k] = -inf
alpar@1
    58
*     or k in J- and u[k] = +inf, then
alpar@1
    59
*
alpar@1
    60
*     f_min :=   sum       a[j] * l[j] +   sum       a[j] * u[j]
alpar@1
    61
*              j in J+\{k}               j in J-\{k}
alpar@1
    62
*                                                                    (4)
alpar@1
    63
*     j_min := k
alpar@1
    64
*
alpar@1
    65
*  3) if there are two or more x[k] such that k in J+ and l[k] = -inf
alpar@1
    66
*     or k in J- and u[k] = +inf, then
alpar@1
    67
*
alpar@1
    68
*     f_min := -inf
alpar@1
    69
*                                                                    (5)
alpar@1
    70
*     j_min := 0
alpar@1
    71
*
alpar@1
    72
*  Parameters f_max and j_max are computed in a similar way as follows:
alpar@1
    73
*
alpar@1
    74
*  1) if there is no x[k] such that k in J+ and u[k] = +inf or k in J-
alpar@1
    75
*     and l[k] = -inf, then
alpar@1
    76
*
alpar@1
    77
*     f_max :=   sum   a[j] * u[j] +   sum   a[j] * l[j]
alpar@1
    78
*              j in J+               j in J-
alpar@1
    79
*                                                                    (6)
alpar@1
    80
*     j_max := 0
alpar@1
    81
*
alpar@1
    82
*  2) if there is exactly one x[k] such that k in J+ and u[k] = +inf
alpar@1
    83
*     or k in J- and l[k] = -inf, then
alpar@1
    84
*
alpar@1
    85
*     f_max :=   sum       a[j] * u[j] +   sum       a[j] * l[j]
alpar@1
    86
*              j in J+\{k}               j in J-\{k}
alpar@1
    87
*                                                                    (7)
alpar@1
    88
*     j_max := k
alpar@1
    89
*
alpar@1
    90
*  3) if there are two or more x[k] such that k in J+ and u[k] = +inf
alpar@1
    91
*     or k in J- and l[k] = -inf, then
alpar@1
    92
*
alpar@1
    93
*     f_max := +inf
alpar@1
    94
*                                                                    (8)
alpar@1
    95
*     j_max := 0                                                      */
alpar@1
    96
alpar@1
    97
struct f_info
alpar@1
    98
{     int j_min, j_max;
alpar@1
    99
      double f_min, f_max;
alpar@1
   100
};
alpar@1
   101
alpar@1
   102
static void prepare_row_info(int n, const double a[], const double l[],
alpar@1
   103
      const double u[], struct f_info *f)
alpar@1
   104
{     int j, j_min, j_max;
alpar@1
   105
      double f_min, f_max;
alpar@1
   106
      xassert(n >= 0);
alpar@1
   107
      /* determine f_min and j_min */
alpar@1
   108
      f_min = 0.0, j_min = 0;
alpar@1
   109
      for (j = 1; j <= n; j++)
alpar@1
   110
      {  if (a[j] > 0.0)
alpar@1
   111
         {  if (l[j] == -DBL_MAX)
alpar@1
   112
            {  if (j_min == 0)
alpar@1
   113
                  j_min = j;
alpar@1
   114
               else
alpar@1
   115
               {  f_min = -DBL_MAX, j_min = 0;
alpar@1
   116
                  break;
alpar@1
   117
               }
alpar@1
   118
            }
alpar@1
   119
            else
alpar@1
   120
               f_min += a[j] * l[j];
alpar@1
   121
         }
alpar@1
   122
         else if (a[j] < 0.0)
alpar@1
   123
         {  if (u[j] == +DBL_MAX)
alpar@1
   124
            {  if (j_min == 0)
alpar@1
   125
                  j_min = j;
alpar@1
   126
               else
alpar@1
   127
               {  f_min = -DBL_MAX, j_min = 0;
alpar@1
   128
                  break;
alpar@1
   129
               }
alpar@1
   130
            }
alpar@1
   131
            else
alpar@1
   132
               f_min += a[j] * u[j];
alpar@1
   133
         }
alpar@1
   134
         else
alpar@1
   135
            xassert(a != a);
alpar@1
   136
      }
alpar@1
   137
      f->f_min = f_min, f->j_min = j_min;
alpar@1
   138
      /* determine f_max and j_max */
alpar@1
   139
      f_max = 0.0, j_max = 0;
alpar@1
   140
      for (j = 1; j <= n; j++)
alpar@1
   141
      {  if (a[j] > 0.0)
alpar@1
   142
         {  if (u[j] == +DBL_MAX)
alpar@1
   143
            {  if (j_max == 0)
alpar@1
   144
                  j_max = j;
alpar@1
   145
               else
alpar@1
   146
               {  f_max = +DBL_MAX, j_max = 0;
alpar@1
   147
                  break;
alpar@1
   148
               }
alpar@1
   149
            }
alpar@1
   150
            else
alpar@1
   151
               f_max += a[j] * u[j];
alpar@1
   152
         }
alpar@1
   153
         else if (a[j] < 0.0)
alpar@1
   154
         {  if (l[j] == -DBL_MAX)
alpar@1
   155
            {  if (j_max == 0)
alpar@1
   156
                  j_max = j;
alpar@1
   157
               else
alpar@1
   158
               {  f_max = +DBL_MAX, j_max = 0;
alpar@1
   159
                  break;
alpar@1
   160
               }
alpar@1
   161
            }
alpar@1
   162
            else
alpar@1
   163
               f_max += a[j] * l[j];
alpar@1
   164
         }
alpar@1
   165
         else
alpar@1
   166
            xassert(a != a);
alpar@1
   167
      }
alpar@1
   168
      f->f_max = f_max, f->j_max = j_max;
alpar@1
   169
      return;
alpar@1
   170
}
alpar@1
   171
alpar@1
   172
/***********************************************************************
alpar@1
   173
*  row_implied_bounds - determine row implied bounds
alpar@1
   174
*
alpar@1
   175
*  Given a row (linear form)
alpar@1
   176
*
alpar@1
   177
*      n
alpar@1
   178
*     sum a[j] * x[j]
alpar@1
   179
*     j=1
alpar@1
   180
*
alpar@1
   181
*  and bounds of columns (variables)
alpar@1
   182
*
alpar@1
   183
*     l[j] <= x[j] <= u[j]
alpar@1
   184
*
alpar@1
   185
*  this routine determines implied bounds of the row.
alpar@1
   186
*
alpar@1
   187
*  ALGORITHM
alpar@1
   188
*
alpar@1
   189
*  Let J+ = {j : a[j] > 0} and J- = {j : a[j] < 0}.
alpar@1
   190
*
alpar@1
   191
*  The implied lower bound of the row is computed as follows:
alpar@1
   192
*
alpar@1
   193
*     L' :=   sum   a[j] * l[j] +   sum   a[j] * u[j]                (9)
alpar@1
   194
*           j in J+               j in J-
alpar@1
   195
*
alpar@1
   196
*  and as it follows from (3), (4), and (5):
alpar@1
   197
*
alpar@1
   198
*     L' := if j_min = 0 then f_min else -inf                       (10)
alpar@1
   199
*
alpar@1
   200
*  The implied upper bound of the row is computed as follows:
alpar@1
   201
*
alpar@1
   202
*     U' :=   sum   a[j] * u[j] +   sum   a[j] * l[j]               (11)
alpar@1
   203
*           j in J+               j in J-
alpar@1
   204
*
alpar@1
   205
*  and as it follows from (6), (7), and (8):
alpar@1
   206
*
alpar@1
   207
*     U' := if j_max = 0 then f_max else +inf                       (12)
alpar@1
   208
*
alpar@1
   209
*  The implied bounds are stored in locations LL and UU. */
alpar@1
   210
alpar@1
   211
static void row_implied_bounds(const struct f_info *f, double *LL,
alpar@1
   212
      double *UU)
alpar@1
   213
{     *LL = (f->j_min == 0 ? f->f_min : -DBL_MAX);
alpar@1
   214
      *UU = (f->j_max == 0 ? f->f_max : +DBL_MAX);
alpar@1
   215
      return;
alpar@1
   216
}
alpar@1
   217
alpar@1
   218
/***********************************************************************
alpar@1
   219
*  col_implied_bounds - determine column implied bounds
alpar@1
   220
*
alpar@1
   221
*  Given a row (constraint)
alpar@1
   222
*
alpar@1
   223
*           n
alpar@1
   224
*     L <= sum a[j] * x[j] <= U                                     (13)
alpar@1
   225
*          j=1
alpar@1
   226
*
alpar@1
   227
*  and bounds of columns (variables)
alpar@1
   228
*
alpar@1
   229
*     l[j] <= x[j] <= u[j]
alpar@1
   230
*
alpar@1
   231
*  this routine determines implied bounds of variable x[k].
alpar@1
   232
*
alpar@1
   233
*  It is assumed that if L != -inf, the lower bound of the row can be
alpar@1
   234
*  active, and if U != +inf, the upper bound of the row can be active.
alpar@1
   235
*
alpar@1
   236
*  ALGORITHM
alpar@1
   237
*
alpar@1
   238
*  From (13) it follows that
alpar@1
   239
*
alpar@1
   240
*     L <= sum a[j] * x[j] + a[k] * x[k] <= U
alpar@1
   241
*          j!=k
alpar@1
   242
*  or
alpar@1
   243
*
alpar@1
   244
*     L - sum a[j] * x[j] <= a[k] * x[k] <= U - sum a[j] * x[j]
alpar@1
   245
*         j!=k                                  j!=k
alpar@1
   246
*
alpar@1
   247
*  Thus, if the row lower bound L can be active, implied lower bound of
alpar@1
   248
*  term a[k] * x[k] can be determined as follows:
alpar@1
   249
*
alpar@1
   250
*     ilb(a[k] * x[k]) = min(L - sum a[j] * x[j]) =
alpar@1
   251
*                                j!=k
alpar@1
   252
*                                                                   (14)
alpar@1
   253
*                      = L - max sum a[j] * x[j]
alpar@1
   254
*                            j!=k
alpar@1
   255
*
alpar@1
   256
*  where, as it follows from (6), (7), and (8)
alpar@1
   257
*
alpar@1
   258
*                           / f_max - a[k] * u[k], j_max = 0, a[k] > 0
alpar@1
   259
*                           |
alpar@1
   260
*                           | f_max - a[k] * l[k], j_max = 0, a[k] < 0
alpar@1
   261
*     max sum a[j] * x[j] = {
alpar@1
   262
*         j!=k              | f_max,               j_max = k
alpar@1
   263
*                           |
alpar@1
   264
*                           \ +inf,                j_max != 0
alpar@1
   265
*
alpar@1
   266
*  and if the upper bound U can be active, implied upper bound of term
alpar@1
   267
*  a[k] * x[k] can be determined as follows:
alpar@1
   268
*
alpar@1
   269
*     iub(a[k] * x[k]) = max(U - sum a[j] * x[j]) =
alpar@1
   270
*                                j!=k
alpar@1
   271
*                                                                   (15)
alpar@1
   272
*                      = U - min sum a[j] * x[j]
alpar@1
   273
*                            j!=k
alpar@1
   274
*
alpar@1
   275
*  where, as it follows from (3), (4), and (5)
alpar@1
   276
*
alpar@1
   277
*                           / f_min - a[k] * l[k], j_min = 0, a[k] > 0
alpar@1
   278
*                           |
alpar@1
   279
*                           | f_min - a[k] * u[k], j_min = 0, a[k] < 0
alpar@1
   280
*     min sum a[j] * x[j] = {
alpar@1
   281
*         j!=k              | f_min,               j_min = k
alpar@1
   282
*                           |
alpar@1
   283
*                           \ -inf,                j_min != 0
alpar@1
   284
*
alpar@1
   285
*  Since
alpar@1
   286
*
alpar@1
   287
*     ilb(a[k] * x[k]) <= a[k] * x[k] <= iub(a[k] * x[k])
alpar@1
   288
*
alpar@1
   289
*  implied lower and upper bounds of x[k] are determined as follows:
alpar@1
   290
*
alpar@1
   291
*     l'[k] := if a[k] > 0 then ilb / a[k] else ulb / a[k]          (16)
alpar@1
   292
*
alpar@1
   293
*     u'[k] := if a[k] > 0 then ulb / a[k] else ilb / a[k]          (17)
alpar@1
   294
*
alpar@1
   295
*  The implied bounds are stored in locations ll and uu. */
alpar@1
   296
alpar@1
   297
static void col_implied_bounds(const struct f_info *f, int n,
alpar@1
   298
      const double a[], double L, double U, const double l[],
alpar@1
   299
      const double u[], int k, double *ll, double *uu)
alpar@1
   300
{     double ilb, iub;
alpar@1
   301
      xassert(n >= 0);
alpar@1
   302
      xassert(1 <= k && k <= n);
alpar@1
   303
      /* determine implied lower bound of term a[k] * x[k] (14) */
alpar@1
   304
      if (L == -DBL_MAX || f->f_max == +DBL_MAX)
alpar@1
   305
         ilb = -DBL_MAX;
alpar@1
   306
      else if (f->j_max == 0)
alpar@1
   307
      {  if (a[k] > 0.0)
alpar@1
   308
         {  xassert(u[k] != +DBL_MAX);
alpar@1
   309
            ilb = L - (f->f_max - a[k] * u[k]);
alpar@1
   310
         }
alpar@1
   311
         else if (a[k] < 0.0)
alpar@1
   312
         {  xassert(l[k] != -DBL_MAX);
alpar@1
   313
            ilb = L - (f->f_max - a[k] * l[k]);
alpar@1
   314
         }
alpar@1
   315
         else
alpar@1
   316
            xassert(a != a);
alpar@1
   317
      }
alpar@1
   318
      else if (f->j_max == k)
alpar@1
   319
         ilb = L - f->f_max;
alpar@1
   320
      else
alpar@1
   321
         ilb = -DBL_MAX;
alpar@1
   322
      /* determine implied upper bound of term a[k] * x[k] (15) */
alpar@1
   323
      if (U == +DBL_MAX || f->f_min == -DBL_MAX)
alpar@1
   324
         iub = +DBL_MAX;
alpar@1
   325
      else if (f->j_min == 0)
alpar@1
   326
      {  if (a[k] > 0.0)
alpar@1
   327
         {  xassert(l[k] != -DBL_MAX);
alpar@1
   328
            iub = U - (f->f_min - a[k] * l[k]);
alpar@1
   329
         }
alpar@1
   330
         else if (a[k] < 0.0)
alpar@1
   331
         {  xassert(u[k] != +DBL_MAX);
alpar@1
   332
            iub = U - (f->f_min - a[k] * u[k]);
alpar@1
   333
         }
alpar@1
   334
         else
alpar@1
   335
            xassert(a != a);
alpar@1
   336
      }
alpar@1
   337
      else if (f->j_min == k)
alpar@1
   338
         iub = U - f->f_min;
alpar@1
   339
      else
alpar@1
   340
         iub = +DBL_MAX;
alpar@1
   341
      /* determine implied bounds of x[k] (16) and (17) */
alpar@1
   342
#if 1
alpar@1
   343
      /* do not use a[k] if it has small magnitude to prevent wrong
alpar@1
   344
         implied bounds; for example, 1e-15 * x1 >= x2 + x3, where
alpar@1
   345
         x1 >= -10, x2, x3 >= 0, would lead to wrong conclusion that
alpar@1
   346
         x1 >= 0 */
alpar@1
   347
      if (fabs(a[k]) < 1e-6)
alpar@1
   348
         *ll = -DBL_MAX, *uu = +DBL_MAX; else
alpar@1
   349
#endif
alpar@1
   350
      if (a[k] > 0.0)
alpar@1
   351
      {  *ll = (ilb == -DBL_MAX ? -DBL_MAX : ilb / a[k]);
alpar@1
   352
         *uu = (iub == +DBL_MAX ? +DBL_MAX : iub / a[k]);
alpar@1
   353
      }
alpar@1
   354
      else if (a[k] < 0.0)
alpar@1
   355
      {  *ll = (iub == +DBL_MAX ? -DBL_MAX : iub / a[k]);
alpar@1
   356
         *uu = (ilb == -DBL_MAX ? +DBL_MAX : ilb / a[k]);
alpar@1
   357
      }
alpar@1
   358
      else
alpar@1
   359
         xassert(a != a);
alpar@1
   360
      return;
alpar@1
   361
}
alpar@1
   362
alpar@1
   363
/***********************************************************************
alpar@1
   364
*  check_row_bounds - check and relax original row bounds
alpar@1
   365
*
alpar@1
   366
*  Given a row (constraint)
alpar@1
   367
*
alpar@1
   368
*           n
alpar@1
   369
*     L <= sum a[j] * x[j] <= U
alpar@1
   370
*          j=1
alpar@1
   371
*
alpar@1
   372
*  and bounds of columns (variables)
alpar@1
   373
*
alpar@1
   374
*     l[j] <= x[j] <= u[j]
alpar@1
   375
*
alpar@1
   376
*  this routine checks the original row bounds L and U for feasibility
alpar@1
   377
*  and redundancy. If the original lower bound L or/and upper bound U
alpar@1
   378
*  cannot be active due to bounds of variables, the routine remove them
alpar@1
   379
*  replacing by -inf or/and +inf, respectively.
alpar@1
   380
*
alpar@1
   381
*  If no primal infeasibility is detected, the routine returns zero,
alpar@1
   382
*  otherwise non-zero. */
alpar@1
   383
alpar@1
   384
static int check_row_bounds(const struct f_info *f, double *L_,
alpar@1
   385
      double *U_)
alpar@1
   386
{     int ret = 0;
alpar@1
   387
      double L = *L_, U = *U_, LL, UU;
alpar@1
   388
      /* determine implied bounds of the row */
alpar@1
   389
      row_implied_bounds(f, &LL, &UU);
alpar@1
   390
      /* check if the original lower bound is infeasible */
alpar@1
   391
      if (L != -DBL_MAX)
alpar@1
   392
      {  double eps = 1e-3 * (1.0 + fabs(L));
alpar@1
   393
         if (UU < L - eps)
alpar@1
   394
         {  ret = 1;
alpar@1
   395
            goto done;
alpar@1
   396
         }
alpar@1
   397
      }
alpar@1
   398
      /* check if the original upper bound is infeasible */
alpar@1
   399
      if (U != +DBL_MAX)
alpar@1
   400
      {  double eps = 1e-3 * (1.0 + fabs(U));
alpar@1
   401
         if (LL > U + eps)
alpar@1
   402
         {  ret = 1;
alpar@1
   403
            goto done;
alpar@1
   404
         }
alpar@1
   405
      }
alpar@1
   406
      /* check if the original lower bound is redundant */
alpar@1
   407
      if (L != -DBL_MAX)
alpar@1
   408
      {  double eps = 1e-12 * (1.0 + fabs(L));
alpar@1
   409
         if (LL > L - eps)
alpar@1
   410
         {  /* it cannot be active, so remove it */
alpar@1
   411
            *L_ = -DBL_MAX;
alpar@1
   412
         }
alpar@1
   413
      }
alpar@1
   414
      /* check if the original upper bound is redundant */
alpar@1
   415
      if (U != +DBL_MAX)
alpar@1
   416
      {  double eps = 1e-12 * (1.0 + fabs(U));
alpar@1
   417
         if (UU < U + eps)
alpar@1
   418
         {  /* it cannot be active, so remove it */
alpar@1
   419
            *U_ = +DBL_MAX;
alpar@1
   420
         }
alpar@1
   421
      }
alpar@1
   422
done: return ret;
alpar@1
   423
}
alpar@1
   424
alpar@1
   425
/***********************************************************************
alpar@1
   426
*  check_col_bounds - check and tighten original column bounds
alpar@1
   427
*
alpar@1
   428
*  Given a row (constraint)
alpar@1
   429
*
alpar@1
   430
*           n
alpar@1
   431
*     L <= sum a[j] * x[j] <= U
alpar@1
   432
*          j=1
alpar@1
   433
*
alpar@1
   434
*  and bounds of columns (variables)
alpar@1
   435
*
alpar@1
   436
*     l[j] <= x[j] <= u[j]
alpar@1
   437
*
alpar@1
   438
*  for column (variable) x[j] this routine checks the original column
alpar@1
   439
*  bounds l[j] and u[j] for feasibility and redundancy. If the original
alpar@1
   440
*  lower bound l[j] or/and upper bound u[j] cannot be active due to
alpar@1
   441
*  bounds of the constraint and other variables, the routine tighten
alpar@1
   442
*  them replacing by corresponding implied bounds, if possible.
alpar@1
   443
*
alpar@1
   444
*  NOTE: It is assumed that if L != -inf, the row lower bound can be
alpar@1
   445
*        active, and if U != +inf, the row upper bound can be active.
alpar@1
   446
*
alpar@1
   447
*  The flag means that variable x[j] is required to be integer.
alpar@1
   448
*
alpar@1
   449
*  New actual bounds for x[j] are stored in locations lj and uj.
alpar@1
   450
*
alpar@1
   451
*  If no primal infeasibility is detected, the routine returns zero,
alpar@1
   452
*  otherwise non-zero. */
alpar@1
   453
alpar@1
   454
static int check_col_bounds(const struct f_info *f, int n,
alpar@1
   455
      const double a[], double L, double U, const double l[],
alpar@1
   456
      const double u[], int flag, int j, double *_lj, double *_uj)
alpar@1
   457
{     int ret = 0;
alpar@1
   458
      double lj, uj, ll, uu;
alpar@1
   459
      xassert(n >= 0);
alpar@1
   460
      xassert(1 <= j && j <= n);
alpar@1
   461
      lj = l[j], uj = u[j];
alpar@1
   462
      /* determine implied bounds of the column */
alpar@1
   463
      col_implied_bounds(f, n, a, L, U, l, u, j, &ll, &uu);
alpar@1
   464
      /* if x[j] is integral, round its implied bounds */
alpar@1
   465
      if (flag)
alpar@1
   466
      {  if (ll != -DBL_MAX)
alpar@1
   467
            ll = (ll - floor(ll) < 1e-3 ? floor(ll) : ceil(ll));
alpar@1
   468
         if (uu != +DBL_MAX)
alpar@1
   469
            uu = (ceil(uu) - uu < 1e-3 ? ceil(uu) : floor(uu));
alpar@1
   470
      }
alpar@1
   471
      /* check if the original lower bound is infeasible */
alpar@1
   472
      if (lj != -DBL_MAX)
alpar@1
   473
      {  double eps = 1e-3 * (1.0 + fabs(lj));
alpar@1
   474
         if (uu < lj - eps)
alpar@1
   475
         {  ret = 1;
alpar@1
   476
            goto done;
alpar@1
   477
         }
alpar@1
   478
      }
alpar@1
   479
      /* check if the original upper bound is infeasible */
alpar@1
   480
      if (uj != +DBL_MAX)
alpar@1
   481
      {  double eps = 1e-3 * (1.0 + fabs(uj));
alpar@1
   482
         if (ll > uj + eps)
alpar@1
   483
         {  ret = 1;
alpar@1
   484
            goto done;
alpar@1
   485
         }
alpar@1
   486
      }
alpar@1
   487
      /* check if the original lower bound is redundant */
alpar@1
   488
      if (ll != -DBL_MAX)
alpar@1
   489
      {  double eps = 1e-3 * (1.0 + fabs(ll));
alpar@1
   490
         if (lj < ll - eps)
alpar@1
   491
         {  /* it cannot be active, so tighten it */
alpar@1
   492
            lj = ll;
alpar@1
   493
         }
alpar@1
   494
      }
alpar@1
   495
      /* check if the original upper bound is redundant */
alpar@1
   496
      if (uu != +DBL_MAX)
alpar@1
   497
      {  double eps = 1e-3 * (1.0 + fabs(uu));
alpar@1
   498
         if (uj > uu + eps)
alpar@1
   499
         {  /* it cannot be active, so tighten it */
alpar@1
   500
            uj = uu;
alpar@1
   501
         }
alpar@1
   502
      }
alpar@1
   503
      /* due to round-off errors it may happen that lj > uj (although
alpar@1
   504
         lj < uj + eps, since no primal infeasibility is detected), so
alpar@1
   505
         adjuct the new actual bounds to provide lj <= uj */
alpar@1
   506
      if (!(lj == -DBL_MAX || uj == +DBL_MAX))
alpar@1
   507
      {  double t1 = fabs(lj), t2 = fabs(uj);
alpar@1
   508
         double eps = 1e-10 * (1.0 + (t1 <= t2 ? t1 : t2));
alpar@1
   509
         if (lj > uj - eps)
alpar@1
   510
         {  if (lj == l[j])
alpar@1
   511
               uj = lj;
alpar@1
   512
            else if (uj == u[j])
alpar@1
   513
               lj = uj;
alpar@1
   514
            else if (t1 <= t2)
alpar@1
   515
               uj = lj;
alpar@1
   516
            else
alpar@1
   517
               lj = uj;
alpar@1
   518
         }
alpar@1
   519
      }
alpar@1
   520
      *_lj = lj, *_uj = uj;
alpar@1
   521
done: return ret;
alpar@1
   522
}
alpar@1
   523
alpar@1
   524
/***********************************************************************
alpar@1
   525
*  check_efficiency - check if change in column bounds is efficient
alpar@1
   526
*
alpar@1
   527
*  Given the original bounds of a column l and u and its new actual
alpar@1
   528
*  bounds l' and u' (possibly tighten by the routine check_col_bounds)
alpar@1
   529
*  this routine checks if the change in the column bounds is efficient
alpar@1
   530
*  enough. If so, the routine returns non-zero, otherwise zero.
alpar@1
   531
*
alpar@1
   532
*  The flag means that the variable is required to be integer. */
alpar@1
   533
alpar@1
   534
static int check_efficiency(int flag, double l, double u, double ll,
alpar@1
   535
      double uu)
alpar@1
   536
{     int eff = 0;
alpar@1
   537
      /* check efficiency for lower bound */
alpar@1
   538
      if (l < ll)
alpar@1
   539
      {  if (flag || l == -DBL_MAX)
alpar@1
   540
            eff++;
alpar@1
   541
         else
alpar@1
   542
         {  double r;
alpar@1
   543
            if (u == +DBL_MAX)
alpar@1
   544
               r = 1.0 + fabs(l);
alpar@1
   545
            else
alpar@1
   546
               r = 1.0 + (u - l);
alpar@1
   547
            if (ll - l >= 0.25 * r)
alpar@1
   548
               eff++;
alpar@1
   549
         }
alpar@1
   550
      }
alpar@1
   551
      /* check efficiency for upper bound */
alpar@1
   552
      if (u > uu)
alpar@1
   553
      {  if (flag || u == +DBL_MAX)
alpar@1
   554
            eff++;
alpar@1
   555
         else
alpar@1
   556
         {  double r;
alpar@1
   557
            if (l == -DBL_MAX)
alpar@1
   558
               r = 1.0 + fabs(u);
alpar@1
   559
            else
alpar@1
   560
               r = 1.0 + (u - l);
alpar@1
   561
            if (u - uu >= 0.25 * r)
alpar@1
   562
               eff++;
alpar@1
   563
         }
alpar@1
   564
      }
alpar@1
   565
      return eff;
alpar@1
   566
}
alpar@1
   567
alpar@1
   568
/***********************************************************************
alpar@1
   569
*  basic_preprocessing - perform basic preprocessing
alpar@1
   570
*
alpar@1
   571
*  This routine performs basic preprocessing of the specified MIP that
alpar@1
   572
*  includes relaxing some row bounds and tightening some column bounds.
alpar@1
   573
*
alpar@1
   574
*  On entry the arrays L and U contains original row bounds, and the
alpar@1
   575
*  arrays l and u contains original column bounds:
alpar@1
   576
*
alpar@1
   577
*  L[0] is the lower bound of the objective row;
alpar@1
   578
*  L[i], i = 1,...,m, is the lower bound of i-th row;
alpar@1
   579
*  U[0] is the upper bound of the objective row;
alpar@1
   580
*  U[i], i = 1,...,m, is the upper bound of i-th row;
alpar@1
   581
*  l[0] is not used;
alpar@1
   582
*  l[j], j = 1,...,n, is the lower bound of j-th column;
alpar@1
   583
*  u[0] is not used;
alpar@1
   584
*  u[j], j = 1,...,n, is the upper bound of j-th column.
alpar@1
   585
*
alpar@1
   586
*  On exit the arrays L, U, l, and u contain new actual bounds of rows
alpar@1
   587
*  and column in the same locations.
alpar@1
   588
*
alpar@1
   589
*  The parameters nrs and num specify an initial list of rows to be
alpar@1
   590
*  processed:
alpar@1
   591
*
alpar@1
   592
*  nrs is the number of rows in the initial list, 0 <= nrs <= m+1;
alpar@1
   593
*  num[0] is not used;
alpar@1
   594
*  num[1,...,nrs] are row numbers (0 means the objective row).
alpar@1
   595
*
alpar@1
   596
*  The parameter max_pass specifies the maximal number of times that
alpar@1
   597
*  each row can be processed, max_pass > 0.
alpar@1
   598
*
alpar@1
   599
*  If no primal infeasibility is detected, the routine returns zero,
alpar@1
   600
*  otherwise non-zero. */
alpar@1
   601
alpar@1
   602
static int basic_preprocessing(glp_prob *mip, double L[], double U[],
alpar@1
   603
      double l[], double u[], int nrs, const int num[], int max_pass)
alpar@1
   604
{     int m = mip->m;
alpar@1
   605
      int n = mip->n;
alpar@1
   606
      struct f_info f;
alpar@1
   607
      int i, j, k, len, size, ret = 0;
alpar@1
   608
      int *ind, *list, *mark, *pass;
alpar@1
   609
      double *val, *lb, *ub;
alpar@1
   610
      xassert(0 <= nrs && nrs <= m+1);
alpar@1
   611
      xassert(max_pass > 0);
alpar@1
   612
      /* allocate working arrays */
alpar@1
   613
      ind = xcalloc(1+n, sizeof(int));
alpar@1
   614
      list = xcalloc(1+m+1, sizeof(int));
alpar@1
   615
      mark = xcalloc(1+m+1, sizeof(int));
alpar@1
   616
      memset(&mark[0], 0, (m+1) * sizeof(int));
alpar@1
   617
      pass = xcalloc(1+m+1, sizeof(int));
alpar@1
   618
      memset(&pass[0], 0, (m+1) * sizeof(int));
alpar@1
   619
      val = xcalloc(1+n, sizeof(double));
alpar@1
   620
      lb = xcalloc(1+n, sizeof(double));
alpar@1
   621
      ub = xcalloc(1+n, sizeof(double));
alpar@1
   622
      /* initialize the list of rows to be processed */
alpar@1
   623
      size = 0;
alpar@1
   624
      for (k = 1; k <= nrs; k++)
alpar@1
   625
      {  i = num[k];
alpar@1
   626
         xassert(0 <= i && i <= m);
alpar@1
   627
         /* duplicate row numbers are not allowed */
alpar@1
   628
         xassert(!mark[i]);
alpar@1
   629
         list[++size] = i, mark[i] = 1;
alpar@1
   630
      }
alpar@1
   631
      xassert(size == nrs);
alpar@1
   632
      /* process rows in the list until it becomes empty */
alpar@1
   633
      while (size > 0)
alpar@1
   634
      {  /* get a next row from the list */
alpar@1
   635
         i = list[size--], mark[i] = 0;
alpar@1
   636
         /* increase the row processing count */
alpar@1
   637
         pass[i]++;
alpar@1
   638
         /* if the row is free, skip it */
alpar@1
   639
         if (L[i] == -DBL_MAX && U[i] == +DBL_MAX) continue;
alpar@1
   640
         /* obtain coefficients of the row */
alpar@1
   641
         len = 0;
alpar@1
   642
         if (i == 0)
alpar@1
   643
         {  for (j = 1; j <= n; j++)
alpar@1
   644
            {  GLPCOL *col = mip->col[j];
alpar@1
   645
               if (col->coef != 0.0)
alpar@1
   646
                  len++, ind[len] = j, val[len] = col->coef;
alpar@1
   647
            }
alpar@1
   648
         }
alpar@1
   649
         else
alpar@1
   650
         {  GLPROW *row = mip->row[i];
alpar@1
   651
            GLPAIJ *aij;
alpar@1
   652
            for (aij = row->ptr; aij != NULL; aij = aij->r_next)
alpar@1
   653
               len++, ind[len] = aij->col->j, val[len] = aij->val;
alpar@1
   654
         }
alpar@1
   655
         /* determine lower and upper bounds of columns corresponding
alpar@1
   656
            to non-zero row coefficients */
alpar@1
   657
         for (k = 1; k <= len; k++)
alpar@1
   658
            j = ind[k], lb[k] = l[j], ub[k] = u[j];
alpar@1
   659
         /* prepare the row info to determine implied bounds */
alpar@1
   660
         prepare_row_info(len, val, lb, ub, &f);
alpar@1
   661
         /* check and relax bounds of the row */
alpar@1
   662
         if (check_row_bounds(&f, &L[i], &U[i]))
alpar@1
   663
         {  /* the feasible region is empty */
alpar@1
   664
            ret = 1;
alpar@1
   665
            goto done;
alpar@1
   666
         }
alpar@1
   667
         /* if the row became free, drop it */
alpar@1
   668
         if (L[i] == -DBL_MAX && U[i] == +DBL_MAX) continue;
alpar@1
   669
         /* process columns having non-zero coefficients in the row */
alpar@1
   670
         for (k = 1; k <= len; k++)
alpar@1
   671
         {  GLPCOL *col;
alpar@1
   672
            int flag, eff;
alpar@1
   673
            double ll, uu;
alpar@1
   674
            /* take a next column in the row */
alpar@1
   675
            j = ind[k], col = mip->col[j];
alpar@1
   676
            flag = col->kind != GLP_CV;
alpar@1
   677
            /* check and tighten bounds of the column */
alpar@1
   678
            if (check_col_bounds(&f, len, val, L[i], U[i], lb, ub,
alpar@1
   679
                flag, k, &ll, &uu))
alpar@1
   680
            {  /* the feasible region is empty */
alpar@1
   681
               ret = 1;
alpar@1
   682
               goto done;
alpar@1
   683
            }
alpar@1
   684
            /* check if change in the column bounds is efficient */
alpar@1
   685
            eff = check_efficiency(flag, l[j], u[j], ll, uu);
alpar@1
   686
            /* set new actual bounds of the column */
alpar@1
   687
            l[j] = ll, u[j] = uu;
alpar@1
   688
            /* if the change is efficient, add all rows affected by the
alpar@1
   689
               corresponding column, to the list */
alpar@1
   690
            if (eff > 0)
alpar@1
   691
            {  GLPAIJ *aij;
alpar@1
   692
               for (aij = col->ptr; aij != NULL; aij = aij->c_next)
alpar@1
   693
               {  int ii = aij->row->i;
alpar@1
   694
                  /* if the row was processed maximal number of times,
alpar@1
   695
                     skip it */
alpar@1
   696
                  if (pass[ii] >= max_pass) continue;
alpar@1
   697
                  /* if the row is free, skip it */
alpar@1
   698
                  if (L[ii] == -DBL_MAX && U[ii] == +DBL_MAX) continue;
alpar@1
   699
                  /* put the row into the list */
alpar@1
   700
                  if (mark[ii] == 0)
alpar@1
   701
                  {  xassert(size <= m);
alpar@1
   702
                     list[++size] = ii, mark[ii] = 1;
alpar@1
   703
                  }
alpar@1
   704
               }
alpar@1
   705
            }
alpar@1
   706
         }
alpar@1
   707
      }
alpar@1
   708
done: /* free working arrays */
alpar@1
   709
      xfree(ind);
alpar@1
   710
      xfree(list);
alpar@1
   711
      xfree(mark);
alpar@1
   712
      xfree(pass);
alpar@1
   713
      xfree(val);
alpar@1
   714
      xfree(lb);
alpar@1
   715
      xfree(ub);
alpar@1
   716
      return ret;
alpar@1
   717
}
alpar@1
   718
alpar@1
   719
/***********************************************************************
alpar@1
   720
*  NAME
alpar@1
   721
*
alpar@1
   722
*  ios_preprocess_node - preprocess current subproblem
alpar@1
   723
*
alpar@1
   724
*  SYNOPSIS
alpar@1
   725
*
alpar@1
   726
*  #include "glpios.h"
alpar@1
   727
*  int ios_preprocess_node(glp_tree *tree, int max_pass);
alpar@1
   728
*
alpar@1
   729
*  DESCRIPTION
alpar@1
   730
*
alpar@1
   731
*  The routine ios_preprocess_node performs basic preprocessing of the
alpar@1
   732
*  current subproblem.
alpar@1
   733
*
alpar@1
   734
*  RETURNS
alpar@1
   735
*
alpar@1
   736
*  If no primal infeasibility is detected, the routine returns zero,
alpar@1
   737
*  otherwise non-zero. */
alpar@1
   738
alpar@1
   739
int ios_preprocess_node(glp_tree *tree, int max_pass)
alpar@1
   740
{     glp_prob *mip = tree->mip;
alpar@1
   741
      int m = mip->m;
alpar@1
   742
      int n = mip->n;
alpar@1
   743
      int i, j, nrs, *num, ret = 0;
alpar@1
   744
      double *L, *U, *l, *u;
alpar@1
   745
      /* the current subproblem must exist */
alpar@1
   746
      xassert(tree->curr != NULL);
alpar@1
   747
      /* determine original row bounds */
alpar@1
   748
      L = xcalloc(1+m, sizeof(double));
alpar@1
   749
      U = xcalloc(1+m, sizeof(double));
alpar@1
   750
      switch (mip->mip_stat)
alpar@1
   751
      {  case GLP_UNDEF:
alpar@1
   752
            L[0] = -DBL_MAX, U[0] = +DBL_MAX;
alpar@1
   753
            break;
alpar@1
   754
         case GLP_FEAS:
alpar@1
   755
            switch (mip->dir)
alpar@1
   756
            {  case GLP_MIN:
alpar@1
   757
                  L[0] = -DBL_MAX, U[0] = mip->mip_obj - mip->c0;
alpar@1
   758
                  break;
alpar@1
   759
               case GLP_MAX:
alpar@1
   760
                  L[0] = mip->mip_obj - mip->c0, U[0] = +DBL_MAX;
alpar@1
   761
                  break;
alpar@1
   762
               default:
alpar@1
   763
                  xassert(mip != mip);
alpar@1
   764
            }
alpar@1
   765
            break;
alpar@1
   766
         default:
alpar@1
   767
            xassert(mip != mip);
alpar@1
   768
      }
alpar@1
   769
      for (i = 1; i <= m; i++)
alpar@1
   770
      {  L[i] = glp_get_row_lb(mip, i);
alpar@1
   771
         U[i] = glp_get_row_ub(mip, i);
alpar@1
   772
      }
alpar@1
   773
      /* determine original column bounds */
alpar@1
   774
      l = xcalloc(1+n, sizeof(double));
alpar@1
   775
      u = xcalloc(1+n, sizeof(double));
alpar@1
   776
      for (j = 1; j <= n; j++)
alpar@1
   777
      {  l[j] = glp_get_col_lb(mip, j);
alpar@1
   778
         u[j] = glp_get_col_ub(mip, j);
alpar@1
   779
      }
alpar@1
   780
      /* build the initial list of rows to be analyzed */
alpar@1
   781
      nrs = m + 1;
alpar@1
   782
      num = xcalloc(1+nrs, sizeof(int));
alpar@1
   783
      for (i = 1; i <= nrs; i++) num[i] = i - 1;
alpar@1
   784
      /* perform basic preprocessing */
alpar@1
   785
      if (basic_preprocessing(mip , L, U, l, u, nrs, num, max_pass))
alpar@1
   786
      {  ret = 1;
alpar@1
   787
         goto done;
alpar@1
   788
      }
alpar@1
   789
      /* set new actual (relaxed) row bounds */
alpar@1
   790
      for (i = 1; i <= m; i++)
alpar@1
   791
      {  /* consider only non-active rows to keep dual feasibility */
alpar@1
   792
         if (glp_get_row_stat(mip, i) == GLP_BS)
alpar@1
   793
         {  if (L[i] == -DBL_MAX && U[i] == +DBL_MAX)
alpar@1
   794
               glp_set_row_bnds(mip, i, GLP_FR, 0.0, 0.0);
alpar@1
   795
            else if (U[i] == +DBL_MAX)
alpar@1
   796
               glp_set_row_bnds(mip, i, GLP_LO, L[i], 0.0);
alpar@1
   797
            else if (L[i] == -DBL_MAX)
alpar@1
   798
               glp_set_row_bnds(mip, i, GLP_UP, 0.0, U[i]);
alpar@1
   799
         }
alpar@1
   800
      }
alpar@1
   801
      /* set new actual (tightened) column bounds */
alpar@1
   802
      for (j = 1; j <= n; j++)
alpar@1
   803
      {  int type;
alpar@1
   804
         if (l[j] == -DBL_MAX && u[j] == +DBL_MAX)
alpar@1
   805
            type = GLP_FR;
alpar@1
   806
         else if (u[j] == +DBL_MAX)
alpar@1
   807
            type = GLP_LO;
alpar@1
   808
         else if (l[j] == -DBL_MAX)
alpar@1
   809
            type = GLP_UP;
alpar@1
   810
         else if (l[j] != u[j])
alpar@1
   811
            type = GLP_DB;
alpar@1
   812
         else
alpar@1
   813
            type = GLP_FX;
alpar@1
   814
         glp_set_col_bnds(mip, j, type, l[j], u[j]);
alpar@1
   815
      }
alpar@1
   816
done: /* free working arrays and return */
alpar@1
   817
      xfree(L);
alpar@1
   818
      xfree(U);
alpar@1
   819
      xfree(l);
alpar@1
   820
      xfree(u);
alpar@1
   821
      xfree(num);
alpar@1
   822
      return ret;
alpar@1
   823
}
alpar@1
   824
alpar@1
   825
/* eof */