src/glpini02.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
/* glpini02.c */
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
struct var
alpar@1
    28
{     /* structural variable */
alpar@1
    29
      int j;
alpar@1
    30
      /* ordinal number */
alpar@1
    31
      double q;
alpar@1
    32
      /* penalty value */
alpar@1
    33
};
alpar@1
    34
alpar@1
    35
static int fcmp(const void *ptr1, const void *ptr2)
alpar@1
    36
{     /* this routine is passed to the qsort() function */
alpar@1
    37
      struct var *col1 = (void *)ptr1, *col2 = (void *)ptr2;
alpar@1
    38
      if (col1->q < col2->q) return -1;
alpar@1
    39
      if (col1->q > col2->q) return +1;
alpar@1
    40
      return 0;
alpar@1
    41
}
alpar@1
    42
alpar@1
    43
static int get_column(glp_prob *lp, int j, int ind[], double val[])
alpar@1
    44
{     /* Bixby's algorithm assumes that the constraint matrix is scaled
alpar@1
    45
         such that the maximum absolute value in every non-zero row and
alpar@1
    46
         column is 1 */
alpar@1
    47
      int k, len;
alpar@1
    48
      double big;
alpar@1
    49
      len = glp_get_mat_col(lp, j, ind, val);
alpar@1
    50
      big = 0.0;
alpar@1
    51
      for (k = 1; k <= len; k++)
alpar@1
    52
         if (big < fabs(val[k])) big = fabs(val[k]);
alpar@1
    53
      if (big == 0.0) big = 1.0;
alpar@1
    54
      for (k = 1; k <= len; k++) val[k] /= big;
alpar@1
    55
      return len;
alpar@1
    56
}
alpar@1
    57
alpar@1
    58
static void cpx_basis(glp_prob *lp)
alpar@1
    59
{     /* main routine */
alpar@1
    60
      struct var *C, *C2, *C3, *C4;
alpar@1
    61
      int m, n, i, j, jk, k, l, ll, t, n2, n3, n4, type, len, *I, *r,
alpar@1
    62
         *ind;
alpar@1
    63
      double alpha, gamma, cmax, temp, *v, *val;
alpar@1
    64
      xprintf("Constructing initial basis...\n");
alpar@1
    65
      /* determine the number of rows and columns */
alpar@1
    66
      m = glp_get_num_rows(lp);
alpar@1
    67
      n = glp_get_num_cols(lp);
alpar@1
    68
      /* allocate working arrays */
alpar@1
    69
      C = xcalloc(1+n, sizeof(struct var));
alpar@1
    70
      I = xcalloc(1+m, sizeof(int));
alpar@1
    71
      r = xcalloc(1+m, sizeof(int));
alpar@1
    72
      v = xcalloc(1+m, sizeof(double));
alpar@1
    73
      ind = xcalloc(1+m, sizeof(int));
alpar@1
    74
      val = xcalloc(1+m, sizeof(double));
alpar@1
    75
      /* make all auxiliary variables non-basic */
alpar@1
    76
      for (i = 1; i <= m; i++)
alpar@1
    77
      {  if (glp_get_row_type(lp, i) != GLP_DB)
alpar@1
    78
            glp_set_row_stat(lp, i, GLP_NS);
alpar@1
    79
         else if (fabs(glp_get_row_lb(lp, i)) <=
alpar@1
    80
                  fabs(glp_get_row_ub(lp, i)))
alpar@1
    81
            glp_set_row_stat(lp, i, GLP_NL);
alpar@1
    82
         else
alpar@1
    83
            glp_set_row_stat(lp, i, GLP_NU);
alpar@1
    84
      }
alpar@1
    85
      /* make all structural variables non-basic */
alpar@1
    86
      for (j = 1; j <= n; j++)
alpar@1
    87
      {  if (glp_get_col_type(lp, j) != GLP_DB)
alpar@1
    88
            glp_set_col_stat(lp, j, GLP_NS);
alpar@1
    89
         else if (fabs(glp_get_col_lb(lp, j)) <=
alpar@1
    90
                  fabs(glp_get_col_ub(lp, j)))
alpar@1
    91
            glp_set_col_stat(lp, j, GLP_NL);
alpar@1
    92
         else
alpar@1
    93
            glp_set_col_stat(lp, j, GLP_NU);
alpar@1
    94
      }
alpar@1
    95
      /* C2 is a set of free structural variables */
alpar@1
    96
      n2 = 0, C2 = C + 0;
alpar@1
    97
      for (j = 1; j <= n; j++)
alpar@1
    98
      {  type = glp_get_col_type(lp, j);
alpar@1
    99
         if (type == GLP_FR)
alpar@1
   100
         {  n2++;
alpar@1
   101
            C2[n2].j = j;
alpar@1
   102
            C2[n2].q = 0.0;
alpar@1
   103
         }
alpar@1
   104
      }
alpar@1
   105
      /* C3 is a set of structural variables having excatly one (lower
alpar@1
   106
         or upper) bound */
alpar@1
   107
      n3 = 0, C3 = C2 + n2;
alpar@1
   108
      for (j = 1; j <= n; j++)
alpar@1
   109
      {  type = glp_get_col_type(lp, j);
alpar@1
   110
         if (type == GLP_LO)
alpar@1
   111
         {  n3++;
alpar@1
   112
            C3[n3].j = j;
alpar@1
   113
            C3[n3].q = + glp_get_col_lb(lp, j);
alpar@1
   114
         }
alpar@1
   115
         else if (type == GLP_UP)
alpar@1
   116
         {  n3++;
alpar@1
   117
            C3[n3].j = j;
alpar@1
   118
            C3[n3].q = - glp_get_col_ub(lp, j);
alpar@1
   119
         }
alpar@1
   120
      }
alpar@1
   121
      /* C4 is a set of structural variables having both (lower and
alpar@1
   122
         upper) bounds */
alpar@1
   123
      n4 = 0, C4 = C3 + n3;
alpar@1
   124
      for (j = 1; j <= n; j++)
alpar@1
   125
      {  type = glp_get_col_type(lp, j);
alpar@1
   126
         if (type == GLP_DB)
alpar@1
   127
         {  n4++;
alpar@1
   128
            C4[n4].j = j;
alpar@1
   129
            C4[n4].q = glp_get_col_lb(lp, j) - glp_get_col_ub(lp, j);
alpar@1
   130
         }
alpar@1
   131
      }
alpar@1
   132
      /* compute gamma = max{|c[j]|: 1 <= j <= n} */
alpar@1
   133
      gamma = 0.0;
alpar@1
   134
      for (j = 1; j <= n; j++)
alpar@1
   135
      {  temp = fabs(glp_get_obj_coef(lp, j));
alpar@1
   136
         if (gamma < temp) gamma = temp;
alpar@1
   137
      }
alpar@1
   138
      /* compute cmax */
alpar@1
   139
      cmax = (gamma == 0.0 ? 1.0 : 1000.0 * gamma);
alpar@1
   140
      /* compute final penalty for all structural variables within sets
alpar@1
   141
         C2, C3, and C4 */
alpar@1
   142
      switch (glp_get_obj_dir(lp))
alpar@1
   143
      {  case GLP_MIN: temp = +1.0; break;
alpar@1
   144
         case GLP_MAX: temp = -1.0; break;
alpar@1
   145
         default: xassert(lp != lp);
alpar@1
   146
      }
alpar@1
   147
      for (k = 1; k <= n2+n3+n4; k++)
alpar@1
   148
      {  j = C[k].j;
alpar@1
   149
         C[k].q += (temp * glp_get_obj_coef(lp, j)) / cmax;
alpar@1
   150
      }
alpar@1
   151
      /* sort structural variables within C2, C3, and C4 in ascending
alpar@1
   152
         order of penalty value */
alpar@1
   153
      qsort(C2+1, n2, sizeof(struct var), fcmp);
alpar@1
   154
      for (k = 1; k < n2; k++) xassert(C2[k].q <= C2[k+1].q);
alpar@1
   155
      qsort(C3+1, n3, sizeof(struct var), fcmp);
alpar@1
   156
      for (k = 1; k < n3; k++) xassert(C3[k].q <= C3[k+1].q);
alpar@1
   157
      qsort(C4+1, n4, sizeof(struct var), fcmp);
alpar@1
   158
      for (k = 1; k < n4; k++) xassert(C4[k].q <= C4[k+1].q);
alpar@1
   159
      /*** STEP 1 ***/
alpar@1
   160
      for (i = 1; i <= m; i++)
alpar@1
   161
      {  type = glp_get_row_type(lp, i);
alpar@1
   162
         if (type != GLP_FX)
alpar@1
   163
         {  /* row i is either free or inequality constraint */
alpar@1
   164
            glp_set_row_stat(lp, i, GLP_BS);
alpar@1
   165
            I[i] = 1;
alpar@1
   166
            r[i] = 1;
alpar@1
   167
         }
alpar@1
   168
         else
alpar@1
   169
         {  /* row i is equality constraint */
alpar@1
   170
            I[i] = 0;
alpar@1
   171
            r[i] = 0;
alpar@1
   172
         }
alpar@1
   173
         v[i] = +DBL_MAX;
alpar@1
   174
      }
alpar@1
   175
      /*** STEP 2 ***/
alpar@1
   176
      for (k = 1; k <= n2+n3+n4; k++)
alpar@1
   177
      {  jk = C[k].j;
alpar@1
   178
         len = get_column(lp, jk, ind, val);
alpar@1
   179
         /* let alpha = max{|A[l,jk]|: r[l] = 0} and let l' be such
alpar@1
   180
            that alpha = |A[l',jk]| */
alpar@1
   181
         alpha = 0.0, ll = 0;
alpar@1
   182
         for (t = 1; t <= len; t++)
alpar@1
   183
         {  l = ind[t];
alpar@1
   184
            if (r[l] == 0 && alpha < fabs(val[t]))
alpar@1
   185
               alpha = fabs(val[t]), ll = l;
alpar@1
   186
         }
alpar@1
   187
         if (alpha >= 0.99)
alpar@1
   188
         {  /* B := B union {jk} */
alpar@1
   189
            glp_set_col_stat(lp, jk, GLP_BS);
alpar@1
   190
            I[ll] = 1;
alpar@1
   191
            v[ll] = alpha;
alpar@1
   192
            /* r[l] := r[l] + 1 for all l such that |A[l,jk]| != 0 */
alpar@1
   193
            for (t = 1; t <= len; t++)
alpar@1
   194
            {  l = ind[t];
alpar@1
   195
               if (val[t] != 0.0) r[l]++;
alpar@1
   196
            }
alpar@1
   197
            /* continue to the next k */
alpar@1
   198
            continue;
alpar@1
   199
         }
alpar@1
   200
         /* if |A[l,jk]| > 0.01 * v[l] for some l, continue to the
alpar@1
   201
            next k */
alpar@1
   202
         for (t = 1; t <= len; t++)
alpar@1
   203
         {  l = ind[t];
alpar@1
   204
            if (fabs(val[t]) > 0.01 * v[l]) break;
alpar@1
   205
         }
alpar@1
   206
         if (t <= len) continue;
alpar@1
   207
         /* otherwise, let alpha = max{|A[l,jk]|: I[l] = 0} and let l'
alpar@1
   208
            be such that alpha = |A[l',jk]| */
alpar@1
   209
         alpha = 0.0, ll = 0;
alpar@1
   210
         for (t = 1; t <= len; t++)
alpar@1
   211
         {  l = ind[t];
alpar@1
   212
            if (I[l] == 0 && alpha < fabs(val[t]))
alpar@1
   213
               alpha = fabs(val[t]), ll = l;
alpar@1
   214
         }
alpar@1
   215
         /* if alpha = 0, continue to the next k */
alpar@1
   216
         if (alpha == 0.0) continue;
alpar@1
   217
         /* B := B union {jk} */
alpar@1
   218
         glp_set_col_stat(lp, jk, GLP_BS);
alpar@1
   219
         I[ll] = 1;
alpar@1
   220
         v[ll] = alpha;
alpar@1
   221
         /* r[l] := r[l] + 1 for all l such that |A[l,jk]| != 0 */
alpar@1
   222
         for (t = 1; t <= len; t++)
alpar@1
   223
         {  l = ind[t];
alpar@1
   224
            if (val[t] != 0.0) r[l]++;
alpar@1
   225
         }
alpar@1
   226
      }
alpar@1
   227
      /*** STEP 3 ***/
alpar@1
   228
      /* add an artificial variable (auxiliary variable for equality
alpar@1
   229
         constraint) to cover each remaining uncovered row */
alpar@1
   230
      for (i = 1; i <= m; i++)
alpar@1
   231
         if (I[i] == 0) glp_set_row_stat(lp, i, GLP_BS);
alpar@1
   232
      /* free working arrays */
alpar@1
   233
      xfree(C);
alpar@1
   234
      xfree(I);
alpar@1
   235
      xfree(r);
alpar@1
   236
      xfree(v);
alpar@1
   237
      xfree(ind);
alpar@1
   238
      xfree(val);
alpar@1
   239
      return;
alpar@1
   240
}
alpar@1
   241
alpar@1
   242
/***********************************************************************
alpar@1
   243
*  NAME
alpar@1
   244
*
alpar@1
   245
*  glp_cpx_basis - construct Bixby's initial LP basis
alpar@1
   246
*
alpar@1
   247
*  SYNOPSIS
alpar@1
   248
*
alpar@1
   249
*  void glp_cpx_basis(glp_prob *lp);
alpar@1
   250
*
alpar@1
   251
*  DESCRIPTION
alpar@1
   252
*
alpar@1
   253
*  The routine glp_cpx_basis constructs an advanced initial basis for
alpar@1
   254
*  the specified problem object.
alpar@1
   255
*
alpar@1
   256
*  The routine is based on Bixby's algorithm described in the paper:
alpar@1
   257
*
alpar@1
   258
*  Robert E. Bixby. Implementing the Simplex Method: The Initial Basis.
alpar@1
   259
*  ORSA Journal on Computing, Vol. 4, No. 3, 1992, pp. 267-84. */
alpar@1
   260
alpar@1
   261
void glp_cpx_basis(glp_prob *lp)
alpar@1
   262
{     if (lp->m == 0 || lp->n == 0)
alpar@1
   263
         glp_std_basis(lp);
alpar@1
   264
      else
alpar@1
   265
         cpx_basis(lp);
alpar@1
   266
      return;
alpar@1
   267
}
alpar@1
   268
alpar@1
   269
/* eof */