glpnet03.c 24 KB

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