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 */
|