src/glpnet06.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
/* glpnet06.c (out-of-kilter algorithm) */
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 "glpenv.h"
alpar@1
    26
#include "glpnet.h"
alpar@1
    27
alpar@1
    28
/***********************************************************************
alpar@1
    29
*  NAME
alpar@1
    30
*
alpar@1
    31
*  okalg - out-of-kilter algorithm
alpar@1
    32
*
alpar@1
    33
*  SYNOPSIS
alpar@1
    34
*
alpar@1
    35
*  #include "glpnet.h"
alpar@1
    36
*  int okalg(int nv, int na, const int tail[], const int head[],
alpar@1
    37
*     const int low[], const int cap[], const int cost[], int x[],
alpar@1
    38
*     int pi[]);
alpar@1
    39
*
alpar@1
    40
*  DESCRIPTION
alpar@1
    41
*
alpar@1
    42
*  The routine okalg implements the out-of-kilter algorithm to find a
alpar@1
    43
*  minimal-cost circulation in the specified flow network.
alpar@1
    44
*
alpar@1
    45
*  INPUT PARAMETERS
alpar@1
    46
*
alpar@1
    47
*  nv is the number of nodes, nv >= 0.
alpar@1
    48
*
alpar@1
    49
*  na is the number of arcs, na >= 0.
alpar@1
    50
*
alpar@1
    51
*  tail[a], a = 1,...,na, is the index of tail node of arc a.
alpar@1
    52
*
alpar@1
    53
*  head[a], a = 1,...,na, is the index of head node of arc a.
alpar@1
    54
*
alpar@1
    55
*  low[a], a = 1,...,na, is an lower bound to the flow through arc a.
alpar@1
    56
*
alpar@1
    57
*  cap[a], a = 1,...,na, is an upper bound to the flow through arc a,
alpar@1
    58
*  which is the capacity of the arc.
alpar@1
    59
*
alpar@1
    60
*  cost[a], a = 1,...,na, is a per-unit cost of the flow through arc a.
alpar@1
    61
*
alpar@1
    62
*  NOTES
alpar@1
    63
*
alpar@1
    64
*  1. Multiple arcs are allowed, but self-loops are not allowed.
alpar@1
    65
*
alpar@1
    66
*  2. It is required that 0 <= low[a] <= cap[a] for all arcs.
alpar@1
    67
*
alpar@1
    68
*  3. Arc costs may have any sign.
alpar@1
    69
*
alpar@1
    70
*  OUTPUT PARAMETERS
alpar@1
    71
*
alpar@1
    72
*  x[a], a = 1,...,na, is optimal value of the flow through arc a.
alpar@1
    73
*
alpar@1
    74
*  pi[i], i = 1,...,nv, is Lagrange multiplier for flow conservation
alpar@1
    75
*  equality constraint corresponding to node i (the node potential).
alpar@1
    76
*
alpar@1
    77
*  RETURNS
alpar@1
    78
*
alpar@1
    79
*  0  optimal circulation found;
alpar@1
    80
*
alpar@1
    81
*  1  there is no feasible circulation;
alpar@1
    82
*
alpar@1
    83
*  2  integer overflow occured;
alpar@1
    84
*
alpar@1
    85
*  3  optimality test failed (logic error).
alpar@1
    86
*
alpar@1
    87
*  REFERENCES
alpar@1
    88
*
alpar@1
    89
*  L.R.Ford, Jr., and D.R.Fulkerson, "Flows in Networks," The RAND
alpar@1
    90
*  Corp., Report R-375-PR (August 1962), Chap. III "Minimal Cost Flow
alpar@1
    91
*  Problems," pp.113-26. */
alpar@1
    92
alpar@1
    93
static int overflow(int u, int v)
alpar@1
    94
{     /* check for integer overflow on computing u + v */
alpar@1
    95
      if (u > 0 && v > 0 && u + v < 0) return 1;
alpar@1
    96
      if (u < 0 && v < 0 && u + v > 0) return 1;
alpar@1
    97
      return 0;
alpar@1
    98
}
alpar@1
    99
alpar@1
   100
int okalg(int nv, int na, const int tail[], const int head[],
alpar@1
   101
      const int low[], const int cap[], const int cost[], int x[],
alpar@1
   102
      int pi[])
alpar@1
   103
{     int a, aok, delta, i, j, k, lambda, pos1, pos2, s, t, temp, ret,
alpar@1
   104
         *ptr, *arc, *link, *list;
alpar@1
   105
      /* sanity checks */
alpar@1
   106
      xassert(nv >= 0);
alpar@1
   107
      xassert(na >= 0);
alpar@1
   108
      for (a = 1; a <= na; a++)
alpar@1
   109
      {  i = tail[a], j = head[a];
alpar@1
   110
         xassert(1 <= i && i <= nv);
alpar@1
   111
         xassert(1 <= j && j <= nv);
alpar@1
   112
         xassert(i != j);
alpar@1
   113
         xassert(0 <= low[a] && low[a] <= cap[a]);
alpar@1
   114
      }
alpar@1
   115
      /* allocate working arrays */
alpar@1
   116
      ptr = xcalloc(1+nv+1, sizeof(int));
alpar@1
   117
      arc = xcalloc(1+na+na, sizeof(int));
alpar@1
   118
      link = xcalloc(1+nv, sizeof(int));
alpar@1
   119
      list = xcalloc(1+nv, sizeof(int));
alpar@1
   120
      /* ptr[i] := (degree of node i) */
alpar@1
   121
      for (i = 1; i <= nv; i++)
alpar@1
   122
         ptr[i] = 0;
alpar@1
   123
      for (a = 1; a <= na; a++)
alpar@1
   124
      {  ptr[tail[a]]++;
alpar@1
   125
         ptr[head[a]]++;
alpar@1
   126
      }
alpar@1
   127
      /* initialize arc pointers */
alpar@1
   128
      ptr[1]++;
alpar@1
   129
      for (i = 1; i < nv; i++)
alpar@1
   130
         ptr[i+1] += ptr[i];
alpar@1
   131
      ptr[nv+1] = ptr[nv];
alpar@1
   132
      /* build arc lists */
alpar@1
   133
      for (a = 1; a <= na; a++)
alpar@1
   134
      {  arc[--ptr[tail[a]]] = a;
alpar@1
   135
         arc[--ptr[head[a]]] = a;
alpar@1
   136
      }
alpar@1
   137
      xassert(ptr[1] == 1);
alpar@1
   138
      xassert(ptr[nv+1] == na+na+1);
alpar@1
   139
      /* now the indices of arcs incident to node i are stored in
alpar@1
   140
         locations arc[ptr[i]], arc[ptr[i]+1], ..., arc[ptr[i+1]-1] */
alpar@1
   141
      /* initialize arc flows and node potentials */
alpar@1
   142
      for (a = 1; a <= na; a++)
alpar@1
   143
         x[a] = 0;
alpar@1
   144
      for (i = 1; i <= nv; i++)
alpar@1
   145
         pi[i] = 0;
alpar@1
   146
loop: /* main loop starts here */
alpar@1
   147
      /* find out-of-kilter arc */
alpar@1
   148
      aok = 0;
alpar@1
   149
      for (a = 1; a <= na; a++)
alpar@1
   150
      {  i = tail[a], j = head[a];
alpar@1
   151
         if (overflow(cost[a], pi[i] - pi[j]))
alpar@1
   152
         {  ret = 2;
alpar@1
   153
            goto done;
alpar@1
   154
         }
alpar@1
   155
         lambda = cost[a] + (pi[i] - pi[j]);
alpar@1
   156
         if (x[a] < low[a] || lambda < 0 && x[a] < cap[a])
alpar@1
   157
         {  /* arc a = i->j is out of kilter, and we need to increase
alpar@1
   158
               the flow through this arc */
alpar@1
   159
            aok = a, s = j, t = i;
alpar@1
   160
            break;
alpar@1
   161
         }
alpar@1
   162
         if (x[a] > cap[a] || lambda > 0 && x[a] > low[a])
alpar@1
   163
         {  /* arc a = i->j is out of kilter, and we need to decrease
alpar@1
   164
               the flow through this arc */
alpar@1
   165
            aok = a, s = i, t = j;
alpar@1
   166
            break;
alpar@1
   167
         }
alpar@1
   168
      }
alpar@1
   169
      if (aok == 0)
alpar@1
   170
      {  /* all arcs are in kilter */
alpar@1
   171
         /* check for feasibility */
alpar@1
   172
         for (a = 1; a <= na; a++)
alpar@1
   173
         {  if (!(low[a] <= x[a] && x[a] <= cap[a]))
alpar@1
   174
            {  ret = 3;
alpar@1
   175
               goto done;
alpar@1
   176
            }
alpar@1
   177
         }
alpar@1
   178
         for (i = 1; i <= nv; i++)
alpar@1
   179
         {  temp = 0;
alpar@1
   180
            for (k = ptr[i]; k < ptr[i+1]; k++)
alpar@1
   181
            {  a = arc[k];
alpar@1
   182
               if (tail[a] == i)
alpar@1
   183
               {  /* a is outgoing arc */
alpar@1
   184
                  temp += x[a];
alpar@1
   185
               }
alpar@1
   186
               else if (head[a] == i)
alpar@1
   187
               {  /* a is incoming arc */
alpar@1
   188
                  temp -= x[a];
alpar@1
   189
               }
alpar@1
   190
               else
alpar@1
   191
                  xassert(a != a);
alpar@1
   192
            }
alpar@1
   193
            if (temp != 0)
alpar@1
   194
            {  ret = 3;
alpar@1
   195
               goto done;
alpar@1
   196
            }
alpar@1
   197
         }
alpar@1
   198
         /* check for optimality */
alpar@1
   199
         for (a = 1; a <= na; a++)
alpar@1
   200
         {  i = tail[a], j = head[a];
alpar@1
   201
            lambda = cost[a] + (pi[i] - pi[j]);
alpar@1
   202
            if (lambda > 0 && x[a] != low[a] ||
alpar@1
   203
                lambda < 0 && x[a] != cap[a])
alpar@1
   204
            {  ret = 3;
alpar@1
   205
               goto done;
alpar@1
   206
            }
alpar@1
   207
         }
alpar@1
   208
         /* current circulation is optimal */
alpar@1
   209
         ret = 0;
alpar@1
   210
         goto done;
alpar@1
   211
      }
alpar@1
   212
      /* now we need to find a cycle (t, a, s, ..., t), which allows
alpar@1
   213
         increasing the flow along it, where a is the out-of-kilter arc
alpar@1
   214
         just found */
alpar@1
   215
      /* link[i] = 0 means that node i is not labelled yet;
alpar@1
   216
         link[i] = a means that arc a immediately precedes node i */
alpar@1
   217
      /* initially only node s is labelled */
alpar@1
   218
      for (i = 1; i <= nv; i++)
alpar@1
   219
         link[i] = 0;
alpar@1
   220
      link[s] = aok, list[1] = s, pos1 = pos2 = 1;
alpar@1
   221
      /* breadth first search */
alpar@1
   222
      while (pos1 <= pos2)
alpar@1
   223
      {  /* dequeue node i */
alpar@1
   224
         i = list[pos1++];
alpar@1
   225
         /* consider all arcs incident to node i */
alpar@1
   226
         for (k = ptr[i]; k < ptr[i+1]; k++)
alpar@1
   227
         {  a = arc[k];
alpar@1
   228
            if (tail[a] == i)
alpar@1
   229
            {  /* a = i->j is a forward arc from s to t */
alpar@1
   230
               j = head[a];
alpar@1
   231
               /* if node j has been labelled, skip the arc */
alpar@1
   232
               if (link[j] != 0) continue;
alpar@1
   233
               /* if the arc does not allow increasing the flow through
alpar@1
   234
                  it, skip the arc */
alpar@1
   235
               if (x[a] >= cap[a]) continue;
alpar@1
   236
               if (overflow(cost[a], pi[i] - pi[j]))
alpar@1
   237
               {  ret = 2;
alpar@1
   238
                  goto done;
alpar@1
   239
               }
alpar@1
   240
               lambda = cost[a] + (pi[i] - pi[j]);
alpar@1
   241
               if (lambda > 0 && x[a] >= low[a]) continue;
alpar@1
   242
            }
alpar@1
   243
            else if (head[a] == i)
alpar@1
   244
            {  /* a = i<-j is a backward arc from s to t */
alpar@1
   245
               j = tail[a];
alpar@1
   246
               /* if node j has been labelled, skip the arc */
alpar@1
   247
               if (link[j] != 0) continue;
alpar@1
   248
               /* if the arc does not allow decreasing the flow through
alpar@1
   249
                  it, skip the arc */
alpar@1
   250
               if (x[a] <= low[a]) continue;
alpar@1
   251
               if (overflow(cost[a], pi[j] - pi[i]))
alpar@1
   252
               {  ret = 2;
alpar@1
   253
                  goto done;
alpar@1
   254
               }
alpar@1
   255
               lambda = cost[a] + (pi[j] - pi[i]);
alpar@1
   256
               if (lambda < 0 && x[a] <= cap[a]) continue;
alpar@1
   257
            }
alpar@1
   258
            else
alpar@1
   259
               xassert(a != a);
alpar@1
   260
            /* label node j and enqueue it */
alpar@1
   261
            link[j] = a, list[++pos2] = j;
alpar@1
   262
            /* check for breakthrough */
alpar@1
   263
            if (j == t) goto brkt;
alpar@1
   264
         }
alpar@1
   265
      }
alpar@1
   266
      /* NONBREAKTHROUGH */
alpar@1
   267
      /* consider all arcs, whose one endpoint is labelled and other is
alpar@1
   268
         not, and determine maximal change of node potentials */
alpar@1
   269
      delta = 0;
alpar@1
   270
      for (a = 1; a <= na; a++)
alpar@1
   271
      {  i = tail[a], j = head[a];
alpar@1
   272
         if (link[i] != 0 && link[j] == 0)
alpar@1
   273
         {  /* a = i->j, where node i is labelled, node j is not */
alpar@1
   274
            if (overflow(cost[a], pi[i] - pi[j]))
alpar@1
   275
            {  ret = 2;
alpar@1
   276
               goto done;
alpar@1
   277
            }
alpar@1
   278
            lambda = cost[a] + (pi[i] - pi[j]);
alpar@1
   279
            if (x[a] <= cap[a] && lambda > 0)
alpar@1
   280
               if (delta == 0 || delta > + lambda) delta = + lambda;
alpar@1
   281
         }
alpar@1
   282
         else if (link[i] == 0 && link[j] != 0)
alpar@1
   283
         {  /* a = j<-i, where node j is labelled, node i is not */
alpar@1
   284
            if (overflow(cost[a], pi[i] - pi[j]))
alpar@1
   285
            {  ret = 2;
alpar@1
   286
               goto done;
alpar@1
   287
            }
alpar@1
   288
            lambda = cost[a] + (pi[i] - pi[j]);
alpar@1
   289
            if (x[a] >= low[a] && lambda < 0)
alpar@1
   290
               if (delta == 0 || delta > - lambda) delta = - lambda;
alpar@1
   291
         }
alpar@1
   292
      }
alpar@1
   293
      if (delta == 0)
alpar@1
   294
      {  /* there is no feasible circulation */
alpar@1
   295
         ret = 1;
alpar@1
   296
         goto done;
alpar@1
   297
      }
alpar@1
   298
      /* increase potentials of all unlabelled nodes */
alpar@1
   299
      for (i = 1; i <= nv; i++)
alpar@1
   300
      {  if (link[i] == 0)
alpar@1
   301
         {  if (overflow(pi[i], delta))
alpar@1
   302
            {  ret = 2;
alpar@1
   303
               goto done;
alpar@1
   304
            }
alpar@1
   305
            pi[i] += delta;
alpar@1
   306
         }
alpar@1
   307
      }
alpar@1
   308
      goto loop;
alpar@1
   309
brkt: /* BREAKTHROUGH */
alpar@1
   310
      /* walk through arcs of the cycle (t, a, s, ..., t) found in the
alpar@1
   311
         reverse order and determine maximal change of the flow */
alpar@1
   312
      delta = 0;
alpar@1
   313
      for (j = t;; j = i)
alpar@1
   314
      {  /* arc a immediately precedes node j in the cycle */
alpar@1
   315
         a = link[j];
alpar@1
   316
         if (head[a] == j)
alpar@1
   317
         {  /* a = i->j is a forward arc of the cycle */
alpar@1
   318
            i = tail[a];
alpar@1
   319
            lambda = cost[a] + (pi[i] - pi[j]);
alpar@1
   320
            if (lambda > 0 && x[a] < low[a])
alpar@1
   321
            {  /* x[a] may be increased until its lower bound */
alpar@1
   322
               temp = low[a] - x[a];
alpar@1
   323
            }
alpar@1
   324
            else if (lambda <= 0 && x[a] < cap[a])
alpar@1
   325
            {  /* x[a] may be increased until its upper bound */
alpar@1
   326
               temp = cap[a] - x[a];
alpar@1
   327
            }
alpar@1
   328
            else
alpar@1
   329
               xassert(a != a);
alpar@1
   330
         }
alpar@1
   331
         else if (tail[a] == j)
alpar@1
   332
         {  /* a = i<-j is a backward arc of the cycle */
alpar@1
   333
            i = head[a];
alpar@1
   334
            lambda = cost[a] + (pi[j] - pi[i]);
alpar@1
   335
            if (lambda < 0 && x[a] > cap[a])
alpar@1
   336
            {  /* x[a] may be decreased until its upper bound */
alpar@1
   337
               temp = x[a] - cap[a];
alpar@1
   338
            }
alpar@1
   339
            else if (lambda >= 0 && x[a] > low[a])
alpar@1
   340
            {  /* x[a] may be decreased until its lower bound */
alpar@1
   341
               temp = x[a] - low[a];
alpar@1
   342
            }
alpar@1
   343
            else
alpar@1
   344
               xassert(a != a);
alpar@1
   345
         }
alpar@1
   346
         else
alpar@1
   347
            xassert(a != a);
alpar@1
   348
         if (delta == 0 || delta > temp) delta = temp;
alpar@1
   349
         /* check for end of the cycle */
alpar@1
   350
         if (i == t) break;
alpar@1
   351
      }
alpar@1
   352
      xassert(delta > 0);
alpar@1
   353
      /* increase the flow along the cycle */
alpar@1
   354
      for (j = t;; j = i)
alpar@1
   355
      {  /* arc a immediately precedes node j in the cycle */
alpar@1
   356
         a = link[j];
alpar@1
   357
         if (head[a] == j)
alpar@1
   358
         {  /* a = i->j is a forward arc of the cycle */
alpar@1
   359
            i = tail[a];
alpar@1
   360
            /* overflow cannot occur */
alpar@1
   361
            x[a] += delta;
alpar@1
   362
         }
alpar@1
   363
         else if (tail[a] == j)
alpar@1
   364
         {  /* a = i<-j is a backward arc of the cycle */
alpar@1
   365
            i = head[a];
alpar@1
   366
            /* overflow cannot occur */
alpar@1
   367
            x[a] -= delta;
alpar@1
   368
         }
alpar@1
   369
         else
alpar@1
   370
            xassert(a != a);
alpar@1
   371
         /* check for end of the cycle */
alpar@1
   372
         if (i == t) break;
alpar@1
   373
      }
alpar@1
   374
      goto loop;
alpar@1
   375
done: /* free working arrays */
alpar@1
   376
      xfree(ptr);
alpar@1
   377
      xfree(arc);
alpar@1
   378
      xfree(link);
alpar@1
   379
      xfree(list);
alpar@1
   380
      return ret;
alpar@1
   381
}
alpar@1
   382
alpar@1
   383
/* eof */