lemon-project-template-glpk
comparison 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 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:71ceecb470ba |
---|---|
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 */ |