lemon-project-template-glpk
diff deps/glpk/src/glpnet04.c @ 9:33de93886c88
Import GLPK 4.47
author | Alpar Juttner <alpar@cs.elte.hu> |
---|---|
date | Sun, 06 Nov 2011 20:59:10 +0100 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/deps/glpk/src/glpnet04.c Sun Nov 06 20:59:10 2011 +0100 1.3 @@ -0,0 +1,768 @@ 1.4 +/* glpnet04.c (grid-like network problem generator) */ 1.5 + 1.6 +/*********************************************************************** 1.7 +* This code is part of GLPK (GNU Linear Programming Kit). 1.8 +* 1.9 +* This code is a modified version of the program GRIDGEN, a grid-like 1.10 +* network problem generator developed by Yusin Lee and Jim Orlin. 1.11 +* The original code is publically available on the DIMACS ftp site at: 1.12 +* <ftp://dimacs.rutgers.edu/pub/netflow/generators/network/gridgen>. 1.13 +* 1.14 +* All changes concern only the program interface, so this modified 1.15 +* version produces exactly the same instances as the original version. 1.16 +* 1.17 +* Changes were made by Andrew Makhorin <mao@gnu.org>. 1.18 +* 1.19 +* GLPK is free software: you can redistribute it and/or modify it 1.20 +* under the terms of the GNU General Public License as published by 1.21 +* the Free Software Foundation, either version 3 of the License, or 1.22 +* (at your option) any later version. 1.23 +* 1.24 +* GLPK is distributed in the hope that it will be useful, but WITHOUT 1.25 +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 1.26 +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 1.27 +* License for more details. 1.28 +* 1.29 +* You should have received a copy of the GNU General Public License 1.30 +* along with GLPK. If not, see <http://www.gnu.org/licenses/>. 1.31 +***********************************************************************/ 1.32 + 1.33 +#include "glpapi.h" 1.34 + 1.35 +/*********************************************************************** 1.36 +* NAME 1.37 +* 1.38 +* glp_gridgen - grid-like network problem generator 1.39 +* 1.40 +* SYNOPSIS 1.41 +* 1.42 +* int glp_gridgen(glp_graph *G, int v_rhs, int a_cap, int a_cost, 1.43 +* const int parm[1+14]); 1.44 +* 1.45 +* DESCRIPTION 1.46 +* 1.47 +* The routine glp_gridgen is a grid-like network problem generator 1.48 +* developed by Yusin Lee and Jim Orlin. 1.49 +* 1.50 +* The parameter G specifies the graph object, to which the generated 1.51 +* problem data have to be stored. Note that on entry the graph object 1.52 +* is erased with the routine glp_erase_graph. 1.53 +* 1.54 +* The parameter v_rhs specifies an offset of the field of type double 1.55 +* in the vertex data block, to which the routine stores the supply or 1.56 +* demand value. If v_rhs < 0, the value is not stored. 1.57 +* 1.58 +* The parameter a_cap specifies an offset of the field of type double 1.59 +* in the arc data block, to which the routine stores the arc capacity. 1.60 +* If a_cap < 0, the capacity is not stored. 1.61 +* 1.62 +* The parameter a_cost specifies an offset of the field of type double 1.63 +* in the arc data block, to which the routine stores the per-unit cost 1.64 +* if the arc flow. If a_cost < 0, the cost is not stored. 1.65 +* 1.66 +* The array parm contains description of the network to be generated: 1.67 +* 1.68 +* parm[0] not used 1.69 +* parm[1] two-ways arcs indicator: 1.70 +* 1 - if links in both direction should be generated 1.71 +* 0 - otherwise 1.72 +* parm[2] random number seed (a positive integer) 1.73 +* parm[3] number of nodes (the number of nodes generated might be 1.74 +* slightly different to make the network a grid) 1.75 +* parm[4] grid width 1.76 +* parm[5] number of sources 1.77 +* parm[6] number of sinks 1.78 +* parm[7] average degree 1.79 +* parm[8] total flow 1.80 +* parm[9] distribution of arc costs: 1.81 +* 1 - uniform 1.82 +* 2 - exponential 1.83 +* parm[10] lower bound for arc cost (uniform) 1.84 +* 100 * lambda (exponential) 1.85 +* parm[11] upper bound for arc cost (uniform) 1.86 +* not used (exponential) 1.87 +* parm[12] distribution of arc capacities: 1.88 +* 1 - uniform 1.89 +* 2 - exponential 1.90 +* parm[13] lower bound for arc capacity (uniform) 1.91 +* 100 * lambda (exponential) 1.92 +* parm[14] upper bound for arc capacity (uniform) 1.93 +* not used (exponential) 1.94 +* 1.95 +* RETURNS 1.96 +* 1.97 +* If the instance was successfully generated, the routine glp_gridgen 1.98 +* returns zero; otherwise, if specified parameters are inconsistent, 1.99 +* the routine returns a non-zero error code. 1.100 +* 1.101 +* COMMENTS 1.102 +* 1.103 +* This network generator generates a grid-like network plus a super 1.104 +* node. In additional to the arcs connecting the nodes in the grid, 1.105 +* there is an arc from each supply node to the super node and from the 1.106 +* super node to each demand node to guarantee feasiblity. These arcs 1.107 +* have very high costs and very big capacities. 1.108 +* 1.109 +* The idea of this network generator is as follows: First, a grid of 1.110 +* n1 * n2 is generated. For example, 5 * 3. The nodes are numbered as 1.111 +* 1 to 15, and the supernode is numbered as n1*n2+1. Then arcs between 1.112 +* adjacent nodes are generated. For these arcs, the user is allowed to 1.113 +* specify either to generate two-way arcs or one-way arcs. If two-way 1.114 +* arcs are to be generated, two arcs, one in each direction, will be 1.115 +* generated between each adjacent node pairs. Otherwise, only one arc 1.116 +* will be generated. If this is the case, the arcs will be generated 1.117 +* in alterntive directions as shown below. 1.118 +* 1.119 +* 1 ---> 2 ---> 3 ---> 4 ---> 5 1.120 +* | ^ | ^ | 1.121 +* | | | | | 1.122 +* V | V | V 1.123 +* 6 <--- 7 <--- 8 <--- 9 <--- 10 1.124 +* | ^ | ^ | 1.125 +* | | | | | 1.126 +* V | V | V 1.127 +* 11 --->12 --->13 --->14 ---> 15 1.128 +* 1.129 +* Then the arcs between the super node and the source/sink nodes are 1.130 +* added as mentioned before. If the number of arcs still doesn't reach 1.131 +* the requirement, additional arcs will be added by uniformly picking 1.132 +* random node pairs. There is no checking to prevent multiple arcs 1.133 +* between any pair of nodes. However, there will be no self-arcs (arcs 1.134 +* that poins back to its tail node) in the network. 1.135 +* 1.136 +* The source and sink nodes are selected uniformly in the network, and 1.137 +* the imbalances of each source/sink node are also assigned by uniform 1.138 +* distribution. */ 1.139 + 1.140 +struct stat_para 1.141 +{ /* structure for statistical distributions */ 1.142 + int distribution; 1.143 + /* the distribution: */ 1.144 +#define UNIFORM 1 /* uniform distribution */ 1.145 +#define EXPONENTIAL 2 /* exponential distribution */ 1.146 + double parameter[5]; 1.147 + /* the parameters of the distribution */ 1.148 +}; 1.149 + 1.150 +struct arcs 1.151 +{ int from; 1.152 + /* the FROM node of that arc */ 1.153 + int to; 1.154 + /* the TO node of that arc */ 1.155 + int cost; 1.156 + /* original cost of that arc */ 1.157 + int u; 1.158 + /* capacity of the arc */ 1.159 +}; 1.160 + 1.161 +struct imbalance 1.162 +{ int node; 1.163 + /* Node ID */ 1.164 + int supply; 1.165 + /* Supply of that node */ 1.166 +}; 1.167 + 1.168 +struct csa 1.169 +{ /* common storage area */ 1.170 + glp_graph *G; 1.171 + int v_rhs, a_cap, a_cost; 1.172 + int seed; 1.173 + /* random number seed */ 1.174 + int seed_original; 1.175 + /* the original seed from input */ 1.176 + int two_way; 1.177 + /* 0: generate arcs in both direction for the basic grid, except 1.178 + for the arcs to/from the super node. 1: o/w */ 1.179 + int n_node; 1.180 + /* total number of nodes in the network, numbered 1 to n_node, 1.181 + including the super node, which is the last one */ 1.182 + int n_arc; 1.183 + /* total number of arcs in the network, counting EVERY arc. */ 1.184 + int n_grid_arc; 1.185 + /* number of arcs in the basic grid, including the arcs to/from 1.186 + the super node */ 1.187 + int n_source, n_sink; 1.188 + /* number of source and sink nodes */ 1.189 + int avg_degree; 1.190 + /* average degree, arcs to and from the super node are counted */ 1.191 + int t_supply; 1.192 + /* total supply in the network */ 1.193 + int n1, n2; 1.194 + /* the two edges of the network grid. n1 >= n2 */ 1.195 + struct imbalance *source_list, *sink_list; 1.196 + /* head of the array of source/sink nodes */ 1.197 + struct stat_para arc_costs; 1.198 + /* the distribution of arc costs */ 1.199 + struct stat_para capacities; 1.200 + /* distribution of the capacities of the arcs */ 1.201 + struct arcs *arc_list; 1.202 + /* head of the arc list array. Arcs in this array are in the 1.203 + order of grid_arcs, arcs to/from super node, and other arcs */ 1.204 +}; 1.205 + 1.206 +#define G (csa->G) 1.207 +#define v_rhs (csa->v_rhs) 1.208 +#define a_cap (csa->a_cap) 1.209 +#define a_cost (csa->a_cost) 1.210 +#define seed (csa->seed) 1.211 +#define seed_original (csa->seed_original) 1.212 +#define two_way (csa->two_way) 1.213 +#define n_node (csa->n_node) 1.214 +#define n_arc (csa->n_arc) 1.215 +#define n_grid_arc (csa->n_grid_arc) 1.216 +#define n_source (csa->n_source) 1.217 +#define n_sink (csa->n_sink) 1.218 +#define avg_degree (csa->avg_degree) 1.219 +#define t_supply (csa->t_supply) 1.220 +#define n1 (csa->n1) 1.221 +#define n2 (csa->n2) 1.222 +#define source_list (csa->source_list) 1.223 +#define sink_list (csa->sink_list) 1.224 +#define arc_costs (csa->arc_costs) 1.225 +#define capacities (csa->capacities) 1.226 +#define arc_list (csa->arc_list) 1.227 + 1.228 +static void assign_capacities(struct csa *csa); 1.229 +static void assign_costs(struct csa *csa); 1.230 +static void assign_imbalance(struct csa *csa); 1.231 +static int exponential(struct csa *csa, double lambda[1]); 1.232 +static struct arcs *gen_additional_arcs(struct csa *csa, struct arcs 1.233 + *arc_ptr); 1.234 +static struct arcs *gen_basic_grid(struct csa *csa, struct arcs 1.235 + *arc_ptr); 1.236 +static void gen_more_arcs(struct csa *csa, struct arcs *arc_ptr); 1.237 +static void generate(struct csa *csa); 1.238 +static void output(struct csa *csa); 1.239 +static double randy(struct csa *csa); 1.240 +static void select_source_sinks(struct csa *csa); 1.241 +static int uniform(struct csa *csa, double a[2]); 1.242 + 1.243 +int glp_gridgen(glp_graph *G_, int _v_rhs, int _a_cap, int _a_cost, 1.244 + const int parm[1+14]) 1.245 +{ struct csa _csa, *csa = &_csa; 1.246 + int n, ret; 1.247 + G = G_; 1.248 + v_rhs = _v_rhs; 1.249 + a_cap = _a_cap; 1.250 + a_cost = _a_cost; 1.251 + if (G != NULL) 1.252 + { if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double)) 1.253 + xerror("glp_gridgen: v_rhs = %d; invalid offset\n", v_rhs); 1.254 + if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) 1.255 + xerror("glp_gridgen: a_cap = %d; invalid offset\n", a_cap); 1.256 + if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) 1.257 + xerror("glp_gridgen: a_cost = %d; invalid offset\n", a_cost) 1.258 + ; 1.259 + } 1.260 + /* Check the parameters for consistency. */ 1.261 + if (!(parm[1] == 0 || parm[1] == 1)) 1.262 + { ret = 1; 1.263 + goto done; 1.264 + } 1.265 + if (parm[2] < 1) 1.266 + { ret = 2; 1.267 + goto done; 1.268 + } 1.269 + if (!(10 <= parm[3] && parm[3] <= 40000)) 1.270 + { ret = 3; 1.271 + goto done; 1.272 + } 1.273 + if (!(1 <= parm[4] && parm[4] <= 40000)) 1.274 + { ret = 4; 1.275 + goto done; 1.276 + } 1.277 + if (!(parm[5] >= 0 && parm[6] >= 0 && parm[5] + parm[6] <= 1.278 + parm[3])) 1.279 + { ret = 5; 1.280 + goto done; 1.281 + } 1.282 + if (!(1 <= parm[7] && parm[7] <= parm[3])) 1.283 + { ret = 6; 1.284 + goto done; 1.285 + } 1.286 + if (parm[8] < 0) 1.287 + { ret = 7; 1.288 + goto done; 1.289 + } 1.290 + if (!(parm[9] == 1 || parm[9] == 2)) 1.291 + { ret = 8; 1.292 + goto done; 1.293 + } 1.294 + if (parm[9] == 1 && parm[10] > parm[11] || 1.295 + parm[9] == 2 && parm[10] < 1) 1.296 + { ret = 9; 1.297 + goto done; 1.298 + } 1.299 + if (!(parm[12] == 1 || parm[12] == 2)) 1.300 + { ret = 10; 1.301 + goto done; 1.302 + } 1.303 + if (parm[12] == 1 && !(0 <= parm[13] && parm[13] <= parm[14]) || 1.304 + parm[12] == 2 && parm[13] < 1) 1.305 + { ret = 11; 1.306 + goto done; 1.307 + } 1.308 + /* Initialize the graph object. */ 1.309 + if (G != NULL) 1.310 + { glp_erase_graph(G, G->v_size, G->a_size); 1.311 + glp_set_graph_name(G, "GRIDGEN"); 1.312 + } 1.313 + /* Copy the generator parameters. */ 1.314 + two_way = parm[1]; 1.315 + seed_original = seed = parm[2]; 1.316 + n_node = parm[3]; 1.317 + n = parm[4]; 1.318 + n_source = parm[5]; 1.319 + n_sink = parm[6]; 1.320 + avg_degree = parm[7]; 1.321 + t_supply = parm[8]; 1.322 + arc_costs.distribution = parm[9]; 1.323 + if (parm[9] == 1) 1.324 + { arc_costs.parameter[0] = parm[10]; 1.325 + arc_costs.parameter[1] = parm[11]; 1.326 + } 1.327 + else 1.328 + { arc_costs.parameter[0] = (double)parm[10] / 100.0; 1.329 + arc_costs.parameter[1] = 0.0; 1.330 + } 1.331 + capacities.distribution = parm[12]; 1.332 + if (parm[12] == 1) 1.333 + { capacities.parameter[0] = parm[13]; 1.334 + capacities.parameter[1] = parm[14]; 1.335 + } 1.336 + else 1.337 + { capacities.parameter[0] = (double)parm[13] / 100.0; 1.338 + capacities.parameter[1] = 0.0; 1.339 + } 1.340 + /* Calculate the edge lengths of the grid according to the 1.341 + input. */ 1.342 + if (n * n >= n_node) 1.343 + { n1 = n; 1.344 + n2 = (int)((double)n_node / (double)n + 0.5); 1.345 + } 1.346 + else 1.347 + { n2 = n; 1.348 + n1 = (int)((double)n_node / (double)n + 0.5); 1.349 + } 1.350 + /* Recalculate the total number of nodes and plus 1 for the super 1.351 + node. */ 1.352 + n_node = n1 * n2 + 1; 1.353 + n_arc = n_node * avg_degree; 1.354 + n_grid_arc = (two_way + 1) * ((n1 - 1) * n2 + (n2 - 1) * n1) + 1.355 + n_source + n_sink; 1.356 + if (n_grid_arc > n_arc) n_arc = n_grid_arc; 1.357 + arc_list = xcalloc(n_arc, sizeof(struct arcs)); 1.358 + source_list = xcalloc(n_source, sizeof(struct imbalance)); 1.359 + sink_list = xcalloc(n_sink, sizeof(struct imbalance)); 1.360 + /* Generate a random network. */ 1.361 + generate(csa); 1.362 + /* Output the network. */ 1.363 + output(csa); 1.364 + /* Free all allocated memory. */ 1.365 + xfree(arc_list); 1.366 + xfree(source_list); 1.367 + xfree(sink_list); 1.368 + /* The instance has been successfully generated. */ 1.369 + ret = 0; 1.370 +done: return ret; 1.371 +} 1.372 + 1.373 +#undef random 1.374 + 1.375 +static void assign_capacities(struct csa *csa) 1.376 +{ /* Assign a capacity to each arc. */ 1.377 + struct arcs *arc_ptr = arc_list; 1.378 + int (*random)(struct csa *csa, double *); 1.379 + int i; 1.380 + /* Determine the random number generator to use. */ 1.381 + switch (arc_costs.distribution) 1.382 + { case UNIFORM: 1.383 + random = uniform; 1.384 + break; 1.385 + case EXPONENTIAL: 1.386 + random = exponential; 1.387 + break; 1.388 + default: 1.389 + xassert(csa != csa); 1.390 + } 1.391 + /* Assign capacities to grid arcs. */ 1.392 + for (i = n_source + n_sink; i < n_grid_arc; i++, arc_ptr++) 1.393 + arc_ptr->u = random(csa, capacities.parameter); 1.394 + i = i - n_source - n_sink; 1.395 + /* Assign capacities to arcs to/from supernode. */ 1.396 + for (; i < n_grid_arc; i++, arc_ptr++) 1.397 + arc_ptr->u = t_supply; 1.398 + /* Assign capacities to all other arcs. */ 1.399 + for (; i < n_arc; i++, arc_ptr++) 1.400 + arc_ptr->u = random(csa, capacities.parameter); 1.401 + return; 1.402 +} 1.403 + 1.404 +static void assign_costs(struct csa *csa) 1.405 +{ /* Assign a cost to each arc. */ 1.406 + struct arcs *arc_ptr = arc_list; 1.407 + int (*random)(struct csa *csa, double *); 1.408 + int i; 1.409 + /* A high cost assigned to arcs to/from the supernode. */ 1.410 + int high_cost; 1.411 + /* The maximum cost assigned to arcs in the base grid. */ 1.412 + int max_cost = 0; 1.413 + /* Determine the random number generator to use. */ 1.414 + switch (arc_costs.distribution) 1.415 + { case UNIFORM: 1.416 + random = uniform; 1.417 + break; 1.418 + case EXPONENTIAL: 1.419 + random = exponential; 1.420 + break; 1.421 + default: 1.422 + xassert(csa != csa); 1.423 + } 1.424 + /* Assign costs to arcs in the base grid. */ 1.425 + for (i = n_source + n_sink; i < n_grid_arc; i++, arc_ptr++) 1.426 + { arc_ptr->cost = random(csa, arc_costs.parameter); 1.427 + if (max_cost < arc_ptr->cost) max_cost = arc_ptr->cost; 1.428 + } 1.429 + i = i - n_source - n_sink; 1.430 + /* Assign costs to arcs to/from the super node. */ 1.431 + high_cost = max_cost * 2; 1.432 + for (; i < n_grid_arc; i++, arc_ptr++) 1.433 + arc_ptr->cost = high_cost; 1.434 + /* Assign costs to all other arcs. */ 1.435 + for (; i < n_arc; i++, arc_ptr++) 1.436 + arc_ptr->cost = random(csa, arc_costs.parameter); 1.437 + return; 1.438 +} 1.439 + 1.440 +static void assign_imbalance(struct csa *csa) 1.441 +{ /* Assign an imbalance to each node. */ 1.442 + int total, i; 1.443 + double avg; 1.444 + struct imbalance *ptr; 1.445 + /* assign the supply nodes */ 1.446 + avg = 2.0 * t_supply / n_source; 1.447 + do 1.448 + { for (i = 1, total = t_supply, ptr = source_list + 1; 1.449 + i < n_source; i++, ptr++) 1.450 + { ptr->supply = (int)(randy(csa) * avg + 0.5); 1.451 + total -= ptr->supply; 1.452 + } 1.453 + source_list->supply = total; 1.454 + } 1.455 + /* redo all if the assignment "overshooted" */ 1.456 + while (total <= 0); 1.457 + /* assign the demand nodes */ 1.458 + avg = -2.0 * t_supply / n_sink; 1.459 + do 1.460 + { for (i = 1, total = t_supply, ptr = sink_list + 1; 1.461 + i < n_sink; i++, ptr++) 1.462 + { ptr->supply = (int)(randy(csa) * avg - 0.5); 1.463 + total += ptr->supply; 1.464 + } 1.465 + sink_list->supply = - total; 1.466 + } 1.467 + while (total <= 0); 1.468 + return; 1.469 +} 1.470 + 1.471 +static int exponential(struct csa *csa, double lambda[1]) 1.472 +{ /* Returns an "exponentially distributed" integer with parameter 1.473 + lambda. */ 1.474 + return ((int)(- lambda[0] * log((double)randy(csa)) + 0.5)); 1.475 +} 1.476 + 1.477 +static struct arcs *gen_additional_arcs(struct csa *csa, struct arcs 1.478 + *arc_ptr) 1.479 +{ /* Generate an arc from each source to the supernode and from 1.480 + supernode to each sink. */ 1.481 + int i; 1.482 + for (i = 0; i < n_source; i++, arc_ptr++) 1.483 + { arc_ptr->from = source_list[i].node; 1.484 + arc_ptr->to = n_node; 1.485 + } 1.486 + for (i = 0; i < n_sink; i++, arc_ptr++) 1.487 + { arc_ptr->to = sink_list[i].node; 1.488 + arc_ptr->from = n_node; 1.489 + } 1.490 + return arc_ptr; 1.491 +} 1.492 + 1.493 +static struct arcs *gen_basic_grid(struct csa *csa, struct arcs 1.494 + *arc_ptr) 1.495 +{ /* Generate the basic grid. */ 1.496 + int direction = 1, i, j, k; 1.497 + if (two_way) 1.498 + { /* Generate an arc in each direction. */ 1.499 + for (i = 1; i < n_node; i += n1) 1.500 + { for (j = i, k = j + n1 - 1; j < k; j++) 1.501 + { arc_ptr->from = j; 1.502 + arc_ptr->to = j + 1; 1.503 + arc_ptr++; 1.504 + arc_ptr->from = j + 1; 1.505 + arc_ptr->to = j; 1.506 + arc_ptr++; 1.507 + } 1.508 + } 1.509 + for (i = 1; i <= n1; i++) 1.510 + { for (j = i + n1; j < n_node; j += n1) 1.511 + { arc_ptr->from = j; 1.512 + arc_ptr->to = j - n1; 1.513 + arc_ptr++; 1.514 + arc_ptr->from = j - n1; 1.515 + arc_ptr->to = j; 1.516 + arc_ptr++; 1.517 + } 1.518 + } 1.519 + } 1.520 + else 1.521 + { /* Generate one arc in each direction. */ 1.522 + for (i = 1; i < n_node; i += n1) 1.523 + { if (direction == 1) 1.524 + j = i; 1.525 + else 1.526 + j = i + 1; 1.527 + for (k = j + n1 - 1; j < k; j++) 1.528 + { arc_ptr->from = j; 1.529 + arc_ptr->to = j + direction; 1.530 + arc_ptr++; 1.531 + } 1.532 + direction = - direction; 1.533 + } 1.534 + for (i = 1; i <= n1; i++) 1.535 + { j = i + n1; 1.536 + if (direction == 1) 1.537 + { for (; j < n_node; j += n1) 1.538 + { arc_ptr->from = j - n1; 1.539 + arc_ptr->to = j; 1.540 + arc_ptr++; 1.541 + } 1.542 + } 1.543 + else 1.544 + { for (; j < n_node; j += n1) 1.545 + { arc_ptr->from = j - n1; 1.546 + arc_ptr->to = j; 1.547 + arc_ptr++; 1.548 + } 1.549 + } 1.550 + direction = - direction; 1.551 + } 1.552 + } 1.553 + return arc_ptr; 1.554 +} 1.555 + 1.556 +static void gen_more_arcs(struct csa *csa, struct arcs *arc_ptr) 1.557 +{ /* Generate random arcs to meet the specified density. */ 1.558 + int i; 1.559 + double ab[2]; 1.560 + ab[0] = 0.9; 1.561 + ab[1] = n_node - 0.99; /* upper limit is n_node-1 because the 1.562 + supernode cannot be selected */ 1.563 + for (i = n_grid_arc; i < n_arc; i++, arc_ptr++) 1.564 + { arc_ptr->from = uniform(csa, ab); 1.565 + arc_ptr->to = uniform(csa, ab); 1.566 + if (arc_ptr->from == arc_ptr->to) 1.567 + { arc_ptr--; 1.568 + i--; 1.569 + } 1.570 + } 1.571 + return; 1.572 +} 1.573 + 1.574 +static void generate(struct csa *csa) 1.575 +{ /* Generate a random network. */ 1.576 + struct arcs *arc_ptr = arc_list; 1.577 + arc_ptr = gen_basic_grid(csa, arc_ptr); 1.578 + select_source_sinks(csa); 1.579 + arc_ptr = gen_additional_arcs(csa, arc_ptr); 1.580 + gen_more_arcs(csa, arc_ptr); 1.581 + assign_costs(csa); 1.582 + assign_capacities(csa); 1.583 + assign_imbalance(csa); 1.584 + return; 1.585 +} 1.586 + 1.587 +static void output(struct csa *csa) 1.588 +{ /* Output the network in DIMACS format. */ 1.589 + struct arcs *arc_ptr; 1.590 + struct imbalance *imb_ptr; 1.591 + int i; 1.592 + if (G != NULL) goto skip; 1.593 + /* Output "c", "p" records. */ 1.594 + xprintf("c generated by GRIDGEN\n"); 1.595 + xprintf("c seed %d\n", seed_original); 1.596 + xprintf("c nodes %d\n", n_node); 1.597 + xprintf("c grid size %d X %d\n", n1, n2); 1.598 + xprintf("c sources %d sinks %d\n", n_source, n_sink); 1.599 + xprintf("c avg. degree %d\n", avg_degree); 1.600 + xprintf("c supply %d\n", t_supply); 1.601 + switch (arc_costs.distribution) 1.602 + { case UNIFORM: 1.603 + xprintf("c arc costs: UNIFORM distr. min %d max %d\n", 1.604 + (int)arc_costs.parameter[0], 1.605 + (int)arc_costs.parameter[1]); 1.606 + break; 1.607 + case EXPONENTIAL: 1.608 + xprintf("c arc costs: EXPONENTIAL distr. lambda %d\n", 1.609 + (int)arc_costs.parameter[0]); 1.610 + break; 1.611 + default: 1.612 + xassert(csa != csa); 1.613 + } 1.614 + switch (capacities.distribution) 1.615 + { case UNIFORM: 1.616 + xprintf("c arc caps : UNIFORM distr. min %d max %d\n", 1.617 + (int)capacities.parameter[0], 1.618 + (int)capacities.parameter[1]); 1.619 + break; 1.620 + case EXPONENTIAL: 1.621 + xprintf("c arc caps : EXPONENTIAL distr. %d lambda %d\n", 1.622 + (int)capacities.parameter[0]); 1.623 + break; 1.624 + default: 1.625 + xassert(csa != csa); 1.626 + } 1.627 +skip: if (G == NULL) 1.628 + xprintf("p min %d %d\n", n_node, n_arc); 1.629 + else 1.630 + { glp_add_vertices(G, n_node); 1.631 + if (v_rhs >= 0) 1.632 + { double zero = 0.0; 1.633 + for (i = 1; i <= n_node; i++) 1.634 + { glp_vertex *v = G->v[i]; 1.635 + memcpy((char *)v->data + v_rhs, &zero, sizeof(double)); 1.636 + } 1.637 + } 1.638 + } 1.639 + /* Output "n node supply". */ 1.640 + for (i = 0, imb_ptr = source_list; i < n_source; i++, imb_ptr++) 1.641 + { if (G == NULL) 1.642 + xprintf("n %d %d\n", imb_ptr->node, imb_ptr->supply); 1.643 + else 1.644 + { if (v_rhs >= 0) 1.645 + { double temp = (double)imb_ptr->supply; 1.646 + glp_vertex *v = G->v[imb_ptr->node]; 1.647 + memcpy((char *)v->data + v_rhs, &temp, sizeof(double)); 1.648 + } 1.649 + } 1.650 + } 1.651 + for (i = 0, imb_ptr = sink_list; i < n_sink; i++, imb_ptr++) 1.652 + { if (G == NULL) 1.653 + xprintf("n %d %d\n", imb_ptr->node, imb_ptr->supply); 1.654 + else 1.655 + { if (v_rhs >= 0) 1.656 + { double temp = (double)imb_ptr->supply; 1.657 + glp_vertex *v = G->v[imb_ptr->node]; 1.658 + memcpy((char *)v->data + v_rhs, &temp, sizeof(double)); 1.659 + } 1.660 + } 1.661 + } 1.662 + /* Output "a from to lowcap=0 hicap cost". */ 1.663 + for (i = 0, arc_ptr = arc_list; i < n_arc; i++, arc_ptr++) 1.664 + { if (G == NULL) 1.665 + xprintf("a %d %d 0 %d %d\n", arc_ptr->from, arc_ptr->to, 1.666 + arc_ptr->u, arc_ptr->cost); 1.667 + else 1.668 + { glp_arc *a = glp_add_arc(G, arc_ptr->from, arc_ptr->to); 1.669 + if (a_cap >= 0) 1.670 + { double temp = (double)arc_ptr->u; 1.671 + memcpy((char *)a->data + a_cap, &temp, sizeof(double)); 1.672 + } 1.673 + if (a_cost >= 0) 1.674 + { double temp = (double)arc_ptr->cost; 1.675 + memcpy((char *)a->data + a_cost, &temp, sizeof(double)); 1.676 + } 1.677 + } 1.678 + } 1.679 + return; 1.680 +} 1.681 + 1.682 +static double randy(struct csa *csa) 1.683 +{ /* Returns a random number between 0.0 and 1.0. 1.684 + See Ward Cheney & David Kincaid, "Numerical Mathematics and 1.685 + Computing," 2Ed, pp. 335. */ 1.686 + seed = 16807 * seed % 2147483647; 1.687 + if (seed < 0) seed = - seed; 1.688 + return seed * 4.6566128752459e-10; 1.689 +} 1.690 + 1.691 +static void select_source_sinks(struct csa *csa) 1.692 +{ /* Randomly select the source nodes and sink nodes. */ 1.693 + int i, *int_ptr; 1.694 + int *temp_list; /* a temporary list of nodes */ 1.695 + struct imbalance *ptr; 1.696 + double ab[2]; /* parameter for random number generator */ 1.697 + ab[0] = 0.9; 1.698 + ab[1] = n_node - 0.99; /* upper limit is n_node-1 because the 1.699 + supernode cannot be selected */ 1.700 + temp_list = xcalloc(n_node, sizeof(int)); 1.701 + for (i = 0, int_ptr = temp_list; i < n_node; i++, int_ptr++) 1.702 + *int_ptr = 0; 1.703 + /* Select the source nodes. */ 1.704 + for (i = 0, ptr = source_list; i < n_source; i++, ptr++) 1.705 + { ptr->node = uniform(csa, ab); 1.706 + if (temp_list[ptr->node] == 1) /* check for duplicates */ 1.707 + { ptr--; 1.708 + i--; 1.709 + } 1.710 + else 1.711 + temp_list[ptr->node] = 1; 1.712 + } 1.713 + /* Select the sink nodes. */ 1.714 + for (i = 0, ptr = sink_list; i < n_sink; i++, ptr++) 1.715 + { ptr->node = uniform(csa, ab); 1.716 + if (temp_list[ptr->node] == 1) 1.717 + { ptr--; 1.718 + i--; 1.719 + } 1.720 + else 1.721 + temp_list[ptr->node] = 1; 1.722 + } 1.723 + xfree(temp_list); 1.724 + return; 1.725 +} 1.726 + 1.727 +int uniform(struct csa *csa, double a[2]) 1.728 +{ /* Generates an integer uniformly selected from [a[0],a[1]]. */ 1.729 + return (int)((a[1] - a[0]) * randy(csa) + a[0] + 0.5); 1.730 +} 1.731 + 1.732 +/**********************************************************************/ 1.733 + 1.734 +#if 0 1.735 +int main(void) 1.736 +{ int parm[1+14]; 1.737 + double temp; 1.738 + scanf("%d", &parm[1]); 1.739 + scanf("%d", &parm[2]); 1.740 + scanf("%d", &parm[3]); 1.741 + scanf("%d", &parm[4]); 1.742 + scanf("%d", &parm[5]); 1.743 + scanf("%d", &parm[6]); 1.744 + scanf("%d", &parm[7]); 1.745 + scanf("%d", &parm[8]); 1.746 + scanf("%d", &parm[9]); 1.747 + if (parm[9] == 1) 1.748 + { scanf("%d", &parm[10]); 1.749 + scanf("%d", &parm[11]); 1.750 + } 1.751 + else 1.752 + { scanf("%le", &temp); 1.753 + parm[10] = (int)(100.0 * temp + .5); 1.754 + parm[11] = 0; 1.755 + } 1.756 + scanf("%d", &parm[12]); 1.757 + if (parm[12] == 1) 1.758 + { scanf("%d", &parm[13]); 1.759 + scanf("%d", &parm[14]); 1.760 + } 1.761 + else 1.762 + { scanf("%le", &temp); 1.763 + parm[13] = (int)(100.0 * temp + .5); 1.764 + parm[14] = 0; 1.765 + } 1.766 + glp_gridgen(NULL, 0, 0, 0, parm); 1.767 + return 0; 1.768 +} 1.769 +#endif 1.770 + 1.771 +/* eof */