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