alpar@1
|
1 |
/* glpnet03.c (Klingman's 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 the result of translation of the Fortran program NETGEN
|
alpar@1
|
7 |
* developed by Dr. Darwin Klingman, which is publically available from
|
alpar@1
|
8 |
* NETLIB at <http://www.netlib.org/lp/generators>.
|
alpar@1
|
9 |
*
|
alpar@1
|
10 |
* The translation was made by Andrew Makhorin <mao@gnu.org>.
|
alpar@1
|
11 |
*
|
alpar@1
|
12 |
* GLPK is free software: you can redistribute it and/or modify it
|
alpar@1
|
13 |
* under the terms of the GNU General Public License as published by
|
alpar@1
|
14 |
* the Free Software Foundation, either version 3 of the License, or
|
alpar@1
|
15 |
* (at your option) any later version.
|
alpar@1
|
16 |
*
|
alpar@1
|
17 |
* GLPK is distributed in the hope that it will be useful, but WITHOUT
|
alpar@1
|
18 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
alpar@1
|
19 |
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
alpar@1
|
20 |
* License for more details.
|
alpar@1
|
21 |
*
|
alpar@1
|
22 |
* You should have received a copy of the GNU General Public License
|
alpar@1
|
23 |
* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
|
alpar@1
|
24 |
***********************************************************************/
|
alpar@1
|
25 |
|
alpar@1
|
26 |
#include "glpapi.h"
|
alpar@1
|
27 |
|
alpar@1
|
28 |
/***********************************************************************
|
alpar@1
|
29 |
* NAME
|
alpar@1
|
30 |
*
|
alpar@1
|
31 |
* glp_netgen - Klingman's network problem generator
|
alpar@1
|
32 |
*
|
alpar@1
|
33 |
* SYNOPSIS
|
alpar@1
|
34 |
*
|
alpar@1
|
35 |
* int glp_netgen(glp_graph *G, int v_rhs, int a_cap, int a_cost,
|
alpar@1
|
36 |
* const int parm[1+15]);
|
alpar@1
|
37 |
*
|
alpar@1
|
38 |
* DESCRIPTION
|
alpar@1
|
39 |
*
|
alpar@1
|
40 |
* The routine glp_netgen is a network problem generator developed by
|
alpar@1
|
41 |
* Dr. Darwin Klingman. It can create capacitated and uncapacitated
|
alpar@1
|
42 |
* minimum cost flow (or transshipment), transportation, and assignment
|
alpar@1
|
43 |
* problems.
|
alpar@1
|
44 |
*
|
alpar@1
|
45 |
* The parameter G specifies the graph object, to which the generated
|
alpar@1
|
46 |
* problem data have to be stored. Note that on entry the graph object
|
alpar@1
|
47 |
* is erased with the routine glp_erase_graph.
|
alpar@1
|
48 |
*
|
alpar@1
|
49 |
* The parameter v_rhs specifies an offset of the field of type double
|
alpar@1
|
50 |
* in the vertex data block, to which the routine stores the supply or
|
alpar@1
|
51 |
* demand value. If v_rhs < 0, the value is not stored.
|
alpar@1
|
52 |
*
|
alpar@1
|
53 |
* The parameter a_cap specifies an offset of the field of type double
|
alpar@1
|
54 |
* in the arc data block, to which the routine stores the arc capacity.
|
alpar@1
|
55 |
* If a_cap < 0, the capacity is not stored.
|
alpar@1
|
56 |
*
|
alpar@1
|
57 |
* The parameter a_cost specifies an offset of the field of type double
|
alpar@1
|
58 |
* in the arc data block, to which the routine stores the per-unit cost
|
alpar@1
|
59 |
* if the arc flow. If a_cost < 0, the cost is not stored.
|
alpar@1
|
60 |
*
|
alpar@1
|
61 |
* The array parm contains description of the network to be generated:
|
alpar@1
|
62 |
*
|
alpar@1
|
63 |
* parm[0] not used
|
alpar@1
|
64 |
* parm[1] (iseed) 8-digit positive random number seed
|
alpar@1
|
65 |
* parm[2] (nprob) 8-digit problem id number
|
alpar@1
|
66 |
* parm[3] (nodes) total number of nodes
|
alpar@1
|
67 |
* parm[4] (nsorc) total number of source nodes (including
|
alpar@1
|
68 |
* transshipment nodes)
|
alpar@1
|
69 |
* parm[5] (nsink) total number of sink nodes (including
|
alpar@1
|
70 |
* transshipment nodes)
|
alpar@1
|
71 |
* parm[6] (iarcs) number of arcs
|
alpar@1
|
72 |
* parm[7] (mincst) minimum cost for arcs
|
alpar@1
|
73 |
* parm[8] (maxcst) maximum cost for arcs
|
alpar@1
|
74 |
* parm[9] (itsup) total supply
|
alpar@1
|
75 |
* parm[10] (ntsorc) number of transshipment source nodes
|
alpar@1
|
76 |
* parm[11] (ntsink) number of transshipment sink nodes
|
alpar@1
|
77 |
* parm[12] (iphic) percentage of skeleton arcs to be given
|
alpar@1
|
78 |
* the maximum cost
|
alpar@1
|
79 |
* parm[13] (ipcap) percentage of arcs to be capacitated
|
alpar@1
|
80 |
* parm[14] (mincap) minimum upper bound for capacitated arcs
|
alpar@1
|
81 |
* parm[15] (maxcap) maximum upper bound for capacitated arcs
|
alpar@1
|
82 |
*
|
alpar@1
|
83 |
* The routine generates a transportation problem if:
|
alpar@1
|
84 |
*
|
alpar@1
|
85 |
* nsorc + nsink = nodes, ntsorc = 0, and ntsink = 0.
|
alpar@1
|
86 |
*
|
alpar@1
|
87 |
* The routine generates an assignment problem if the requirements for
|
alpar@1
|
88 |
* a transportation problem are met and:
|
alpar@1
|
89 |
*
|
alpar@1
|
90 |
* nsorc = nsink and itsup = nsorc.
|
alpar@1
|
91 |
*
|
alpar@1
|
92 |
* RETURNS
|
alpar@1
|
93 |
*
|
alpar@1
|
94 |
* If the instance was successfully generated, the routine glp_netgen
|
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 |
* REFERENCES
|
alpar@1
|
99 |
*
|
alpar@1
|
100 |
* D.Klingman, A.Napier, and J.Stutz. NETGEN: A program for generating
|
alpar@1
|
101 |
* large scale capacitated assignment, transportation, and minimum cost
|
alpar@1
|
102 |
* flow networks. Management Science 20 (1974), 814-20. */
|
alpar@1
|
103 |
|
alpar@1
|
104 |
struct csa
|
alpar@1
|
105 |
{ /* common storage area */
|
alpar@1
|
106 |
glp_graph *G;
|
alpar@1
|
107 |
int v_rhs, a_cap, a_cost;
|
alpar@1
|
108 |
int nodes, iarcs, mincst, maxcst, itsup, nsorc, nsink, nonsor,
|
alpar@1
|
109 |
nfsink, narcs, nsort, nftsor, ipcap, mincap, maxcap, ktl,
|
alpar@1
|
110 |
nodlft, *ipred, *ihead, *itail, *iflag, *isup, *lsinks, mult,
|
alpar@1
|
111 |
modul, i15, i16, jran;
|
alpar@1
|
112 |
};
|
alpar@1
|
113 |
|
alpar@1
|
114 |
#define G (csa->G)
|
alpar@1
|
115 |
#define v_rhs (csa->v_rhs)
|
alpar@1
|
116 |
#define a_cap (csa->a_cap)
|
alpar@1
|
117 |
#define a_cost (csa->a_cost)
|
alpar@1
|
118 |
#define nodes (csa->nodes)
|
alpar@1
|
119 |
#define iarcs (csa->iarcs)
|
alpar@1
|
120 |
#define mincst (csa->mincst)
|
alpar@1
|
121 |
#define maxcst (csa->maxcst)
|
alpar@1
|
122 |
#define itsup (csa->itsup)
|
alpar@1
|
123 |
#define nsorc (csa->nsorc)
|
alpar@1
|
124 |
#define nsink (csa->nsink)
|
alpar@1
|
125 |
#define nonsor (csa->nonsor)
|
alpar@1
|
126 |
#define nfsink (csa->nfsink)
|
alpar@1
|
127 |
#define narcs (csa->narcs)
|
alpar@1
|
128 |
#define nsort (csa->nsort)
|
alpar@1
|
129 |
#define nftsor (csa->nftsor)
|
alpar@1
|
130 |
#define ipcap (csa->ipcap)
|
alpar@1
|
131 |
#define mincap (csa->mincap)
|
alpar@1
|
132 |
#define maxcap (csa->maxcap)
|
alpar@1
|
133 |
#define ktl (csa->ktl)
|
alpar@1
|
134 |
#define nodlft (csa->nodlft)
|
alpar@1
|
135 |
#if 0
|
alpar@1
|
136 |
/* spent a day to find out this bug */
|
alpar@1
|
137 |
#define ist (csa->ist)
|
alpar@1
|
138 |
#else
|
alpar@1
|
139 |
#define ist (ipred[0])
|
alpar@1
|
140 |
#endif
|
alpar@1
|
141 |
#define ipred (csa->ipred)
|
alpar@1
|
142 |
#define ihead (csa->ihead)
|
alpar@1
|
143 |
#define itail (csa->itail)
|
alpar@1
|
144 |
#define iflag (csa->iflag)
|
alpar@1
|
145 |
#define isup (csa->isup)
|
alpar@1
|
146 |
#define lsinks (csa->lsinks)
|
alpar@1
|
147 |
#define mult (csa->mult)
|
alpar@1
|
148 |
#define modul (csa->modul)
|
alpar@1
|
149 |
#define i15 (csa->i15)
|
alpar@1
|
150 |
#define i16 (csa->i16)
|
alpar@1
|
151 |
#define jran (csa->jran)
|
alpar@1
|
152 |
|
alpar@1
|
153 |
static void cresup(struct csa *csa);
|
alpar@1
|
154 |
static void chain(struct csa *csa, int lpick, int lsorc);
|
alpar@1
|
155 |
static void chnarc(struct csa *csa, int lsorc);
|
alpar@1
|
156 |
static void sort(struct csa *csa);
|
alpar@1
|
157 |
static void pickj(struct csa *csa, int it);
|
alpar@1
|
158 |
static void assign(struct csa *csa);
|
alpar@1
|
159 |
static void setran(struct csa *csa, int iseed);
|
alpar@1
|
160 |
static int iran(struct csa *csa, int ilow, int ihigh);
|
alpar@1
|
161 |
|
alpar@1
|
162 |
int glp_netgen(glp_graph *G_, int _v_rhs, int _a_cap, int _a_cost,
|
alpar@1
|
163 |
const int parm[1+15])
|
alpar@1
|
164 |
{ struct csa _csa, *csa = &_csa;
|
alpar@1
|
165 |
int iseed, nprob, ntsorc, ntsink, iphic, i, nskel, nltr, ltsink,
|
alpar@1
|
166 |
ntrans, npsink, nftr, npsorc, ntravl, ntrrem, lsorc, lpick,
|
alpar@1
|
167 |
nsksr, nsrchn, j, item, l, ks, k, ksp, li, n, ii, it, ih, icap,
|
alpar@1
|
168 |
jcap, icost, jcost, ret;
|
alpar@1
|
169 |
G = G_;
|
alpar@1
|
170 |
v_rhs = _v_rhs;
|
alpar@1
|
171 |
a_cap = _a_cap;
|
alpar@1
|
172 |
a_cost = _a_cost;
|
alpar@1
|
173 |
if (G != NULL)
|
alpar@1
|
174 |
{ if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double))
|
alpar@1
|
175 |
xerror("glp_netgen: v_rhs = %d; invalid offset\n", v_rhs);
|
alpar@1
|
176 |
if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
|
alpar@1
|
177 |
xerror("glp_netgen: a_cap = %d; invalid offset\n", a_cap);
|
alpar@1
|
178 |
if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
|
alpar@1
|
179 |
xerror("glp_netgen: a_cost = %d; invalid offset\n", a_cost);
|
alpar@1
|
180 |
}
|
alpar@1
|
181 |
/* Input the user's random number seed and fix it if
|
alpar@1
|
182 |
non-positive. */
|
alpar@1
|
183 |
iseed = parm[1];
|
alpar@1
|
184 |
nprob = parm[2];
|
alpar@1
|
185 |
if (iseed <= 0) iseed = 13502460;
|
alpar@1
|
186 |
setran(csa, iseed);
|
alpar@1
|
187 |
/* Input the user's problem characteristics. */
|
alpar@1
|
188 |
nodes = parm[3];
|
alpar@1
|
189 |
nsorc = parm[4];
|
alpar@1
|
190 |
nsink = parm[5];
|
alpar@1
|
191 |
iarcs = parm[6];
|
alpar@1
|
192 |
mincst = parm[7];
|
alpar@1
|
193 |
maxcst = parm[8];
|
alpar@1
|
194 |
itsup = parm[9];
|
alpar@1
|
195 |
ntsorc = parm[10];
|
alpar@1
|
196 |
ntsink = parm[11];
|
alpar@1
|
197 |
iphic = parm[12];
|
alpar@1
|
198 |
ipcap = parm[13];
|
alpar@1
|
199 |
mincap = parm[14];
|
alpar@1
|
200 |
maxcap = parm[15];
|
alpar@1
|
201 |
/* Check the size of the problem. */
|
alpar@1
|
202 |
if (!(10 <= nodes && nodes <= 100000))
|
alpar@1
|
203 |
{ ret = 1;
|
alpar@1
|
204 |
goto done;
|
alpar@1
|
205 |
}
|
alpar@1
|
206 |
/* Check user supplied parameters for consistency. */
|
alpar@1
|
207 |
if (!(nsorc >= 0 && nsink >= 0 && nsorc + nsink <= nodes))
|
alpar@1
|
208 |
{ ret = 2;
|
alpar@1
|
209 |
goto done;
|
alpar@1
|
210 |
}
|
alpar@1
|
211 |
if (iarcs < 0)
|
alpar@1
|
212 |
{ ret = 3;
|
alpar@1
|
213 |
goto done;
|
alpar@1
|
214 |
}
|
alpar@1
|
215 |
if (mincst > maxcst)
|
alpar@1
|
216 |
{ ret = 4;
|
alpar@1
|
217 |
goto done;
|
alpar@1
|
218 |
}
|
alpar@1
|
219 |
if (itsup < 0)
|
alpar@1
|
220 |
{ ret = 5;
|
alpar@1
|
221 |
goto done;
|
alpar@1
|
222 |
}
|
alpar@1
|
223 |
if (!(0 <= ntsorc && ntsorc <= nsorc))
|
alpar@1
|
224 |
{ ret = 6;
|
alpar@1
|
225 |
goto done;
|
alpar@1
|
226 |
}
|
alpar@1
|
227 |
if (!(0 <= ntsink && ntsink <= nsink))
|
alpar@1
|
228 |
{ ret = 7;
|
alpar@1
|
229 |
goto done;
|
alpar@1
|
230 |
}
|
alpar@1
|
231 |
if (!(0 <= iphic && iphic <= 100))
|
alpar@1
|
232 |
{ ret = 8;
|
alpar@1
|
233 |
goto done;
|
alpar@1
|
234 |
}
|
alpar@1
|
235 |
if (!(0 <= ipcap && ipcap <= 100))
|
alpar@1
|
236 |
{ ret = 9;
|
alpar@1
|
237 |
goto done;
|
alpar@1
|
238 |
}
|
alpar@1
|
239 |
if (mincap > maxcap)
|
alpar@1
|
240 |
{ ret = 10;
|
alpar@1
|
241 |
goto done;
|
alpar@1
|
242 |
}
|
alpar@1
|
243 |
/* Initailize the graph object. */
|
alpar@1
|
244 |
if (G != NULL)
|
alpar@1
|
245 |
{ glp_erase_graph(G, G->v_size, G->a_size);
|
alpar@1
|
246 |
glp_add_vertices(G, nodes);
|
alpar@1
|
247 |
if (v_rhs >= 0)
|
alpar@1
|
248 |
{ double zero = 0.0;
|
alpar@1
|
249 |
for (i = 1; i <= nodes; i++)
|
alpar@1
|
250 |
{ glp_vertex *v = G->v[i];
|
alpar@1
|
251 |
memcpy((char *)v->data + v_rhs, &zero, sizeof(double));
|
alpar@1
|
252 |
}
|
alpar@1
|
253 |
}
|
alpar@1
|
254 |
}
|
alpar@1
|
255 |
/* Allocate working arrays. */
|
alpar@1
|
256 |
ipred = xcalloc(1+nodes, sizeof(int));
|
alpar@1
|
257 |
ihead = xcalloc(1+nodes, sizeof(int));
|
alpar@1
|
258 |
itail = xcalloc(1+nodes, sizeof(int));
|
alpar@1
|
259 |
iflag = xcalloc(1+nodes, sizeof(int));
|
alpar@1
|
260 |
isup = xcalloc(1+nodes, sizeof(int));
|
alpar@1
|
261 |
lsinks = xcalloc(1+nodes, sizeof(int));
|
alpar@1
|
262 |
/* Print the problem documentation records. */
|
alpar@1
|
263 |
if (G == NULL)
|
alpar@1
|
264 |
{ xprintf("BEGIN\n");
|
alpar@1
|
265 |
xprintf("NETGEN PROBLEM%8d%10s%10d NODES AND%10d ARCS\n",
|
alpar@1
|
266 |
nprob, "", nodes, iarcs);
|
alpar@1
|
267 |
xprintf("USER:%11d%11d%11d%11d%11d%11d\nDATA:%11d%11d%11d%11d%"
|
alpar@1
|
268 |
"11d%11d\n", iseed, nsorc, nsink, mincst,
|
alpar@1
|
269 |
maxcst, itsup, ntsorc, ntsink, iphic, ipcap,
|
alpar@1
|
270 |
mincap, maxcap);
|
alpar@1
|
271 |
}
|
alpar@1
|
272 |
else
|
alpar@1
|
273 |
glp_set_graph_name(G, "NETGEN");
|
alpar@1
|
274 |
/* Set various constants used in the program. */
|
alpar@1
|
275 |
narcs = 0;
|
alpar@1
|
276 |
nskel = 0;
|
alpar@1
|
277 |
nltr = nodes - nsink;
|
alpar@1
|
278 |
ltsink = nltr + ntsink;
|
alpar@1
|
279 |
ntrans = nltr - nsorc;
|
alpar@1
|
280 |
nfsink = nltr + 1;
|
alpar@1
|
281 |
nonsor = nodes - nsorc + ntsorc;
|
alpar@1
|
282 |
npsink = nsink - ntsink;
|
alpar@1
|
283 |
nodlft = nodes - nsink + ntsink;
|
alpar@1
|
284 |
nftr = nsorc + 1;
|
alpar@1
|
285 |
nftsor = nsorc - ntsorc + 1;
|
alpar@1
|
286 |
npsorc = nsorc - ntsorc;
|
alpar@1
|
287 |
/* Randomly distribute the supply among the source nodes. */
|
alpar@1
|
288 |
if (npsorc + npsink == nodes && npsorc == npsink &&
|
alpar@1
|
289 |
itsup == nsorc)
|
alpar@1
|
290 |
{ assign(csa);
|
alpar@1
|
291 |
nskel = nsorc;
|
alpar@1
|
292 |
goto L390;
|
alpar@1
|
293 |
}
|
alpar@1
|
294 |
cresup(csa);
|
alpar@1
|
295 |
/* Print the supply records. */
|
alpar@1
|
296 |
if (G == NULL)
|
alpar@1
|
297 |
{ xprintf("SUPPLY\n");
|
alpar@1
|
298 |
for (i = 1; i <= nsorc; i++)
|
alpar@1
|
299 |
xprintf("%6s%6d%18s%10d\n", "", i, "", isup[i]);
|
alpar@1
|
300 |
xprintf("ARCS\n");
|
alpar@1
|
301 |
}
|
alpar@1
|
302 |
else
|
alpar@1
|
303 |
{ if (v_rhs >= 0)
|
alpar@1
|
304 |
{ for (i = 1; i <= nsorc; i++)
|
alpar@1
|
305 |
{ double temp = (double)isup[i];
|
alpar@1
|
306 |
glp_vertex *v = G->v[i];
|
alpar@1
|
307 |
memcpy((char *)v->data + v_rhs, &temp, sizeof(double));
|
alpar@1
|
308 |
}
|
alpar@1
|
309 |
}
|
alpar@1
|
310 |
}
|
alpar@1
|
311 |
/* Make the sources point to themselves in ipred array. */
|
alpar@1
|
312 |
for (i = 1; i <= nsorc; i++)
|
alpar@1
|
313 |
ipred[i] = i;
|
alpar@1
|
314 |
if (ntrans == 0) goto L170;
|
alpar@1
|
315 |
/* Chain the transshipment nodes together in the ipred array. */
|
alpar@1
|
316 |
ist = nftr;
|
alpar@1
|
317 |
ipred[nltr] = 0;
|
alpar@1
|
318 |
for (i = nftr; i < nltr; i++)
|
alpar@1
|
319 |
ipred[i] = i+1;
|
alpar@1
|
320 |
/* Form even length chains for 60 percent of the transshipments.*/
|
alpar@1
|
321 |
ntravl = 6 * ntrans / 10;
|
alpar@1
|
322 |
ntrrem = ntrans - ntravl;
|
alpar@1
|
323 |
L140: lsorc = 1;
|
alpar@1
|
324 |
while (ntravl != 0)
|
alpar@1
|
325 |
{ lpick = iran(csa, 1, ntravl + ntrrem);
|
alpar@1
|
326 |
ntravl--;
|
alpar@1
|
327 |
chain(csa, lpick, lsorc);
|
alpar@1
|
328 |
if (lsorc == nsorc) goto L140;
|
alpar@1
|
329 |
lsorc++;
|
alpar@1
|
330 |
}
|
alpar@1
|
331 |
/* Add the remaining transshipments to the chains. */
|
alpar@1
|
332 |
while (ntrrem != 0)
|
alpar@1
|
333 |
{
|
alpar@1
|
334 |
lpick = iran(csa, 1, ntrrem);
|
alpar@1
|
335 |
ntrrem--;
|
alpar@1
|
336 |
lsorc = iran(csa, 1, nsorc);
|
alpar@1
|
337 |
chain(csa, lpick, lsorc);
|
alpar@1
|
338 |
}
|
alpar@1
|
339 |
L170: /* Set all demands equal to zero. */
|
alpar@1
|
340 |
for (i = nfsink; i <= nodes; i++)
|
alpar@1
|
341 |
ipred[i] = 0;
|
alpar@1
|
342 |
/* The following loop takes one chain at a time (through the use
|
alpar@1
|
343 |
of logic contained in the loop and calls to other routines) and
|
alpar@1
|
344 |
creates the remaining network arcs. */
|
alpar@1
|
345 |
for (lsorc = 1; lsorc <= nsorc; lsorc++)
|
alpar@1
|
346 |
{ chnarc(csa, lsorc);
|
alpar@1
|
347 |
for (i = nfsink; i <= nodes; i++)
|
alpar@1
|
348 |
iflag[i] = 0;
|
alpar@1
|
349 |
/* Choose the number of sinks to be hooked up to the current
|
alpar@1
|
350 |
chain. */
|
alpar@1
|
351 |
if (ntrans != 0)
|
alpar@1
|
352 |
nsksr = (nsort * 2 * nsink) / ntrans;
|
alpar@1
|
353 |
else
|
alpar@1
|
354 |
nsksr = nsink / nsorc + 1;
|
alpar@1
|
355 |
if (nsksr < 2) nsksr = 2;
|
alpar@1
|
356 |
if (nsksr > nsink) nsksr = nsink;
|
alpar@1
|
357 |
nsrchn = nsort;
|
alpar@1
|
358 |
/* Randomly pick nsksr sinks and put their names in lsinks. */
|
alpar@1
|
359 |
ktl = nsink;
|
alpar@1
|
360 |
for (j = 1; j <= nsksr; j++)
|
alpar@1
|
361 |
{ item = iran(csa, 1, ktl);
|
alpar@1
|
362 |
ktl--;
|
alpar@1
|
363 |
for (l = nfsink; l <= nodes; l++)
|
alpar@1
|
364 |
{ if (iflag[l] != 1)
|
alpar@1
|
365 |
{ item--;
|
alpar@1
|
366 |
if (item == 0) goto L230;
|
alpar@1
|
367 |
}
|
alpar@1
|
368 |
}
|
alpar@1
|
369 |
break;
|
alpar@1
|
370 |
L230: lsinks[j] = l;
|
alpar@1
|
371 |
iflag[l] = 1;
|
alpar@1
|
372 |
}
|
alpar@1
|
373 |
/* If last source chain, add all sinks with zero demand to
|
alpar@1
|
374 |
lsinks list. */
|
alpar@1
|
375 |
if (lsorc == nsorc)
|
alpar@1
|
376 |
{ for (j = nfsink; j <= nodes; j++)
|
alpar@1
|
377 |
{ if (ipred[j] == 0 && iflag[j] != 1)
|
alpar@1
|
378 |
{ nsksr++;
|
alpar@1
|
379 |
lsinks[nsksr] = j;
|
alpar@1
|
380 |
iflag[j] = 1;
|
alpar@1
|
381 |
}
|
alpar@1
|
382 |
}
|
alpar@1
|
383 |
}
|
alpar@1
|
384 |
/* Create demands for group of sinks in lsinks. */
|
alpar@1
|
385 |
ks = isup[lsorc] / nsksr;
|
alpar@1
|
386 |
k = ipred[lsorc];
|
alpar@1
|
387 |
for (i = 1; i <= nsksr; i++)
|
alpar@1
|
388 |
{ nsort++;
|
alpar@1
|
389 |
ksp = iran(csa, 1, ks);
|
alpar@1
|
390 |
j = iran(csa, 1, nsksr);
|
alpar@1
|
391 |
itail[nsort] = k;
|
alpar@1
|
392 |
li = lsinks[i];
|
alpar@1
|
393 |
ihead[nsort] = li;
|
alpar@1
|
394 |
ipred[li] += ksp;
|
alpar@1
|
395 |
li = lsinks[j];
|
alpar@1
|
396 |
ipred[li] += ks - ksp;
|
alpar@1
|
397 |
n = iran(csa, 1, nsrchn);
|
alpar@1
|
398 |
k = lsorc;
|
alpar@1
|
399 |
for (ii = 1; ii <= n; ii++)
|
alpar@1
|
400 |
k = ipred[k];
|
alpar@1
|
401 |
}
|
alpar@1
|
402 |
li = lsinks[1];
|
alpar@1
|
403 |
ipred[li] += isup[lsorc] - ks * nsksr;
|
alpar@1
|
404 |
nskel += nsort;
|
alpar@1
|
405 |
/* Sort the arcs in the chain from source lsorc using itail as
|
alpar@1
|
406 |
sort key. */
|
alpar@1
|
407 |
sort(csa);
|
alpar@1
|
408 |
/* Print this part of skeleton and create the arcs for these
|
alpar@1
|
409 |
nodes. */
|
alpar@1
|
410 |
i = 1;
|
alpar@1
|
411 |
itail[nsort+1] = 0;
|
alpar@1
|
412 |
L300: for (j = nftsor; j <= nodes; j++)
|
alpar@1
|
413 |
iflag[j] = 0;
|
alpar@1
|
414 |
ktl = nonsor - 1;
|
alpar@1
|
415 |
it = itail[i];
|
alpar@1
|
416 |
iflag[it] = 1;
|
alpar@1
|
417 |
L320: ih = ihead[i];
|
alpar@1
|
418 |
iflag[ih] = 1;
|
alpar@1
|
419 |
narcs++;
|
alpar@1
|
420 |
ktl--;
|
alpar@1
|
421 |
/* Determine if this skeleton arc should be capacitated. */
|
alpar@1
|
422 |
icap = itsup;
|
alpar@1
|
423 |
jcap = iran(csa, 1, 100);
|
alpar@1
|
424 |
if (jcap <= ipcap)
|
alpar@1
|
425 |
{ icap = isup[lsorc];
|
alpar@1
|
426 |
if (mincap > icap) icap = mincap;
|
alpar@1
|
427 |
}
|
alpar@1
|
428 |
/* Determine if this skeleton arc should have the maximum
|
alpar@1
|
429 |
cost. */
|
alpar@1
|
430 |
icost = maxcst;
|
alpar@1
|
431 |
jcost = iran(csa, 1, 100);
|
alpar@1
|
432 |
if (jcost > iphic)
|
alpar@1
|
433 |
icost = iran(csa, mincst, maxcst);
|
alpar@1
|
434 |
if (G == NULL)
|
alpar@1
|
435 |
xprintf("%6s%6d%6d%2s%10d%10d\n", "", it, ih, "", icost,
|
alpar@1
|
436 |
icap);
|
alpar@1
|
437 |
else
|
alpar@1
|
438 |
{ glp_arc *a = glp_add_arc(G, it, ih);
|
alpar@1
|
439 |
if (a_cap >= 0)
|
alpar@1
|
440 |
{ double temp = (double)icap;
|
alpar@1
|
441 |
memcpy((char *)a->data + a_cap, &temp, sizeof(double));
|
alpar@1
|
442 |
}
|
alpar@1
|
443 |
if (a_cost >= 0)
|
alpar@1
|
444 |
{ double temp = (double)icost;
|
alpar@1
|
445 |
memcpy((char *)a->data + a_cost, &temp, sizeof(double));
|
alpar@1
|
446 |
}
|
alpar@1
|
447 |
}
|
alpar@1
|
448 |
i++;
|
alpar@1
|
449 |
if (itail[i] == it) goto L320;
|
alpar@1
|
450 |
pickj(csa, it);
|
alpar@1
|
451 |
if (i <= nsort) goto L300;
|
alpar@1
|
452 |
}
|
alpar@1
|
453 |
/* Create arcs from the transshipment sinks. */
|
alpar@1
|
454 |
if (ntsink != 0)
|
alpar@1
|
455 |
{ for (i = nfsink; i <= ltsink; i++)
|
alpar@1
|
456 |
{ for (j = nftsor; j <= nodes; j++)
|
alpar@1
|
457 |
iflag[j] = 0;
|
alpar@1
|
458 |
ktl = nonsor - 1;
|
alpar@1
|
459 |
iflag[i] = 1;
|
alpar@1
|
460 |
pickj(csa, i);
|
alpar@1
|
461 |
}
|
alpar@1
|
462 |
}
|
alpar@1
|
463 |
L390: /* Print the demand records and end record. */
|
alpar@1
|
464 |
if (G == NULL)
|
alpar@1
|
465 |
{ xprintf("DEMAND\n");
|
alpar@1
|
466 |
for (i = nfsink; i <= nodes; i++)
|
alpar@1
|
467 |
xprintf("%6s%6d%18s%10d\n", "", i, "", ipred[i]);
|
alpar@1
|
468 |
xprintf("END\n");
|
alpar@1
|
469 |
}
|
alpar@1
|
470 |
else
|
alpar@1
|
471 |
{ if (v_rhs >= 0)
|
alpar@1
|
472 |
{ for (i = nfsink; i <= nodes; i++)
|
alpar@1
|
473 |
{ double temp = - (double)ipred[i];
|
alpar@1
|
474 |
glp_vertex *v = G->v[i];
|
alpar@1
|
475 |
memcpy((char *)v->data + v_rhs, &temp, sizeof(double));
|
alpar@1
|
476 |
}
|
alpar@1
|
477 |
}
|
alpar@1
|
478 |
}
|
alpar@1
|
479 |
/* Free working arrays. */
|
alpar@1
|
480 |
xfree(ipred);
|
alpar@1
|
481 |
xfree(ihead);
|
alpar@1
|
482 |
xfree(itail);
|
alpar@1
|
483 |
xfree(iflag);
|
alpar@1
|
484 |
xfree(isup);
|
alpar@1
|
485 |
xfree(lsinks);
|
alpar@1
|
486 |
/* The instance has been successfully generated. */
|
alpar@1
|
487 |
ret = 0;
|
alpar@1
|
488 |
done: return ret;
|
alpar@1
|
489 |
}
|
alpar@1
|
490 |
|
alpar@1
|
491 |
/***********************************************************************
|
alpar@1
|
492 |
* The routine cresup randomly distributes the total supply among the
|
alpar@1
|
493 |
* source nodes. */
|
alpar@1
|
494 |
|
alpar@1
|
495 |
static void cresup(struct csa *csa)
|
alpar@1
|
496 |
{ int i, j, ks, ksp;
|
alpar@1
|
497 |
xassert(itsup > nsorc);
|
alpar@1
|
498 |
ks = itsup / nsorc;
|
alpar@1
|
499 |
for (i = 1; i <= nsorc; i++)
|
alpar@1
|
500 |
isup[i] = 0;
|
alpar@1
|
501 |
for (i = 1; i <= nsorc; i++)
|
alpar@1
|
502 |
{ ksp = iran(csa, 1, ks);
|
alpar@1
|
503 |
j = iran(csa, 1, nsorc);
|
alpar@1
|
504 |
isup[i] += ksp;
|
alpar@1
|
505 |
isup[j] += ks - ksp;
|
alpar@1
|
506 |
}
|
alpar@1
|
507 |
j = iran(csa, 1, nsorc);
|
alpar@1
|
508 |
isup[j] += itsup - ks * nsorc;
|
alpar@1
|
509 |
return;
|
alpar@1
|
510 |
}
|
alpar@1
|
511 |
|
alpar@1
|
512 |
/***********************************************************************
|
alpar@1
|
513 |
* The routine chain adds node lpick to the end of the chain with source
|
alpar@1
|
514 |
* node lsorc. */
|
alpar@1
|
515 |
|
alpar@1
|
516 |
static void chain(struct csa *csa, int lpick, int lsorc)
|
alpar@1
|
517 |
{ int i, j, k, l, m;
|
alpar@1
|
518 |
k = 0;
|
alpar@1
|
519 |
m = ist;
|
alpar@1
|
520 |
for (i = 1; i <= lpick; i++)
|
alpar@1
|
521 |
{ l = k;
|
alpar@1
|
522 |
k = m;
|
alpar@1
|
523 |
m = ipred[k];
|
alpar@1
|
524 |
}
|
alpar@1
|
525 |
ipred[l] = m;
|
alpar@1
|
526 |
j = ipred[lsorc];
|
alpar@1
|
527 |
ipred[k] = j;
|
alpar@1
|
528 |
ipred[lsorc] = k;
|
alpar@1
|
529 |
return;
|
alpar@1
|
530 |
}
|
alpar@1
|
531 |
|
alpar@1
|
532 |
/***********************************************************************
|
alpar@1
|
533 |
* The routine chnarc puts the arcs in the chain from source lsorc into
|
alpar@1
|
534 |
* the ihead and itail arrays for sorting. */
|
alpar@1
|
535 |
|
alpar@1
|
536 |
static void chnarc(struct csa *csa, int lsorc)
|
alpar@1
|
537 |
{ int ito, ifrom;
|
alpar@1
|
538 |
nsort = 0;
|
alpar@1
|
539 |
ito = ipred[lsorc];
|
alpar@1
|
540 |
L10: if (ito == lsorc) return;
|
alpar@1
|
541 |
nsort++;
|
alpar@1
|
542 |
ifrom = ipred[ito];
|
alpar@1
|
543 |
ihead[nsort] = ito;
|
alpar@1
|
544 |
itail[nsort] = ifrom;
|
alpar@1
|
545 |
ito = ifrom;
|
alpar@1
|
546 |
goto L10;
|
alpar@1
|
547 |
}
|
alpar@1
|
548 |
|
alpar@1
|
549 |
/***********************************************************************
|
alpar@1
|
550 |
* The routine sort sorts the nsort arcs in the ihead and itail arrays.
|
alpar@1
|
551 |
* ihead is used as the sort key (i.e. forward star sort order). */
|
alpar@1
|
552 |
|
alpar@1
|
553 |
static void sort(struct csa *csa)
|
alpar@1
|
554 |
{ int i, j, k, l, m, n, it;
|
alpar@1
|
555 |
n = nsort;
|
alpar@1
|
556 |
m = n;
|
alpar@1
|
557 |
L10: m /= 2;
|
alpar@1
|
558 |
if (m == 0) return;
|
alpar@1
|
559 |
k = n - m;
|
alpar@1
|
560 |
j = 1;
|
alpar@1
|
561 |
L20: i = j;
|
alpar@1
|
562 |
L30: l = i + m;
|
alpar@1
|
563 |
if (itail[i] <= itail[l]) goto L40;
|
alpar@1
|
564 |
it = itail[i];
|
alpar@1
|
565 |
itail[i] = itail[l];
|
alpar@1
|
566 |
itail[l] = it;
|
alpar@1
|
567 |
it = ihead[i];
|
alpar@1
|
568 |
ihead[i] = ihead[l];
|
alpar@1
|
569 |
ihead[l] = it;
|
alpar@1
|
570 |
i -= m;
|
alpar@1
|
571 |
if (i >= 1) goto L30;
|
alpar@1
|
572 |
L40: j++;
|
alpar@1
|
573 |
if (j <= k) goto L20;
|
alpar@1
|
574 |
goto L10;
|
alpar@1
|
575 |
}
|
alpar@1
|
576 |
|
alpar@1
|
577 |
/***********************************************************************
|
alpar@1
|
578 |
* The routine pickj creates a random number of arcs out of node 'it'.
|
alpar@1
|
579 |
* Various parameters are dynamically adjusted in an attempt to ensure
|
alpar@1
|
580 |
* that the generated network has the correct number of arcs. */
|
alpar@1
|
581 |
|
alpar@1
|
582 |
static void pickj(struct csa *csa, int it)
|
alpar@1
|
583 |
{ int j, k, l, nn, nupbnd, icap, jcap, icost;
|
alpar@1
|
584 |
if ((nodlft - 1) * 2 > iarcs - narcs - 1)
|
alpar@1
|
585 |
{ nodlft--;
|
alpar@1
|
586 |
return;
|
alpar@1
|
587 |
}
|
alpar@1
|
588 |
if ((iarcs - narcs + nonsor - ktl - 1) / nodlft - nonsor + 1 >= 0)
|
alpar@1
|
589 |
k = nonsor;
|
alpar@1
|
590 |
else
|
alpar@1
|
591 |
{ nupbnd = (iarcs - narcs - nodlft) / nodlft * 2;
|
alpar@1
|
592 |
L40: k = iran(csa, 1, nupbnd);
|
alpar@1
|
593 |
if (nodlft == 1) k = iarcs - narcs;
|
alpar@1
|
594 |
if ((nodlft - 1) * (nonsor - 1) < iarcs - narcs - k) goto L40;
|
alpar@1
|
595 |
}
|
alpar@1
|
596 |
nodlft--;
|
alpar@1
|
597 |
for (j = 1; j <= k; j++)
|
alpar@1
|
598 |
{ nn = iran(csa, 1, ktl);
|
alpar@1
|
599 |
ktl--;
|
alpar@1
|
600 |
for (l = nftsor; l <= nodes; l++)
|
alpar@1
|
601 |
{ if (iflag[l] != 1)
|
alpar@1
|
602 |
{ nn--;
|
alpar@1
|
603 |
if (nn == 0) goto L70;
|
alpar@1
|
604 |
}
|
alpar@1
|
605 |
}
|
alpar@1
|
606 |
return;
|
alpar@1
|
607 |
L70: iflag[l] = 1;
|
alpar@1
|
608 |
icap = itsup;
|
alpar@1
|
609 |
jcap = iran(csa, 1, 100);
|
alpar@1
|
610 |
if (jcap <= ipcap)
|
alpar@1
|
611 |
icap = iran(csa, mincap, maxcap);
|
alpar@1
|
612 |
icost = iran(csa, mincst, maxcst);
|
alpar@1
|
613 |
if (G == NULL)
|
alpar@1
|
614 |
xprintf("%6s%6d%6d%2s%10d%10d\n", "", it, l, "", icost,
|
alpar@1
|
615 |
icap);
|
alpar@1
|
616 |
else
|
alpar@1
|
617 |
{ glp_arc *a = glp_add_arc(G, it, l);
|
alpar@1
|
618 |
if (a_cap >= 0)
|
alpar@1
|
619 |
{ double temp = (double)icap;
|
alpar@1
|
620 |
memcpy((char *)a->data + a_cap, &temp, sizeof(double));
|
alpar@1
|
621 |
}
|
alpar@1
|
622 |
if (a_cost >= 0)
|
alpar@1
|
623 |
{ double temp = (double)icost;
|
alpar@1
|
624 |
memcpy((char *)a->data + a_cost, &temp, sizeof(double));
|
alpar@1
|
625 |
}
|
alpar@1
|
626 |
}
|
alpar@1
|
627 |
narcs++;
|
alpar@1
|
628 |
}
|
alpar@1
|
629 |
return;
|
alpar@1
|
630 |
}
|
alpar@1
|
631 |
|
alpar@1
|
632 |
/***********************************************************************
|
alpar@1
|
633 |
* The routine assign generate assignment problems. It defines the unit
|
alpar@1
|
634 |
* supplies, builds a skeleton, then calls pickj to create the arcs. */
|
alpar@1
|
635 |
|
alpar@1
|
636 |
static void assign(struct csa *csa)
|
alpar@1
|
637 |
{ int i, it, nn, l, ll, icost;
|
alpar@1
|
638 |
if (G == NULL)
|
alpar@1
|
639 |
xprintf("SUPPLY\n");
|
alpar@1
|
640 |
for (i = 1; i <= nsorc; i++)
|
alpar@1
|
641 |
{ isup[i] = 1;
|
alpar@1
|
642 |
iflag[i] = 0;
|
alpar@1
|
643 |
if (G == NULL)
|
alpar@1
|
644 |
xprintf("%6s%6d%18s%10d\n", "", i, "", isup[i]);
|
alpar@1
|
645 |
else
|
alpar@1
|
646 |
{ if (v_rhs >= 0)
|
alpar@1
|
647 |
{ double temp = (double)isup[i];
|
alpar@1
|
648 |
glp_vertex *v = G->v[i];
|
alpar@1
|
649 |
memcpy((char *)v->data + v_rhs, &temp, sizeof(double));
|
alpar@1
|
650 |
}
|
alpar@1
|
651 |
}
|
alpar@1
|
652 |
}
|
alpar@1
|
653 |
if (G == NULL)
|
alpar@1
|
654 |
xprintf("ARCS\n");
|
alpar@1
|
655 |
for (i = nfsink; i <= nodes; i++)
|
alpar@1
|
656 |
ipred[i] = 1;
|
alpar@1
|
657 |
for (it = 1; it <= nsorc; it++)
|
alpar@1
|
658 |
{ for (i = nfsink; i <= nodes; i++)
|
alpar@1
|
659 |
iflag[i] = 0;
|
alpar@1
|
660 |
ktl = nsink - 1;
|
alpar@1
|
661 |
nn = iran(csa, 1, nsink - it + 1);
|
alpar@1
|
662 |
for (l = 1; l <= nsorc; l++)
|
alpar@1
|
663 |
{ if (iflag[l] != 1)
|
alpar@1
|
664 |
{ nn--;
|
alpar@1
|
665 |
if (nn == 0) break;
|
alpar@1
|
666 |
}
|
alpar@1
|
667 |
}
|
alpar@1
|
668 |
narcs++;
|
alpar@1
|
669 |
ll = nsorc + l;
|
alpar@1
|
670 |
icost = iran(csa, mincst, maxcst);
|
alpar@1
|
671 |
if (G == NULL)
|
alpar@1
|
672 |
xprintf("%6s%6d%6d%2s%10d%10d\n", "", it, ll, "", icost,
|
alpar@1
|
673 |
isup[1]);
|
alpar@1
|
674 |
else
|
alpar@1
|
675 |
{ glp_arc *a = glp_add_arc(G, it, ll);
|
alpar@1
|
676 |
if (a_cap >= 0)
|
alpar@1
|
677 |
{ double temp = (double)isup[1];
|
alpar@1
|
678 |
memcpy((char *)a->data + a_cap, &temp, sizeof(double));
|
alpar@1
|
679 |
}
|
alpar@1
|
680 |
if (a_cost >= 0)
|
alpar@1
|
681 |
{ double temp = (double)icost;
|
alpar@1
|
682 |
memcpy((char *)a->data + a_cost, &temp, sizeof(double));
|
alpar@1
|
683 |
}
|
alpar@1
|
684 |
}
|
alpar@1
|
685 |
iflag[l] = 1;
|
alpar@1
|
686 |
iflag[ll] = 1;
|
alpar@1
|
687 |
pickj(csa, it);
|
alpar@1
|
688 |
}
|
alpar@1
|
689 |
return;
|
alpar@1
|
690 |
}
|
alpar@1
|
691 |
|
alpar@1
|
692 |
/***********************************************************************
|
alpar@1
|
693 |
* Portable congruential (uniform) random number generator:
|
alpar@1
|
694 |
*
|
alpar@1
|
695 |
* next_value = ((7**5) * previous_value) modulo ((2**31)-1)
|
alpar@1
|
696 |
*
|
alpar@1
|
697 |
* This generator consists of three routines:
|
alpar@1
|
698 |
*
|
alpar@1
|
699 |
* (1) setran - initializes constants and seed
|
alpar@1
|
700 |
* (2) iran - generates an integer random number
|
alpar@1
|
701 |
* (3) rran - generates a real random number
|
alpar@1
|
702 |
*
|
alpar@1
|
703 |
* The generator requires a machine with at least 32 bits of precision.
|
alpar@1
|
704 |
* The seed (iseed) must be in the range [1,(2**31)-1]. */
|
alpar@1
|
705 |
|
alpar@1
|
706 |
static void setran(struct csa *csa, int iseed)
|
alpar@1
|
707 |
{ xassert(iseed >= 1);
|
alpar@1
|
708 |
mult = 16807;
|
alpar@1
|
709 |
modul = 2147483647;
|
alpar@1
|
710 |
i15 = 1 << 15;
|
alpar@1
|
711 |
i16 = 1 << 16;
|
alpar@1
|
712 |
jran = iseed;
|
alpar@1
|
713 |
return;
|
alpar@1
|
714 |
}
|
alpar@1
|
715 |
|
alpar@1
|
716 |
/***********************************************************************
|
alpar@1
|
717 |
* The routine iran generates an integer random number between ilow and
|
alpar@1
|
718 |
* ihigh. If ilow > ihigh then iran returns ihigh. */
|
alpar@1
|
719 |
|
alpar@1
|
720 |
static int iran(struct csa *csa, int ilow, int ihigh)
|
alpar@1
|
721 |
{ int ixhi, ixlo, ixalo, leftlo, ixahi, ifulhi, irtlo, iover,
|
alpar@1
|
722 |
irthi, j;
|
alpar@1
|
723 |
ixhi = jran / i16;
|
alpar@1
|
724 |
ixlo = jran - ixhi * i16;
|
alpar@1
|
725 |
ixalo = ixlo * mult;
|
alpar@1
|
726 |
leftlo = ixalo / i16;
|
alpar@1
|
727 |
ixahi = ixhi * mult;
|
alpar@1
|
728 |
ifulhi = ixahi + leftlo;
|
alpar@1
|
729 |
irtlo = ixalo - leftlo * i16;
|
alpar@1
|
730 |
iover = ifulhi / i15;
|
alpar@1
|
731 |
irthi = ifulhi - iover * i15;
|
alpar@1
|
732 |
jran = ((irtlo - modul) + irthi * i16) + iover;
|
alpar@1
|
733 |
if (jran < 0) jran += modul;
|
alpar@1
|
734 |
j = ihigh - ilow + 1;
|
alpar@1
|
735 |
if (j > 0)
|
alpar@1
|
736 |
return jran % j + ilow;
|
alpar@1
|
737 |
else
|
alpar@1
|
738 |
return ihigh;
|
alpar@1
|
739 |
}
|
alpar@1
|
740 |
|
alpar@1
|
741 |
/**********************************************************************/
|
alpar@1
|
742 |
|
alpar@1
|
743 |
#if 0
|
alpar@1
|
744 |
static int scan(char card[80+1], int pos, int len)
|
alpar@1
|
745 |
{ char buf[10+1];
|
alpar@1
|
746 |
memcpy(buf, &card[pos-1], len);
|
alpar@1
|
747 |
buf[len] = '\0';
|
alpar@1
|
748 |
return atoi(buf);
|
alpar@1
|
749 |
}
|
alpar@1
|
750 |
|
alpar@1
|
751 |
int main(void)
|
alpar@1
|
752 |
{ int parm[1+15];
|
alpar@1
|
753 |
char card[80+1];
|
alpar@1
|
754 |
xassert(fgets(card, sizeof(card), stdin) == card);
|
alpar@1
|
755 |
parm[1] = scan(card, 1, 8);
|
alpar@1
|
756 |
parm[2] = scan(card, 9, 8);
|
alpar@1
|
757 |
xassert(fgets(card, sizeof(card), stdin) == card);
|
alpar@1
|
758 |
parm[3] = scan(card, 1, 5);
|
alpar@1
|
759 |
parm[4] = scan(card, 6, 5);
|
alpar@1
|
760 |
parm[5] = scan(card, 11, 5);
|
alpar@1
|
761 |
parm[6] = scan(card, 16, 5);
|
alpar@1
|
762 |
parm[7] = scan(card, 21, 5);
|
alpar@1
|
763 |
parm[8] = scan(card, 26, 5);
|
alpar@1
|
764 |
parm[9] = scan(card, 31, 10);
|
alpar@1
|
765 |
parm[10] = scan(card, 41, 5);
|
alpar@1
|
766 |
parm[11] = scan(card, 46, 5);
|
alpar@1
|
767 |
parm[12] = scan(card, 51, 5);
|
alpar@1
|
768 |
parm[13] = scan(card, 56, 5);
|
alpar@1
|
769 |
parm[14] = scan(card, 61, 10);
|
alpar@1
|
770 |
parm[15] = scan(card, 71, 10);
|
alpar@1
|
771 |
glp_netgen(NULL, 0, 0, 0, parm);
|
alpar@1
|
772 |
return 0;
|
alpar@1
|
773 |
}
|
alpar@1
|
774 |
#endif
|
alpar@1
|
775 |
|
alpar@1
|
776 |
/* eof */
|