src/glpnet04.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
/* glpnet04.c (grid-like network 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 GRIDGEN, a grid-like
alpar@1
     7
*  network problem generator developed by Yusin Lee and Jim Orlin.
alpar@1
     8
*  The original code is publically available on the DIMACS ftp site at:
alpar@1
     9
*  <ftp://dimacs.rutgers.edu/pub/netflow/generators/network/gridgen>.
alpar@1
    10
*
alpar@1
    11
*  All changes concern only the program interface, so this modified
alpar@1
    12
*  version produces exactly the same instances as the original version.
alpar@1
    13
*
alpar@1
    14
*  Changes were made by Andrew Makhorin <mao@gnu.org>.
alpar@1
    15
*
alpar@1
    16
*  GLPK is free software: you can redistribute it and/or modify it
alpar@1
    17
*  under the terms of the GNU General Public License as published by
alpar@1
    18
*  the Free Software Foundation, either version 3 of the License, or
alpar@1
    19
*  (at your option) any later version.
alpar@1
    20
*
alpar@1
    21
*  GLPK is distributed in the hope that it will be useful, but WITHOUT
alpar@1
    22
*  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
alpar@1
    23
*  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
alpar@1
    24
*  License for more details.
alpar@1
    25
*
alpar@1
    26
*  You should have received a copy of the GNU General Public License
alpar@1
    27
*  along with GLPK. If not, see <http://www.gnu.org/licenses/>.
alpar@1
    28
***********************************************************************/
alpar@1
    29
alpar@1
    30
#include "glpapi.h"
alpar@1
    31
alpar@1
    32
/***********************************************************************
alpar@1
    33
*  NAME
alpar@1
    34
*
alpar@1
    35
*  glp_gridgen - grid-like network problem generator
alpar@1
    36
*
alpar@1
    37
*  SYNOPSIS
alpar@1
    38
*
alpar@1
    39
*  int glp_gridgen(glp_graph *G, int v_rhs, int a_cap, int a_cost,
alpar@1
    40
*     const int parm[1+14]);
alpar@1
    41
*
alpar@1
    42
*  DESCRIPTION
alpar@1
    43
*
alpar@1
    44
*  The routine glp_gridgen is a grid-like network problem generator
alpar@1
    45
*  developed by Yusin Lee and Jim Orlin.
alpar@1
    46
*
alpar@1
    47
*  The parameter G specifies the graph object, to which the generated
alpar@1
    48
*  problem data have to be stored. Note that on entry the graph object
alpar@1
    49
*  is erased with the routine glp_erase_graph.
alpar@1
    50
*
alpar@1
    51
*  The parameter v_rhs specifies an offset of the field of type double
alpar@1
    52
*  in the vertex data block, to which the routine stores the supply or
alpar@1
    53
*  demand value. If v_rhs < 0, the value is not stored.
alpar@1
    54
*
alpar@1
    55
*  The parameter a_cap specifies an offset of the field of type double
alpar@1
    56
*  in the arc data block, to which the routine stores the arc capacity.
alpar@1
    57
*  If a_cap < 0, the capacity is not stored.
alpar@1
    58
*
alpar@1
    59
*  The parameter a_cost specifies an offset of the field of type double
alpar@1
    60
*  in the arc data block, to which the routine stores the per-unit cost
alpar@1
    61
*  if the arc flow. If a_cost < 0, the cost 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]  two-ways arcs indicator:
alpar@1
    67
*           1 - if links in both direction should be generated
alpar@1
    68
*           0 - otherwise
alpar@1
    69
*  parm[2]  random number seed (a positive integer)
alpar@1
    70
*  parm[3]  number of nodes (the number of nodes generated might be
alpar@1
    71
*           slightly different to make the network a grid)
alpar@1
    72
*  parm[4]  grid width
alpar@1
    73
*  parm[5]  number of sources
alpar@1
    74
*  parm[6]  number of sinks
alpar@1
    75
*  parm[7]  average degree
alpar@1
    76
*  parm[8]  total flow
alpar@1
    77
*  parm[9]  distribution of arc costs:
alpar@1
    78
*           1 - uniform
alpar@1
    79
*           2 - exponential
alpar@1
    80
*  parm[10] lower bound for arc cost (uniform)
alpar@1
    81
*           100 * lambda (exponential)
alpar@1
    82
*  parm[11] upper bound for arc cost (uniform)
alpar@1
    83
*           not used (exponential)
alpar@1
    84
*  parm[12] distribution of arc capacities:
alpar@1
    85
*           1 - uniform
alpar@1
    86
*           2 - exponential
alpar@1
    87
*  parm[13] lower bound for arc capacity (uniform)
alpar@1
    88
*           100 * lambda (exponential)
alpar@1
    89
*  parm[14] upper bound for arc capacity (uniform)
alpar@1
    90
*           not used (exponential)
alpar@1
    91
*
alpar@1
    92
*  RETURNS
alpar@1
    93
*
alpar@1
    94
*  If the instance was successfully generated, the routine glp_gridgen
alpar@1
    95
*  returns zero; otherwise, if specified parameters are inconsistent,
alpar@1
    96
*  the routine returns a non-zero error code.
alpar@1
    97
*
alpar@1
    98
*  COMMENTS
alpar@1
    99
*
alpar@1
   100
*  This network generator generates a grid-like network plus a super
alpar@1
   101
*  node. In additional to the arcs connecting the nodes in the grid,
alpar@1
   102
*  there is an arc from each supply node to the super node and from the
alpar@1
   103
*  super node to each demand node to guarantee feasiblity. These arcs
alpar@1
   104
*  have very high costs and very big capacities.
alpar@1
   105
*
alpar@1
   106
*  The idea of this network generator is as follows: First, a grid of
alpar@1
   107
*  n1 * n2 is generated. For example, 5 * 3. The nodes are numbered as
alpar@1
   108
*  1 to 15, and the supernode is numbered as n1*n2+1. Then arcs between
alpar@1
   109
*  adjacent nodes are generated. For these arcs, the user is allowed to
alpar@1
   110
*  specify either to generate two-way arcs or one-way arcs. If two-way
alpar@1
   111
*  arcs are to be generated, two arcs, one in each direction, will be
alpar@1
   112
*  generated between each adjacent node pairs. Otherwise, only one arc
alpar@1
   113
*  will be generated. If this is the case, the arcs will be generated
alpar@1
   114
*  in alterntive directions as shown below.
alpar@1
   115
*
alpar@1
   116
*      1 ---> 2 ---> 3 ---> 4 ---> 5
alpar@1
   117
*      |      ^      |      ^      |
alpar@1
   118
*      |      |      |      |      |
alpar@1
   119
*      V      |      V      |      V
alpar@1
   120
*      6 <--- 7 <--- 8 <--- 9 <--- 10
alpar@1
   121
*      |      ^      |      ^      |
alpar@1
   122
*      |      |      |      |      |
alpar@1
   123
*      V      |      V      |      V
alpar@1
   124
*     11 --->12 --->13 --->14 ---> 15
alpar@1
   125
*
alpar@1
   126
*  Then the arcs between the super node and the source/sink nodes are
alpar@1
   127
*  added as mentioned before. If the number of arcs still doesn't reach
alpar@1
   128
*  the requirement, additional arcs will be added by uniformly picking
alpar@1
   129
*  random node pairs. There is no checking to prevent multiple arcs
alpar@1
   130
*  between any pair of nodes. However, there will be no self-arcs (arcs
alpar@1
   131
*  that poins back to its tail node) in the network.
alpar@1
   132
*
alpar@1
   133
*  The source and sink nodes are selected uniformly in the network, and
alpar@1
   134
*  the imbalances of each source/sink node are also assigned by uniform
alpar@1
   135
*  distribution. */
alpar@1
   136
alpar@1
   137
struct stat_para
alpar@1
   138
{     /* structure for statistical distributions */
alpar@1
   139
      int distribution;
alpar@1
   140
      /* the distribution: */
alpar@1
   141
#define UNIFORM      1  /* uniform distribution */
alpar@1
   142
#define EXPONENTIAL  2  /* exponential distribution */
alpar@1
   143
      double parameter[5];
alpar@1
   144
      /* the parameters of the distribution */
alpar@1
   145
};
alpar@1
   146
alpar@1
   147
struct arcs
alpar@1
   148
{     int from;
alpar@1
   149
      /* the FROM node of that arc */
alpar@1
   150
      int to;
alpar@1
   151
      /* the TO node of that arc */
alpar@1
   152
      int cost;
alpar@1
   153
      /* original cost of that arc */
alpar@1
   154
      int u;
alpar@1
   155
      /* capacity of the arc */
alpar@1
   156
};
alpar@1
   157
alpar@1
   158
struct imbalance
alpar@1
   159
{     int node;
alpar@1
   160
      /* Node ID */
alpar@1
   161
      int supply;
alpar@1
   162
      /* Supply of that node */
alpar@1
   163
};
alpar@1
   164
alpar@1
   165
struct csa
alpar@1
   166
{     /* common storage area */
alpar@1
   167
      glp_graph *G;
alpar@1
   168
      int v_rhs, a_cap, a_cost;
alpar@1
   169
      int seed;
alpar@1
   170
      /* random number seed */
alpar@1
   171
      int seed_original;
alpar@1
   172
      /* the original seed from input */
alpar@1
   173
      int two_way;
alpar@1
   174
      /* 0: generate arcs in both direction for the basic grid, except
alpar@1
   175
         for the arcs to/from the super node.  1: o/w */
alpar@1
   176
      int n_node;
alpar@1
   177
      /* total number of nodes in the network, numbered 1 to n_node,
alpar@1
   178
         including the super node, which is the last one */
alpar@1
   179
      int n_arc;
alpar@1
   180
      /* total number of arcs in the network, counting EVERY arc. */
alpar@1
   181
      int n_grid_arc;
alpar@1
   182
      /* number of arcs in the basic grid, including the arcs to/from
alpar@1
   183
         the super node */
alpar@1
   184
      int n_source, n_sink;
alpar@1
   185
      /* number of source and sink nodes */
alpar@1
   186
      int avg_degree;
alpar@1
   187
      /* average degree, arcs to and from the super node are counted */
alpar@1
   188
      int t_supply;
alpar@1
   189
      /* total supply in the network */
alpar@1
   190
      int n1, n2;
alpar@1
   191
      /* the two edges of the network grid.  n1 >= n2 */
alpar@1
   192
      struct imbalance *source_list, *sink_list;
alpar@1
   193
      /* head of the array of source/sink nodes */
alpar@1
   194
      struct stat_para arc_costs;
alpar@1
   195
      /* the distribution of arc costs */
alpar@1
   196
      struct stat_para capacities;
alpar@1
   197
      /* distribution of the capacities of the arcs */
alpar@1
   198
      struct arcs *arc_list;
alpar@1
   199
      /* head of the arc list array.  Arcs in this array are in the
alpar@1
   200
         order of grid_arcs, arcs to/from super node, and other arcs */
alpar@1
   201
};
alpar@1
   202
alpar@1
   203
#define G (csa->G)
alpar@1
   204
#define v_rhs (csa->v_rhs)
alpar@1
   205
#define a_cap (csa->a_cap)
alpar@1
   206
#define a_cost (csa->a_cost)
alpar@1
   207
#define seed (csa->seed)
alpar@1
   208
#define seed_original (csa->seed_original)
alpar@1
   209
#define two_way (csa->two_way)
alpar@1
   210
#define n_node (csa->n_node)
alpar@1
   211
#define n_arc (csa->n_arc)
alpar@1
   212
#define n_grid_arc (csa->n_grid_arc)
alpar@1
   213
#define n_source (csa->n_source)
alpar@1
   214
#define n_sink (csa->n_sink)
alpar@1
   215
#define avg_degree (csa->avg_degree)
alpar@1
   216
#define t_supply (csa->t_supply)
alpar@1
   217
#define n1 (csa->n1)
alpar@1
   218
#define n2 (csa->n2)
alpar@1
   219
#define source_list (csa->source_list)
alpar@1
   220
#define sink_list (csa->sink_list)
alpar@1
   221
#define arc_costs (csa->arc_costs)
alpar@1
   222
#define capacities (csa->capacities)
alpar@1
   223
#define arc_list (csa->arc_list)
alpar@1
   224
alpar@1
   225
static void assign_capacities(struct csa *csa);
alpar@1
   226
static void assign_costs(struct csa *csa);
alpar@1
   227
static void assign_imbalance(struct csa *csa);
alpar@1
   228
static int exponential(struct csa *csa, double lambda[1]);
alpar@1
   229
static struct arcs *gen_additional_arcs(struct csa *csa, struct arcs
alpar@1
   230
      *arc_ptr);
alpar@1
   231
static struct arcs *gen_basic_grid(struct csa *csa, struct arcs
alpar@1
   232
      *arc_ptr);
alpar@1
   233
static void gen_more_arcs(struct csa *csa, struct arcs *arc_ptr);
alpar@1
   234
static void generate(struct csa *csa);
alpar@1
   235
static void output(struct csa *csa);
alpar@1
   236
static double randy(struct csa *csa);
alpar@1
   237
static void select_source_sinks(struct csa *csa);
alpar@1
   238
static int uniform(struct csa *csa, double a[2]);
alpar@1
   239
alpar@1
   240
int glp_gridgen(glp_graph *G_, int _v_rhs, int _a_cap, int _a_cost,
alpar@1
   241
      const int parm[1+14])
alpar@1
   242
{     struct csa _csa, *csa = &_csa;
alpar@1
   243
      int n, ret;
alpar@1
   244
      G = G_;
alpar@1
   245
      v_rhs = _v_rhs;
alpar@1
   246
      a_cap = _a_cap;
alpar@1
   247
      a_cost = _a_cost;
alpar@1
   248
      if (G != NULL)
alpar@1
   249
      {  if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double))
alpar@1
   250
            xerror("glp_gridgen: v_rhs = %d; invalid offset\n", v_rhs);
alpar@1
   251
         if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
alpar@1
   252
            xerror("glp_gridgen: a_cap = %d; invalid offset\n", a_cap);
alpar@1
   253
         if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
alpar@1
   254
            xerror("glp_gridgen: a_cost = %d; invalid offset\n", a_cost)
alpar@1
   255
               ;
alpar@1
   256
      }
alpar@1
   257
      /* Check the parameters for consistency. */
alpar@1
   258
      if (!(parm[1] == 0 || parm[1] == 1))
alpar@1
   259
      {  ret = 1;
alpar@1
   260
         goto done;
alpar@1
   261
      }
alpar@1
   262
      if (parm[2] < 1)
alpar@1
   263
      {  ret = 2;
alpar@1
   264
         goto done;
alpar@1
   265
      }
alpar@1
   266
      if (!(10 <= parm[3] && parm[3] <= 40000))
alpar@1
   267
      {  ret = 3;
alpar@1
   268
         goto done;
alpar@1
   269
      }
alpar@1
   270
      if (!(1 <= parm[4] && parm[4] <= 40000))
alpar@1
   271
      {  ret = 4;
alpar@1
   272
         goto done;
alpar@1
   273
      }
alpar@1
   274
      if (!(parm[5] >= 0 && parm[6] >= 0 && parm[5] + parm[6] <=
alpar@1
   275
         parm[3]))
alpar@1
   276
      {  ret = 5;
alpar@1
   277
         goto done;
alpar@1
   278
      }
alpar@1
   279
      if (!(1 <= parm[7] && parm[7] <= parm[3]))
alpar@1
   280
      {  ret = 6;
alpar@1
   281
         goto done;
alpar@1
   282
      }
alpar@1
   283
      if (parm[8] < 0)
alpar@1
   284
      {  ret = 7;
alpar@1
   285
         goto done;
alpar@1
   286
      }
alpar@1
   287
      if (!(parm[9] == 1 || parm[9] == 2))
alpar@1
   288
      {  ret = 8;
alpar@1
   289
         goto done;
alpar@1
   290
      }
alpar@1
   291
      if (parm[9] == 1 && parm[10] > parm[11] ||
alpar@1
   292
          parm[9] == 2 && parm[10] < 1)
alpar@1
   293
      {  ret = 9;
alpar@1
   294
         goto done;
alpar@1
   295
      }
alpar@1
   296
      if (!(parm[12] == 1 || parm[12] == 2))
alpar@1
   297
      {  ret = 10;
alpar@1
   298
         goto done;
alpar@1
   299
      }
alpar@1
   300
      if (parm[12] == 1 && !(0 <= parm[13] && parm[13] <= parm[14]) ||
alpar@1
   301
          parm[12] == 2 && parm[13] < 1)
alpar@1
   302
      {  ret = 11;
alpar@1
   303
         goto done;
alpar@1
   304
      }
alpar@1
   305
      /* Initialize the graph object. */
alpar@1
   306
      if (G != NULL)
alpar@1
   307
      {  glp_erase_graph(G, G->v_size, G->a_size);
alpar@1
   308
         glp_set_graph_name(G, "GRIDGEN");
alpar@1
   309
      }
alpar@1
   310
      /* Copy the generator parameters. */
alpar@1
   311
      two_way = parm[1];
alpar@1
   312
      seed_original = seed = parm[2];
alpar@1
   313
      n_node = parm[3];
alpar@1
   314
      n = parm[4];
alpar@1
   315
      n_source = parm[5];
alpar@1
   316
      n_sink = parm[6];
alpar@1
   317
      avg_degree = parm[7];
alpar@1
   318
      t_supply = parm[8];
alpar@1
   319
      arc_costs.distribution = parm[9];
alpar@1
   320
      if (parm[9] == 1)
alpar@1
   321
      {  arc_costs.parameter[0] = parm[10];
alpar@1
   322
         arc_costs.parameter[1] = parm[11];
alpar@1
   323
      }
alpar@1
   324
      else
alpar@1
   325
      {  arc_costs.parameter[0] = (double)parm[10] / 100.0;
alpar@1
   326
         arc_costs.parameter[1] = 0.0;
alpar@1
   327
      }
alpar@1
   328
      capacities.distribution = parm[12];
alpar@1
   329
      if (parm[12] == 1)
alpar@1
   330
      {  capacities.parameter[0] = parm[13];
alpar@1
   331
         capacities.parameter[1] = parm[14];
alpar@1
   332
      }
alpar@1
   333
      else
alpar@1
   334
      {  capacities.parameter[0] = (double)parm[13] / 100.0;
alpar@1
   335
         capacities.parameter[1] = 0.0;
alpar@1
   336
      }
alpar@1
   337
      /* Calculate the edge lengths of the grid according to the
alpar@1
   338
         input. */
alpar@1
   339
      if (n * n >= n_node)
alpar@1
   340
      {  n1 = n;
alpar@1
   341
         n2 = (int)((double)n_node / (double)n + 0.5);
alpar@1
   342
      }
alpar@1
   343
      else
alpar@1
   344
      {  n2 = n;
alpar@1
   345
         n1 = (int)((double)n_node / (double)n + 0.5);
alpar@1
   346
      }
alpar@1
   347
      /* Recalculate the total number of nodes and plus 1 for the super
alpar@1
   348
         node. */
alpar@1
   349
      n_node = n1 * n2 + 1;
alpar@1
   350
      n_arc = n_node * avg_degree;
alpar@1
   351
      n_grid_arc = (two_way + 1) * ((n1 - 1) * n2 + (n2 - 1) * n1) +
alpar@1
   352
         n_source + n_sink;
alpar@1
   353
      if (n_grid_arc > n_arc) n_arc = n_grid_arc;
alpar@1
   354
      arc_list = xcalloc(n_arc, sizeof(struct arcs));
alpar@1
   355
      source_list = xcalloc(n_source, sizeof(struct imbalance));
alpar@1
   356
      sink_list = xcalloc(n_sink, sizeof(struct imbalance));
alpar@1
   357
      /* Generate a random network. */
alpar@1
   358
      generate(csa);
alpar@1
   359
      /* Output the network. */
alpar@1
   360
      output(csa);
alpar@1
   361
      /* Free all allocated memory. */
alpar@1
   362
      xfree(arc_list);
alpar@1
   363
      xfree(source_list);
alpar@1
   364
      xfree(sink_list);
alpar@1
   365
      /* The instance has been successfully generated. */
alpar@1
   366
      ret = 0;
alpar@1
   367
done: return ret;
alpar@1
   368
}
alpar@1
   369
alpar@1
   370
#undef random
alpar@1
   371
alpar@1
   372
static void assign_capacities(struct csa *csa)
alpar@1
   373
{     /* Assign a capacity to each arc. */
alpar@1
   374
      struct arcs *arc_ptr = arc_list;
alpar@1
   375
      int (*random)(struct csa *csa, double *);
alpar@1
   376
      int i;
alpar@1
   377
      /* Determine the random number generator to use. */
alpar@1
   378
      switch (arc_costs.distribution)
alpar@1
   379
      {  case UNIFORM:
alpar@1
   380
            random = uniform;
alpar@1
   381
            break;
alpar@1
   382
         case EXPONENTIAL:
alpar@1
   383
            random = exponential;
alpar@1
   384
            break;
alpar@1
   385
         default:
alpar@1
   386
            xassert(csa != csa);
alpar@1
   387
      }
alpar@1
   388
      /* Assign capacities to grid arcs. */
alpar@1
   389
      for (i = n_source + n_sink; i < n_grid_arc; i++, arc_ptr++)
alpar@1
   390
         arc_ptr->u = random(csa, capacities.parameter);
alpar@1
   391
      i = i - n_source - n_sink;
alpar@1
   392
      /* Assign capacities to arcs to/from supernode. */
alpar@1
   393
      for (; i < n_grid_arc; i++, arc_ptr++)
alpar@1
   394
         arc_ptr->u = t_supply;
alpar@1
   395
      /* Assign capacities to all other arcs. */
alpar@1
   396
      for (; i < n_arc; i++, arc_ptr++)
alpar@1
   397
         arc_ptr->u = random(csa, capacities.parameter);
alpar@1
   398
      return;
alpar@1
   399
}
alpar@1
   400
alpar@1
   401
static void assign_costs(struct csa *csa)
alpar@1
   402
{     /* Assign a cost to each arc. */
alpar@1
   403
      struct arcs *arc_ptr = arc_list;
alpar@1
   404
      int (*random)(struct csa *csa, double *);
alpar@1
   405
      int i;
alpar@1
   406
      /* A high cost assigned to arcs to/from the supernode. */
alpar@1
   407
      int high_cost;
alpar@1
   408
      /* The maximum cost assigned to arcs in the base grid. */
alpar@1
   409
      int max_cost = 0;
alpar@1
   410
      /* Determine the random number generator to use. */
alpar@1
   411
      switch (arc_costs.distribution)
alpar@1
   412
      {  case UNIFORM:
alpar@1
   413
            random = uniform;
alpar@1
   414
            break;
alpar@1
   415
         case EXPONENTIAL:
alpar@1
   416
            random = exponential;
alpar@1
   417
            break;
alpar@1
   418
         default:
alpar@1
   419
            xassert(csa != csa);
alpar@1
   420
      }
alpar@1
   421
      /* Assign costs to arcs in the base grid. */
alpar@1
   422
      for (i = n_source + n_sink; i < n_grid_arc; i++, arc_ptr++)
alpar@1
   423
      {  arc_ptr->cost = random(csa, arc_costs.parameter);
alpar@1
   424
         if (max_cost < arc_ptr->cost) max_cost = arc_ptr->cost;
alpar@1
   425
      }
alpar@1
   426
      i = i - n_source - n_sink;
alpar@1
   427
      /* Assign costs to arcs to/from the super node. */
alpar@1
   428
      high_cost = max_cost * 2;
alpar@1
   429
      for (; i < n_grid_arc; i++, arc_ptr++)
alpar@1
   430
         arc_ptr->cost = high_cost;
alpar@1
   431
      /* Assign costs to all other arcs. */
alpar@1
   432
      for (; i < n_arc; i++, arc_ptr++)
alpar@1
   433
         arc_ptr->cost = random(csa, arc_costs.parameter);
alpar@1
   434
      return;
alpar@1
   435
}
alpar@1
   436
alpar@1
   437
static void assign_imbalance(struct csa *csa)
alpar@1
   438
{     /* Assign an imbalance to each node. */
alpar@1
   439
      int total, i;
alpar@1
   440
      double avg;
alpar@1
   441
      struct imbalance *ptr;
alpar@1
   442
      /* assign the supply nodes */
alpar@1
   443
      avg = 2.0 * t_supply / n_source;
alpar@1
   444
      do
alpar@1
   445
      {  for (i = 1, total = t_supply, ptr = source_list + 1;
alpar@1
   446
            i < n_source; i++, ptr++)
alpar@1
   447
         {  ptr->supply = (int)(randy(csa) * avg + 0.5);
alpar@1
   448
            total -= ptr->supply;
alpar@1
   449
         }
alpar@1
   450
         source_list->supply = total;
alpar@1
   451
      }
alpar@1
   452
      /* redo all if the assignment "overshooted" */
alpar@1
   453
      while (total <= 0);
alpar@1
   454
      /* assign the demand nodes */
alpar@1
   455
      avg = -2.0 * t_supply / n_sink;
alpar@1
   456
      do
alpar@1
   457
      {  for (i = 1, total = t_supply, ptr = sink_list + 1;
alpar@1
   458
            i < n_sink; i++, ptr++)
alpar@1
   459
         {  ptr->supply = (int)(randy(csa) * avg - 0.5);
alpar@1
   460
            total += ptr->supply;
alpar@1
   461
         }
alpar@1
   462
         sink_list->supply = - total;
alpar@1
   463
      }
alpar@1
   464
      while (total <= 0);
alpar@1
   465
      return;
alpar@1
   466
}
alpar@1
   467
alpar@1
   468
static int exponential(struct csa *csa, double lambda[1])
alpar@1
   469
{     /* Returns an "exponentially distributed" integer with parameter
alpar@1
   470
         lambda. */
alpar@1
   471
      return ((int)(- lambda[0] * log((double)randy(csa)) + 0.5));
alpar@1
   472
}
alpar@1
   473
alpar@1
   474
static struct arcs *gen_additional_arcs(struct csa *csa, struct arcs
alpar@1
   475
      *arc_ptr)
alpar@1
   476
{     /* Generate an arc from each source to the supernode and from
alpar@1
   477
         supernode to each sink. */
alpar@1
   478
      int i;
alpar@1
   479
      for (i = 0; i < n_source; i++, arc_ptr++)
alpar@1
   480
      {  arc_ptr->from = source_list[i].node;
alpar@1
   481
         arc_ptr->to = n_node;
alpar@1
   482
      }
alpar@1
   483
      for (i = 0; i < n_sink; i++, arc_ptr++)
alpar@1
   484
      {  arc_ptr->to = sink_list[i].node;
alpar@1
   485
         arc_ptr->from = n_node;
alpar@1
   486
      }
alpar@1
   487
      return arc_ptr;
alpar@1
   488
}
alpar@1
   489
alpar@1
   490
static struct arcs *gen_basic_grid(struct csa *csa, struct arcs
alpar@1
   491
      *arc_ptr)
alpar@1
   492
{     /* Generate the basic grid. */
alpar@1
   493
      int direction = 1, i, j, k;
alpar@1
   494
      if (two_way)
alpar@1
   495
      {  /* Generate an arc in each direction. */
alpar@1
   496
         for (i = 1; i < n_node; i += n1)
alpar@1
   497
         {  for (j = i, k = j + n1 - 1; j < k; j++)
alpar@1
   498
            {  arc_ptr->from = j;
alpar@1
   499
               arc_ptr->to = j + 1;
alpar@1
   500
               arc_ptr++;
alpar@1
   501
               arc_ptr->from = j + 1;
alpar@1
   502
               arc_ptr->to = j;
alpar@1
   503
               arc_ptr++;
alpar@1
   504
            }
alpar@1
   505
         }
alpar@1
   506
         for (i = 1; i <= n1; i++)
alpar@1
   507
         {  for (j = i + n1; j < n_node; j += n1)
alpar@1
   508
            {  arc_ptr->from = j;
alpar@1
   509
               arc_ptr->to = j - n1;
alpar@1
   510
               arc_ptr++;
alpar@1
   511
               arc_ptr->from = j - n1;
alpar@1
   512
               arc_ptr->to = j;
alpar@1
   513
               arc_ptr++;
alpar@1
   514
            }
alpar@1
   515
         }
alpar@1
   516
      }
alpar@1
   517
      else
alpar@1
   518
      {  /* Generate one arc in each direction. */
alpar@1
   519
         for (i = 1; i < n_node; i += n1)
alpar@1
   520
         {  if (direction == 1)
alpar@1
   521
               j = i;
alpar@1
   522
            else
alpar@1
   523
               j = i + 1;
alpar@1
   524
            for (k = j + n1 - 1; j < k; j++)
alpar@1
   525
            {  arc_ptr->from = j;
alpar@1
   526
               arc_ptr->to = j + direction;
alpar@1
   527
               arc_ptr++;
alpar@1
   528
            }
alpar@1
   529
            direction = - direction;
alpar@1
   530
         }
alpar@1
   531
         for (i = 1; i <= n1; i++)
alpar@1
   532
         {  j = i + n1;
alpar@1
   533
            if (direction == 1)
alpar@1
   534
            {  for (; j < n_node; j += n1)
alpar@1
   535
               {  arc_ptr->from = j - n1;
alpar@1
   536
                  arc_ptr->to = j;
alpar@1
   537
                  arc_ptr++;
alpar@1
   538
               }
alpar@1
   539
            }
alpar@1
   540
            else
alpar@1
   541
            {  for (; j < n_node; j += n1)
alpar@1
   542
               {  arc_ptr->from = j - n1;
alpar@1
   543
                  arc_ptr->to = j;
alpar@1
   544
                  arc_ptr++;
alpar@1
   545
               }
alpar@1
   546
            }
alpar@1
   547
            direction = - direction;
alpar@1
   548
         }
alpar@1
   549
      }
alpar@1
   550
      return arc_ptr;
alpar@1
   551
}
alpar@1
   552
alpar@1
   553
static void gen_more_arcs(struct csa *csa, struct arcs *arc_ptr)
alpar@1
   554
{     /* Generate random arcs to meet the specified density. */
alpar@1
   555
      int i;
alpar@1
   556
      double ab[2];
alpar@1
   557
      ab[0] = 0.9;
alpar@1
   558
      ab[1] = n_node - 0.99;  /* upper limit is n_node-1 because the
alpar@1
   559
                                 supernode cannot be selected */
alpar@1
   560
      for (i = n_grid_arc; i < n_arc; i++, arc_ptr++)
alpar@1
   561
      {  arc_ptr->from = uniform(csa, ab);
alpar@1
   562
         arc_ptr->to = uniform(csa, ab);
alpar@1
   563
         if (arc_ptr->from == arc_ptr->to)
alpar@1
   564
         {  arc_ptr--;
alpar@1
   565
            i--;
alpar@1
   566
         }
alpar@1
   567
      }
alpar@1
   568
      return;
alpar@1
   569
}
alpar@1
   570
alpar@1
   571
static void generate(struct csa *csa)
alpar@1
   572
{     /* Generate a random network. */
alpar@1
   573
      struct arcs *arc_ptr = arc_list;
alpar@1
   574
      arc_ptr = gen_basic_grid(csa, arc_ptr);
alpar@1
   575
      select_source_sinks(csa);
alpar@1
   576
      arc_ptr = gen_additional_arcs(csa, arc_ptr);
alpar@1
   577
      gen_more_arcs(csa, arc_ptr);
alpar@1
   578
      assign_costs(csa);
alpar@1
   579
      assign_capacities(csa);
alpar@1
   580
      assign_imbalance(csa);
alpar@1
   581
      return;
alpar@1
   582
}
alpar@1
   583
alpar@1
   584
static void output(struct csa *csa)
alpar@1
   585
{     /* Output the network in DIMACS format. */
alpar@1
   586
      struct arcs *arc_ptr;
alpar@1
   587
      struct imbalance *imb_ptr;
alpar@1
   588
      int i;
alpar@1
   589
      if (G != NULL) goto skip;
alpar@1
   590
      /* Output "c", "p" records. */
alpar@1
   591
      xprintf("c generated by GRIDGEN\n");
alpar@1
   592
      xprintf("c seed %d\n", seed_original);
alpar@1
   593
      xprintf("c nodes %d\n", n_node);
alpar@1
   594
      xprintf("c grid size %d X %d\n", n1, n2);
alpar@1
   595
      xprintf("c sources %d sinks %d\n", n_source, n_sink);
alpar@1
   596
      xprintf("c avg. degree %d\n", avg_degree);
alpar@1
   597
      xprintf("c supply %d\n", t_supply);
alpar@1
   598
      switch (arc_costs.distribution)
alpar@1
   599
      {  case UNIFORM:
alpar@1
   600
            xprintf("c arc costs: UNIFORM distr. min %d max %d\n",
alpar@1
   601
               (int)arc_costs.parameter[0],
alpar@1
   602
               (int)arc_costs.parameter[1]);
alpar@1
   603
            break;
alpar@1
   604
         case EXPONENTIAL:
alpar@1
   605
            xprintf("c arc costs: EXPONENTIAL distr. lambda %d\n",
alpar@1
   606
               (int)arc_costs.parameter[0]);
alpar@1
   607
            break;
alpar@1
   608
         default:
alpar@1
   609
            xassert(csa != csa);
alpar@1
   610
      }
alpar@1
   611
      switch (capacities.distribution)
alpar@1
   612
      {  case UNIFORM:
alpar@1
   613
            xprintf("c arc caps :  UNIFORM distr. min %d max %d\n",
alpar@1
   614
               (int)capacities.parameter[0],
alpar@1
   615
               (int)capacities.parameter[1]);
alpar@1
   616
            break;
alpar@1
   617
         case EXPONENTIAL:
alpar@1
   618
            xprintf("c arc caps :  EXPONENTIAL distr. %d lambda %d\n",
alpar@1
   619
               (int)capacities.parameter[0]);
alpar@1
   620
            break;
alpar@1
   621
         default:
alpar@1
   622
            xassert(csa != csa);
alpar@1
   623
      }
alpar@1
   624
skip: if (G == NULL)
alpar@1
   625
         xprintf("p min %d %d\n", n_node, n_arc);
alpar@1
   626
      else
alpar@1
   627
      {  glp_add_vertices(G, n_node);
alpar@1
   628
         if (v_rhs >= 0)
alpar@1
   629
         {  double zero = 0.0;
alpar@1
   630
            for (i = 1; i <= n_node; i++)
alpar@1
   631
            {  glp_vertex *v = G->v[i];
alpar@1
   632
               memcpy((char *)v->data + v_rhs, &zero, sizeof(double));
alpar@1
   633
            }
alpar@1
   634
         }
alpar@1
   635
      }
alpar@1
   636
      /* Output "n node supply". */
alpar@1
   637
      for (i = 0, imb_ptr = source_list; i < n_source; i++, imb_ptr++)
alpar@1
   638
      {  if (G == NULL)
alpar@1
   639
            xprintf("n %d %d\n", imb_ptr->node, imb_ptr->supply);
alpar@1
   640
         else
alpar@1
   641
         {  if (v_rhs >= 0)
alpar@1
   642
            {  double temp = (double)imb_ptr->supply;
alpar@1
   643
               glp_vertex *v = G->v[imb_ptr->node];
alpar@1
   644
               memcpy((char *)v->data + v_rhs, &temp, sizeof(double));
alpar@1
   645
            }
alpar@1
   646
         }
alpar@1
   647
      }
alpar@1
   648
      for (i = 0, imb_ptr = sink_list; i < n_sink; i++, imb_ptr++)
alpar@1
   649
      {  if (G == NULL)
alpar@1
   650
            xprintf("n %d %d\n", imb_ptr->node, imb_ptr->supply);
alpar@1
   651
         else
alpar@1
   652
         {  if (v_rhs >= 0)
alpar@1
   653
            {  double temp = (double)imb_ptr->supply;
alpar@1
   654
               glp_vertex *v = G->v[imb_ptr->node];
alpar@1
   655
               memcpy((char *)v->data + v_rhs, &temp, sizeof(double));
alpar@1
   656
            }
alpar@1
   657
         }
alpar@1
   658
      }
alpar@1
   659
      /* Output "a from to lowcap=0 hicap cost". */
alpar@1
   660
      for (i = 0, arc_ptr = arc_list; i < n_arc; i++, arc_ptr++)
alpar@1
   661
      {  if (G == NULL)
alpar@1
   662
            xprintf("a %d %d 0 %d %d\n", arc_ptr->from, arc_ptr->to,
alpar@1
   663
               arc_ptr->u, arc_ptr->cost);
alpar@1
   664
         else
alpar@1
   665
         {  glp_arc *a = glp_add_arc(G, arc_ptr->from, arc_ptr->to);
alpar@1
   666
            if (a_cap >= 0)
alpar@1
   667
            {  double temp = (double)arc_ptr->u;
alpar@1
   668
               memcpy((char *)a->data + a_cap, &temp, sizeof(double));
alpar@1
   669
            }
alpar@1
   670
            if (a_cost >= 0)
alpar@1
   671
            {  double temp = (double)arc_ptr->cost;
alpar@1
   672
               memcpy((char *)a->data + a_cost, &temp, sizeof(double));
alpar@1
   673
            }
alpar@1
   674
         }
alpar@1
   675
      }
alpar@1
   676
      return;
alpar@1
   677
}
alpar@1
   678
alpar@1
   679
static double randy(struct csa *csa)
alpar@1
   680
{     /* Returns a random number between 0.0 and 1.0.
alpar@1
   681
         See Ward Cheney & David Kincaid, "Numerical Mathematics and
alpar@1
   682
         Computing," 2Ed, pp. 335. */
alpar@1
   683
      seed = 16807 * seed % 2147483647;
alpar@1
   684
      if (seed < 0) seed = - seed;
alpar@1
   685
      return seed * 4.6566128752459e-10;
alpar@1
   686
}
alpar@1
   687
alpar@1
   688
static void select_source_sinks(struct csa *csa)
alpar@1
   689
{     /* Randomly select the source nodes and sink nodes. */
alpar@1
   690
      int i, *int_ptr;
alpar@1
   691
      int *temp_list;   /* a temporary list of nodes */
alpar@1
   692
      struct imbalance *ptr;
alpar@1
   693
      double ab[2];     /* parameter for random number generator */
alpar@1
   694
      ab[0] = 0.9;
alpar@1
   695
      ab[1] = n_node - 0.99;  /* upper limit is n_node-1 because the
alpar@1
   696
                                 supernode cannot be selected */
alpar@1
   697
      temp_list = xcalloc(n_node, sizeof(int));
alpar@1
   698
      for (i = 0, int_ptr = temp_list; i < n_node; i++, int_ptr++)
alpar@1
   699
         *int_ptr = 0;
alpar@1
   700
      /* Select the source nodes. */
alpar@1
   701
      for (i = 0, ptr = source_list; i < n_source; i++, ptr++)
alpar@1
   702
      {  ptr->node = uniform(csa, ab);
alpar@1
   703
         if (temp_list[ptr->node] == 1) /* check for duplicates */
alpar@1
   704
         {  ptr--;
alpar@1
   705
            i--;
alpar@1
   706
         }
alpar@1
   707
         else
alpar@1
   708
            temp_list[ptr->node] = 1;
alpar@1
   709
      }
alpar@1
   710
      /* Select the sink nodes. */
alpar@1
   711
      for (i = 0, ptr = sink_list; i < n_sink; i++, ptr++)
alpar@1
   712
      {  ptr->node = uniform(csa, ab);
alpar@1
   713
         if (temp_list[ptr->node] == 1)
alpar@1
   714
         {  ptr--;
alpar@1
   715
            i--;
alpar@1
   716
         }
alpar@1
   717
         else
alpar@1
   718
            temp_list[ptr->node] = 1;
alpar@1
   719
      }
alpar@1
   720
      xfree(temp_list);
alpar@1
   721
      return;
alpar@1
   722
}
alpar@1
   723
alpar@1
   724
int uniform(struct csa *csa, double a[2])
alpar@1
   725
{     /* Generates an integer uniformly selected from [a[0],a[1]]. */
alpar@1
   726
      return (int)((a[1] - a[0]) * randy(csa) + a[0] + 0.5);
alpar@1
   727
}
alpar@1
   728
alpar@1
   729
/**********************************************************************/
alpar@1
   730
alpar@1
   731
#if 0
alpar@1
   732
int main(void)
alpar@1
   733
{     int parm[1+14];
alpar@1
   734
      double temp;
alpar@1
   735
      scanf("%d", &parm[1]);
alpar@1
   736
      scanf("%d", &parm[2]);
alpar@1
   737
      scanf("%d", &parm[3]);
alpar@1
   738
      scanf("%d", &parm[4]);
alpar@1
   739
      scanf("%d", &parm[5]);
alpar@1
   740
      scanf("%d", &parm[6]);
alpar@1
   741
      scanf("%d", &parm[7]);
alpar@1
   742
      scanf("%d", &parm[8]);
alpar@1
   743
      scanf("%d", &parm[9]);
alpar@1
   744
      if (parm[9] == 1)
alpar@1
   745
      {  scanf("%d", &parm[10]);
alpar@1
   746
         scanf("%d", &parm[11]);
alpar@1
   747
      }
alpar@1
   748
      else
alpar@1
   749
      {  scanf("%le", &temp);
alpar@1
   750
         parm[10] = (int)(100.0 * temp + .5);
alpar@1
   751
         parm[11] = 0;
alpar@1
   752
      }
alpar@1
   753
      scanf("%d", &parm[12]);
alpar@1
   754
      if (parm[12] == 1)
alpar@1
   755
      {  scanf("%d", &parm[13]);
alpar@1
   756
         scanf("%d", &parm[14]);
alpar@1
   757
      }
alpar@1
   758
      else
alpar@1
   759
      {  scanf("%le", &temp);
alpar@1
   760
         parm[13] = (int)(100.0 * temp + .5);
alpar@1
   761
         parm[14] = 0;
alpar@1
   762
      }
alpar@1
   763
      glp_gridgen(NULL, 0, 0, 0, parm);
alpar@1
   764
      return 0;
alpar@1
   765
}
alpar@1
   766
#endif
alpar@1
   767
alpar@1
   768
/* eof */