src/glpnet05.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
/* glpnet05.c (Goldfarb's maximum flow problem generator) */
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
*  This code is a modified version of the program RMFGEN, a maxflow
alpar@1
     7
*  problem generator developed by D.Goldfarb and M.Grigoriadis, and
alpar@1
     8
*  originally implemented by Tamas Badics <badics@rutcor.rutgers.edu>.
alpar@1
     9
*  The original code is publically available on the DIMACS ftp site at:
alpar@1
    10
*  <ftp://dimacs.rutgers.edu/pub/netflow/generators/network/genrmf>.
alpar@1
    11
*
alpar@1
    12
*  All changes concern only the program interface, so this modified
alpar@1
    13
*  version produces exactly the same instances as the original version.
alpar@1
    14
*
alpar@1
    15
*  Changes were made by Andrew Makhorin <mao@gnu.org>.
alpar@1
    16
*
alpar@1
    17
*  GLPK is free software: you can redistribute it and/or modify it
alpar@1
    18
*  under the terms of the GNU General Public License as published by
alpar@1
    19
*  the Free Software Foundation, either version 3 of the License, or
alpar@1
    20
*  (at your option) any later version.
alpar@1
    21
*
alpar@1
    22
*  GLPK is distributed in the hope that it will be useful, but WITHOUT
alpar@1
    23
*  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
alpar@1
    24
*  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
alpar@1
    25
*  License for more details.
alpar@1
    26
*
alpar@1
    27
*  You should have received a copy of the GNU General Public License
alpar@1
    28
*  along with GLPK. If not, see <http://www.gnu.org/licenses/>.
alpar@1
    29
***********************************************************************/
alpar@1
    30
alpar@1
    31
#include "glpapi.h"
alpar@1
    32
#include "glprng.h"
alpar@1
    33
alpar@1
    34
/***********************************************************************
alpar@1
    35
*  NAME
alpar@1
    36
*
alpar@1
    37
*  glp_rmfgen - Goldfarb's maximum flow problem generator
alpar@1
    38
*
alpar@1
    39
*  SYNOPSIS
alpar@1
    40
*
alpar@1
    41
*  int glp_rmfgen(glp_graph *G, int *s, int *t, int a_cap,
alpar@1
    42
*     const int parm[1+5]);
alpar@1
    43
*
alpar@1
    44
*  DESCRIPTION
alpar@1
    45
*
alpar@1
    46
*  The routine glp_rmfgen is a maximum flow problem generator developed
alpar@1
    47
*  by D.Goldfarb and M.Grigoriadis.
alpar@1
    48
*
alpar@1
    49
*  The parameter G specifies the graph object, to which the generated
alpar@1
    50
*  problem data have to be stored. Note that on entry the graph object
alpar@1
    51
*  is erased with the routine glp_erase_graph.
alpar@1
    52
*
alpar@1
    53
*  The pointer s specifies a location, to which the routine stores the
alpar@1
    54
*  source node number. If s is NULL, the node number is not stored.
alpar@1
    55
*
alpar@1
    56
*  The pointer t specifies a location, to which the routine stores the
alpar@1
    57
*  sink node number. If t is NULL, the node number is not stored.
alpar@1
    58
*
alpar@1
    59
*  The parameter a_cap specifies an offset of the field of type double
alpar@1
    60
*  in the arc data block, to which the routine stores the arc capacity.
alpar@1
    61
*  If a_cap < 0, the capacity is not stored.
alpar@1
    62
*
alpar@1
    63
*  The array parm contains description of the network to be generated:
alpar@1
    64
*
alpar@1
    65
*  parm[0]  not used
alpar@1
    66
*  parm[1]  (seed)   random number seed (a positive integer)
alpar@1
    67
*  parm[2]  (a)      frame size
alpar@1
    68
*  parm[3]  (b)      depth
alpar@1
    69
*  parm[4]  (c1)     minimal arc capacity
alpar@1
    70
*  parm[5]  (c2)     maximal arc capacity
alpar@1
    71
*
alpar@1
    72
*  RETURNS
alpar@1
    73
*
alpar@1
    74
*  If the instance was successfully generated, the routine glp_netgen
alpar@1
    75
*  returns zero; otherwise, if specified parameters are inconsistent,
alpar@1
    76
*  the routine returns a non-zero error code.
alpar@1
    77
*
alpar@1
    78
*  COMMENTS
alpar@1
    79
*
alpar@1
    80
*  The generated network is as follows. It has b pieces of frames of
alpar@1
    81
*  size a * a. (So alltogether the number of vertices is a * a * b)
alpar@1
    82
*
alpar@1
    83
*  In each frame all the vertices are connected with their neighbours
alpar@1
    84
*  (forth and back). In addition the vertices of a frame are connected
alpar@1
    85
*  one to one with the vertices of next frame using a random permutation
alpar@1
    86
*  of those vertices.
alpar@1
    87
*
alpar@1
    88
*  The source is the lower left vertex of the first frame, the sink is
alpar@1
    89
*  the upper right vertex of the b'th frame.
alpar@1
    90
*
alpar@1
    91
*                    t
alpar@1
    92
*           +-------+
alpar@1
    93
*           |      .|
alpar@1
    94
*           |     . |
alpar@1
    95
*        /  |    /  |
alpar@1
    96
*       +-------+/ -+ b
alpar@1
    97
*       |    |  |/.
alpar@1
    98
*     a |   -v- |/
alpar@1
    99
*       |    |  |/
alpar@1
   100
*       +-------+ 1
alpar@1
   101
*      s    a
alpar@1
   102
*
alpar@1
   103
*  The capacities are randomly chosen integers from the range of [c1,c2]
alpar@1
   104
*  in the case of interconnecting edges, and c2 * a * a for the in-frame
alpar@1
   105
*  edges.
alpar@1
   106
*
alpar@1
   107
*  REFERENCES
alpar@1
   108
*
alpar@1
   109
*  D.Goldfarb and M.D.Grigoriadis, "A computational comparison of the
alpar@1
   110
*  Dinic and network simplex methods for maximum flow." Annals of Op.
alpar@1
   111
*  Res. 13 (1988), pp. 83-123.
alpar@1
   112
*
alpar@1
   113
*  U.Derigs and W.Meier, "Implementing Goldberg's max-flow algorithm:
alpar@1
   114
*  A computational investigation." Zeitschrift fuer Operations Research
alpar@1
   115
*  33 (1989), pp. 383-403. */
alpar@1
   116
alpar@1
   117
typedef struct VERTEX
alpar@1
   118
{     struct EDGE **edgelist;
alpar@1
   119
      /* Pointer to the list of pointers to the adjacent edges.
alpar@1
   120
         (No matter that to or from edges) */
alpar@1
   121
      struct EDGE **current;
alpar@1
   122
      /* Pointer to the current edge */
alpar@1
   123
      int degree;
alpar@1
   124
      /* Number of adjacent edges (both direction) */
alpar@1
   125
      int index;
alpar@1
   126
} vertex;
alpar@1
   127
alpar@1
   128
typedef struct EDGE
alpar@1
   129
{     int from;
alpar@1
   130
      int to;
alpar@1
   131
      int cap;
alpar@1
   132
      /* Capacity */
alpar@1
   133
} edge;
alpar@1
   134
alpar@1
   135
typedef struct NETWORK
alpar@1
   136
{     struct NETWORK *next, *prev;
alpar@1
   137
      int vertnum;
alpar@1
   138
      int edgenum;
alpar@1
   139
      vertex *verts;
alpar@1
   140
      /* Vertex array[1..vertnum] */
alpar@1
   141
      edge *edges;
alpar@1
   142
      /* Edge array[1..edgenum] */
alpar@1
   143
      int source;
alpar@1
   144
      /* Pointer to the source */
alpar@1
   145
      int sink;
alpar@1
   146
      /* Pointer to the sink */
alpar@1
   147
} network;
alpar@1
   148
alpar@1
   149
struct csa
alpar@1
   150
{     /* common storage area */
alpar@1
   151
      glp_graph *G;
alpar@1
   152
      int *s, *t, a_cap;
alpar@1
   153
      RNG *rand;
alpar@1
   154
      network *N;
alpar@1
   155
      int *Parr;
alpar@1
   156
      int A, AA, C2AA, Ec;
alpar@1
   157
};
alpar@1
   158
alpar@1
   159
#define G      (csa->G)
alpar@1
   160
#define s      (csa->s)
alpar@1
   161
#define t      (csa->t)
alpar@1
   162
#define a_cap  (csa->a_cap)
alpar@1
   163
#define N      (csa->N)
alpar@1
   164
#define Parr   (csa->Parr)
alpar@1
   165
#define A      (csa->A)
alpar@1
   166
#define AA     (csa->AA)
alpar@1
   167
#define C2AA   (csa->C2AA)
alpar@1
   168
#define Ec     (csa->Ec)
alpar@1
   169
alpar@1
   170
#undef random
alpar@1
   171
#define random(A) (int)(rng_unif_01(csa->rand) * (double)(A))
alpar@1
   172
#define RANDOM(A, B) (int)(random((B) - (A) + 1) + (A))
alpar@1
   173
#define sgn(A) (((A) > 0) ? 1 : ((A) == 0) ? 0 : -1)
alpar@1
   174
alpar@1
   175
static void make_edge(struct csa *csa, int from, int to, int c1, int c2)
alpar@1
   176
{     Ec++;
alpar@1
   177
      N->edges[Ec].from = from;
alpar@1
   178
      N->edges[Ec].to = to;
alpar@1
   179
      N->edges[Ec].cap = RANDOM(c1, c2);
alpar@1
   180
      return;
alpar@1
   181
}
alpar@1
   182
alpar@1
   183
static void permute(struct csa *csa)
alpar@1
   184
{     int i, j, tmp;
alpar@1
   185
      for (i = 1; i < AA; i++)
alpar@1
   186
      {  j = RANDOM(i, AA);
alpar@1
   187
         tmp = Parr[i];
alpar@1
   188
         Parr[i] = Parr[j];
alpar@1
   189
         Parr[j] = tmp;
alpar@1
   190
      }
alpar@1
   191
      return;
alpar@1
   192
}
alpar@1
   193
alpar@1
   194
static void connect(struct csa *csa, int offset, int cv, int x1, int y1)
alpar@1
   195
{     int cv1;
alpar@1
   196
      cv1 = offset + (x1 - 1) * A + y1;
alpar@1
   197
      Ec++;
alpar@1
   198
      N->edges[Ec].from = cv;
alpar@1
   199
      N->edges[Ec].to = cv1;
alpar@1
   200
      N->edges[Ec].cap = C2AA;
alpar@1
   201
      return;
alpar@1
   202
}
alpar@1
   203
alpar@1
   204
static network *gen_rmf(struct csa *csa, int a, int b, int c1, int c2)
alpar@1
   205
{     /* generates a network with a*a*b nodes and 6a*a*b-4ab-2a*a edges
alpar@1
   206
         random_frame network:
alpar@1
   207
         Derigs & Meier, Methods & Models of OR (1989), 33:383-403 */
alpar@1
   208
      int x, y, z, offset, cv;
alpar@1
   209
      A = a;
alpar@1
   210
      AA = a * a;
alpar@1
   211
      C2AA = c2 * AA;
alpar@1
   212
      Ec = 0;
alpar@1
   213
      N = (network *)xmalloc(sizeof(network));
alpar@1
   214
      N->vertnum = AA * b;
alpar@1
   215
      N->edgenum = 5 * AA * b - 4 * A * b - AA;
alpar@1
   216
      N->edges = (edge *)xcalloc(N->edgenum + 1, sizeof(edge));
alpar@1
   217
      N->source = 1;
alpar@1
   218
      N->sink = N->vertnum;
alpar@1
   219
      Parr = (int *)xcalloc(AA + 1, sizeof(int));
alpar@1
   220
      for (x = 1; x <= AA; x++)
alpar@1
   221
         Parr[x] = x;
alpar@1
   222
      for (z = 1; z <= b; z++)
alpar@1
   223
      {  offset = AA * (z - 1);
alpar@1
   224
         if (z != b)
alpar@1
   225
            permute(csa);
alpar@1
   226
         for (x = 1; x <= A; x++)
alpar@1
   227
         {  for (y = 1; y <= A; y++)
alpar@1
   228
            {  cv = offset + (x - 1) * A + y;
alpar@1
   229
               if (z != b)
alpar@1
   230
                  make_edge(csa, cv, offset + AA + Parr[cv - offset],
alpar@1
   231
                     c1, c2); /* the intermediate edges */
alpar@1
   232
               if (y < A)
alpar@1
   233
                  connect(csa, offset, cv, x, y + 1);
alpar@1
   234
               if (y > 1)
alpar@1
   235
                  connect(csa, offset, cv, x, y - 1);
alpar@1
   236
               if (x < A)
alpar@1
   237
                  connect(csa, offset, cv, x + 1, y);
alpar@1
   238
               if (x > 1)
alpar@1
   239
                  connect(csa, offset, cv, x - 1, y);
alpar@1
   240
            }
alpar@1
   241
         }
alpar@1
   242
      }
alpar@1
   243
      xfree(Parr);
alpar@1
   244
      return N;
alpar@1
   245
}
alpar@1
   246
alpar@1
   247
static void print_max_format(struct csa *csa, network *n, char *comm[],
alpar@1
   248
      int dim)
alpar@1
   249
{     /* prints a network heading with dim lines of comments (no \n
alpar@1
   250
         needs at the ends) */
alpar@1
   251
      int i, vnum, e_num;
alpar@1
   252
      edge *e;
alpar@1
   253
      vnum = n->vertnum;
alpar@1
   254
      e_num = n->edgenum;
alpar@1
   255
      if (G == NULL)
alpar@1
   256
      {  for (i = 0; i < dim; i++)
alpar@1
   257
            xprintf("c %s\n", comm[i]);
alpar@1
   258
         xprintf("p max %7d %10d\n", vnum, e_num);
alpar@1
   259
         xprintf("n %7d s\n", n->source);
alpar@1
   260
         xprintf("n %7d t\n", n->sink);
alpar@1
   261
      }
alpar@1
   262
      else
alpar@1
   263
      {  glp_add_vertices(G, vnum);
alpar@1
   264
         if (s != NULL) *s = n->source;
alpar@1
   265
         if (t != NULL) *t = n->sink;
alpar@1
   266
      }
alpar@1
   267
      for (i = 1; i <= e_num; i++)
alpar@1
   268
      {  e = &n->edges[i];
alpar@1
   269
         if (G == NULL)
alpar@1
   270
            xprintf("a %7d %7d %10d\n", e->from, e->to, (int)e->cap);
alpar@1
   271
         else
alpar@1
   272
         {  glp_arc *a = glp_add_arc(G, e->from, e->to);
alpar@1
   273
            if (a_cap >= 0)
alpar@1
   274
            {  double temp = (double)e->cap;
alpar@1
   275
               memcpy((char *)a->data + a_cap, &temp, sizeof(double));
alpar@1
   276
            }
alpar@1
   277
         }
alpar@1
   278
      }
alpar@1
   279
      return;
alpar@1
   280
}
alpar@1
   281
alpar@1
   282
static void gen_free_net(network *n)
alpar@1
   283
{     xfree(n->edges);
alpar@1
   284
      xfree(n);
alpar@1
   285
      return;
alpar@1
   286
}
alpar@1
   287
alpar@1
   288
int glp_rmfgen(glp_graph *G_, int *_s, int *_t, int _a_cap,
alpar@1
   289
      const int parm[1+5])
alpar@1
   290
{     struct csa _csa, *csa = &_csa;
alpar@1
   291
      network *n;
alpar@1
   292
      char comm[10][80], *com1[10];
alpar@1
   293
      int seed, a, b, c1, c2, ret;
alpar@1
   294
      G = G_;
alpar@1
   295
      s = _s;
alpar@1
   296
      t = _t;
alpar@1
   297
      a_cap = _a_cap;
alpar@1
   298
      if (G != NULL)
alpar@1
   299
      {  if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
alpar@1
   300
           xerror("glp_rmfgen: a_cap = %d; invalid offset\n", a_cap);
alpar@1
   301
      }
alpar@1
   302
      seed = parm[1];
alpar@1
   303
      a = parm[2];
alpar@1
   304
      b = parm[3];
alpar@1
   305
      c1 = parm[4];
alpar@1
   306
      c2 = parm[5];
alpar@1
   307
      if (!(seed > 0 && 1 <= a && a <= 1000 && 1 <= b && b <= 1000 &&
alpar@1
   308
            0 <= c1 && c1 <= c2 && c2 <= 1000))
alpar@1
   309
      {  ret = 1;
alpar@1
   310
         goto done;
alpar@1
   311
      }
alpar@1
   312
      if (G != NULL)
alpar@1
   313
      {  glp_erase_graph(G, G->v_size, G->a_size);
alpar@1
   314
         glp_set_graph_name(G, "RMFGEN");
alpar@1
   315
      }
alpar@1
   316
      csa->rand = rng_create_rand();
alpar@1
   317
      rng_init_rand(csa->rand, seed);
alpar@1
   318
      n = gen_rmf(csa, a, b, c1, c2);
alpar@1
   319
      sprintf(comm[0], "This file was generated by genrmf.");
alpar@1
   320
      sprintf(comm[1], "The parameters are: a: %d b: %d c1: %d c2: %d",
alpar@1
   321
         a, b, c1, c2);
alpar@1
   322
      com1[0] = comm[0];
alpar@1
   323
      com1[1] = comm[1];
alpar@1
   324
      print_max_format(csa, n, com1, 2);
alpar@1
   325
      gen_free_net(n);
alpar@1
   326
      rng_delete_rand(csa->rand);
alpar@1
   327
      ret = 0;
alpar@1
   328
done: return ret;
alpar@1
   329
}
alpar@1
   330
alpar@1
   331
/**********************************************************************/
alpar@1
   332
alpar@1
   333
#if 0
alpar@1
   334
int main(int argc, char *argv[])
alpar@1
   335
{     int seed, a, b, c1, c2, i, parm[1+5];
alpar@1
   336
      seed = 123;
alpar@1
   337
      a = b = c1 = c2 = -1;
alpar@1
   338
      for (i = 1; i < argc; i++)
alpar@1
   339
      {  if (strcmp(argv[i], "-seed") == 0)
alpar@1
   340
            seed = atoi(argv[++i]);
alpar@1
   341
         else if (strcmp(argv[i], "-a") == 0)
alpar@1
   342
            a = atoi(argv[++i]);
alpar@1
   343
         else if (strcmp(argv[i], "-b") == 0)
alpar@1
   344
            b = atoi(argv[++i]);
alpar@1
   345
         else if (strcmp(argv[i], "-c1") == 0)
alpar@1
   346
            c1 = atoi(argv[++i]);
alpar@1
   347
         else if (strcmp(argv[i], "-c2") == 0)
alpar@1
   348
            c2 = atoi(argv[++i]);
alpar@1
   349
      }
alpar@1
   350
      if (a < 0 || b < 0 || c1 < 0 || c2 < 0)
alpar@1
   351
      {  xprintf("Usage:\n");
alpar@1
   352
         xprintf("genrmf [-seed seed] -a frame_size -b depth\n");
alpar@1
   353
         xprintf("        -c1 cap_range1 -c2 cap_range2\n");
alpar@1
   354
      }
alpar@1
   355
      else
alpar@1
   356
      {  parm[1] = seed;
alpar@1
   357
         parm[2] = a;
alpar@1
   358
         parm[3] = b;
alpar@1
   359
         parm[4] = c1;
alpar@1
   360
         parm[5] = c2;
alpar@1
   361
         glp_rmfgen(NULL, NULL, NULL, 0, parm);
alpar@1
   362
      }
alpar@1
   363
      return 0;
alpar@1
   364
}
alpar@1
   365
#endif
alpar@1
   366
alpar@1
   367
/* eof */