You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1020 lines
32 KiB

  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 "env.h"
  25. #include "glpk.h"
  26. /***********************************************************************
  27. * NAME
  28. *
  29. * glp_netgen - Klingman's network problem generator
  30. *
  31. * SYNOPSIS
  32. *
  33. * int glp_netgen(glp_graph *G, int v_rhs, int a_cap, int a_cost,
  34. * const int parm[1+15]);
  35. *
  36. * DESCRIPTION
  37. *
  38. * The routine glp_netgen is a network problem generator developed by
  39. * Dr. Darwin Klingman. It can create capacitated and uncapacitated
  40. * minimum cost flow (or transshipment), transportation, and assignment
  41. * problems.
  42. *
  43. * The parameter G specifies the graph object, to which the generated
  44. * problem data have to be stored. Note that on entry the graph object
  45. * is erased with the routine glp_erase_graph.
  46. *
  47. * The parameter v_rhs specifies an offset of the field of type double
  48. * in the vertex data block, to which the routine stores the supply or
  49. * demand value. If v_rhs < 0, the value is not stored.
  50. *
  51. * The parameter a_cap specifies an offset of the field of type double
  52. * in the arc data block, to which the routine stores the arc capacity.
  53. * If a_cap < 0, the capacity is not stored.
  54. *
  55. * The parameter a_cost specifies an offset of the field of type double
  56. * in the arc data block, to which the routine stores the per-unit cost
  57. * if the arc flow. If a_cost < 0, the cost is not stored.
  58. *
  59. * The array parm contains description of the network to be generated:
  60. *
  61. * parm[0] not used
  62. * parm[1] (iseed) 8-digit positive random number seed
  63. * parm[2] (nprob) 8-digit problem id number
  64. * parm[3] (nodes) total number of nodes
  65. * parm[4] (nsorc) total number of source nodes (including
  66. * transshipment nodes)
  67. * parm[5] (nsink) total number of sink nodes (including
  68. * transshipment nodes)
  69. * parm[6] (iarcs) number of arcs
  70. * parm[7] (mincst) minimum cost for arcs
  71. * parm[8] (maxcst) maximum cost for arcs
  72. * parm[9] (itsup) total supply
  73. * parm[10] (ntsorc) number of transshipment source nodes
  74. * parm[11] (ntsink) number of transshipment sink nodes
  75. * parm[12] (iphic) percentage of skeleton arcs to be given
  76. * the maximum cost
  77. * parm[13] (ipcap) percentage of arcs to be capacitated
  78. * parm[14] (mincap) minimum upper bound for capacitated arcs
  79. * parm[15] (maxcap) maximum upper bound for capacitated arcs
  80. *
  81. * The routine generates a transportation problem if:
  82. *
  83. * nsorc + nsink = nodes, ntsorc = 0, and ntsink = 0.
  84. *
  85. * The routine generates an assignment problem if the requirements for
  86. * a transportation problem are met and:
  87. *
  88. * nsorc = nsink and itsup = nsorc.
  89. *
  90. * RETURNS
  91. *
  92. * If the instance was successfully generated, the routine glp_netgen
  93. * returns zero; otherwise, if specified parameters are inconsistent,
  94. * the routine returns a non-zero error code.
  95. *
  96. * REFERENCES
  97. *
  98. * D.Klingman, A.Napier, and J.Stutz. NETGEN: A program for generating
  99. * large scale capacitated assignment, transportation, and minimum cost
  100. * flow networks. Management Science 20 (1974), 814-20. */
  101. struct csa
  102. { /* common storage area */
  103. glp_graph *G;
  104. int v_rhs, a_cap, a_cost;
  105. int nodes, iarcs, mincst, maxcst, itsup, nsorc, nsink, nonsor,
  106. nfsink, narcs, nsort, nftsor, ipcap, mincap, maxcap, ktl,
  107. nodlft, *ipred, *ihead, *itail, *iflag, *isup, *lsinks, mult,
  108. modul, i15, i16, jran;
  109. };
  110. #define G (csa->G)
  111. #define v_rhs (csa->v_rhs)
  112. #define a_cap (csa->a_cap)
  113. #define a_cost (csa->a_cost)
  114. #define nodes (csa->nodes)
  115. #define iarcs (csa->iarcs)
  116. #define mincst (csa->mincst)
  117. #define maxcst (csa->maxcst)
  118. #define itsup (csa->itsup)
  119. #define nsorc (csa->nsorc)
  120. #define nsink (csa->nsink)
  121. #define nonsor (csa->nonsor)
  122. #define nfsink (csa->nfsink)
  123. #define narcs (csa->narcs)
  124. #define nsort (csa->nsort)
  125. #define nftsor (csa->nftsor)
  126. #define ipcap (csa->ipcap)
  127. #define mincap (csa->mincap)
  128. #define maxcap (csa->maxcap)
  129. #define ktl (csa->ktl)
  130. #define nodlft (csa->nodlft)
  131. #if 0
  132. /* spent a day to find out this bug */
  133. #define ist (csa->ist)
  134. #else
  135. #define ist (ipred[0])
  136. #endif
  137. #define ipred (csa->ipred)
  138. #define ihead (csa->ihead)
  139. #define itail (csa->itail)
  140. #define iflag (csa->iflag)
  141. #define isup (csa->isup)
  142. #define lsinks (csa->lsinks)
  143. #define mult (csa->mult)
  144. #define modul (csa->modul)
  145. #define i15 (csa->i15)
  146. #define i16 (csa->i16)
  147. #define jran (csa->jran)
  148. static void cresup(struct csa *csa);
  149. static void chain(struct csa *csa, int lpick, int lsorc);
  150. static void chnarc(struct csa *csa, int lsorc);
  151. static void sort(struct csa *csa);
  152. static void pickj(struct csa *csa, int it);
  153. static void assign(struct csa *csa);
  154. static void setran(struct csa *csa, int iseed);
  155. static int iran(struct csa *csa, int ilow, int ihigh);
  156. int glp_netgen(glp_graph *G_, int _v_rhs, int _a_cap, int _a_cost,
  157. const int parm[1+15])
  158. { struct csa _csa, *csa = &_csa;
  159. int iseed, nprob, ntsorc, ntsink, iphic, i, nskel, nltr, ltsink,
  160. ntrans, npsink, nftr, npsorc, ntravl, ntrrem, lsorc, lpick,
  161. nsksr, nsrchn, j, item, l, ks, k, ksp, li, n, ii, it, ih, icap,
  162. jcap, icost, jcost, ret;
  163. G = G_;
  164. v_rhs = _v_rhs;
  165. a_cap = _a_cap;
  166. a_cost = _a_cost;
  167. if (G != NULL)
  168. { if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double))
  169. xerror("glp_netgen: v_rhs = %d; invalid offset\n", v_rhs);
  170. if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
  171. xerror("glp_netgen: a_cap = %d; invalid offset\n", a_cap);
  172. if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
  173. xerror("glp_netgen: a_cost = %d; invalid offset\n", a_cost);
  174. }
  175. /* Input the user's random number seed and fix it if
  176. non-positive. */
  177. iseed = parm[1];
  178. nprob = parm[2];
  179. if (iseed <= 0) iseed = 13502460;
  180. setran(csa, iseed);
  181. /* Input the user's problem characteristics. */
  182. nodes = parm[3];
  183. nsorc = parm[4];
  184. nsink = parm[5];
  185. iarcs = parm[6];
  186. mincst = parm[7];
  187. maxcst = parm[8];
  188. itsup = parm[9];
  189. ntsorc = parm[10];
  190. ntsink = parm[11];
  191. iphic = parm[12];
  192. ipcap = parm[13];
  193. mincap = parm[14];
  194. maxcap = parm[15];
  195. /* Check the size of the problem. */
  196. if (!(10 <= nodes && nodes <= 100000))
  197. { ret = 1;
  198. goto done;
  199. }
  200. /* Check user supplied parameters for consistency. */
  201. if (!(nsorc >= 0 && nsink >= 0 && nsorc + nsink <= nodes))
  202. { ret = 2;
  203. goto done;
  204. }
  205. if (iarcs < 0)
  206. { ret = 3;
  207. goto done;
  208. }
  209. if (mincst > maxcst)
  210. { ret = 4;
  211. goto done;
  212. }
  213. if (itsup < 0)
  214. { ret = 5;
  215. goto done;
  216. }
  217. if (!(0 <= ntsorc && ntsorc <= nsorc))
  218. { ret = 6;
  219. goto done;
  220. }
  221. if (!(0 <= ntsink && ntsink <= nsink))
  222. { ret = 7;
  223. goto done;
  224. }
  225. if (!(0 <= iphic && iphic <= 100))
  226. { ret = 8;
  227. goto done;
  228. }
  229. if (!(0 <= ipcap && ipcap <= 100))
  230. { ret = 9;
  231. goto done;
  232. }
  233. if (mincap > maxcap)
  234. { ret = 10;
  235. goto done;
  236. }
  237. /* Initailize the graph object. */
  238. if (G != NULL)
  239. { glp_erase_graph(G, G->v_size, G->a_size);
  240. glp_add_vertices(G, nodes);
  241. if (v_rhs >= 0)
  242. { double zero = 0.0;
  243. for (i = 1; i <= nodes; i++)
  244. { glp_vertex *v = G->v[i];
  245. memcpy((char *)v->data + v_rhs, &zero, sizeof(double));
  246. }
  247. }
  248. }
  249. /* Allocate working arrays. */
  250. ipred = xcalloc(1+nodes, sizeof(int));
  251. ihead = xcalloc(1+nodes, sizeof(int));
  252. itail = xcalloc(1+nodes, sizeof(int));
  253. iflag = xcalloc(1+nodes, sizeof(int));
  254. isup = xcalloc(1+nodes, sizeof(int));
  255. lsinks = xcalloc(1+nodes, sizeof(int));
  256. /* Print the problem documentation records. */
  257. if (G == NULL)
  258. { xprintf("BEGIN\n");
  259. xprintf("NETGEN PROBLEM%8d%10s%10d NODES AND%10d ARCS\n",
  260. nprob, "", nodes, iarcs);
  261. xprintf("USER:%11d%11d%11d%11d%11d%11d\nDATA:%11d%11d%11d%11d%"
  262. "11d%11d\n", iseed, nsorc, nsink, mincst,
  263. maxcst, itsup, ntsorc, ntsink, iphic, ipcap,
  264. mincap, maxcap);
  265. }
  266. else
  267. glp_set_graph_name(G, "NETGEN");
  268. /* Set various constants used in the program. */
  269. narcs = 0;
  270. nskel = 0;
  271. nltr = nodes - nsink;
  272. ltsink = nltr + ntsink;
  273. ntrans = nltr - nsorc;
  274. nfsink = nltr + 1;
  275. nonsor = nodes - nsorc + ntsorc;
  276. npsink = nsink - ntsink;
  277. nodlft = nodes - nsink + ntsink;
  278. nftr = nsorc + 1;
  279. nftsor = nsorc - ntsorc + 1;
  280. npsorc = nsorc - ntsorc;
  281. /* Randomly distribute the supply among the source nodes. */
  282. if (npsorc + npsink == nodes && npsorc == npsink &&
  283. itsup == nsorc)
  284. { assign(csa);
  285. nskel = nsorc;
  286. goto L390;
  287. }
  288. cresup(csa);
  289. /* Print the supply records. */
  290. if (G == NULL)
  291. { xprintf("SUPPLY\n");
  292. for (i = 1; i <= nsorc; i++)
  293. xprintf("%6s%6d%18s%10d\n", "", i, "", isup[i]);
  294. xprintf("ARCS\n");
  295. }
  296. else
  297. { if (v_rhs >= 0)
  298. { for (i = 1; i <= nsorc; i++)
  299. { double temp = (double)isup[i];
  300. glp_vertex *v = G->v[i];
  301. memcpy((char *)v->data + v_rhs, &temp, sizeof(double));
  302. }
  303. }
  304. }
  305. /* Make the sources point to themselves in ipred array. */
  306. for (i = 1; i <= nsorc; i++)
  307. ipred[i] = i;
  308. if (ntrans == 0) goto L170;
  309. /* Chain the transshipment nodes together in the ipred array. */
  310. ist = nftr;
  311. ipred[nltr] = 0;
  312. for (i = nftr; i < nltr; i++)
  313. ipred[i] = i+1;
  314. /* Form even length chains for 60 percent of the transshipments.*/
  315. ntravl = 6 * ntrans / 10;
  316. ntrrem = ntrans - ntravl;
  317. L140: lsorc = 1;
  318. while (ntravl != 0)
  319. { lpick = iran(csa, 1, ntravl + ntrrem);
  320. ntravl--;
  321. chain(csa, lpick, lsorc);
  322. if (lsorc == nsorc) goto L140;
  323. lsorc++;
  324. }
  325. /* Add the remaining transshipments to the chains. */
  326. while (ntrrem != 0)
  327. {
  328. lpick = iran(csa, 1, ntrrem);
  329. ntrrem--;
  330. lsorc = iran(csa, 1, nsorc);
  331. chain(csa, lpick, lsorc);
  332. }
  333. L170: /* Set all demands equal to zero. */
  334. for (i = nfsink; i <= nodes; i++)
  335. ipred[i] = 0;
  336. /* The following loop takes one chain at a time (through the use
  337. of logic contained in the loop and calls to other routines) and
  338. creates the remaining network arcs. */
  339. for (lsorc = 1; lsorc <= nsorc; lsorc++)
  340. { chnarc(csa, lsorc);
  341. for (i = nfsink; i <= nodes; i++)
  342. iflag[i] = 0;
  343. /* Choose the number of sinks to be hooked up to the current
  344. chain. */
  345. if (ntrans != 0)
  346. nsksr = (nsort * 2 * nsink) / ntrans;
  347. else
  348. nsksr = nsink / nsorc + 1;
  349. if (nsksr < 2) nsksr = 2;
  350. if (nsksr > nsink) nsksr = nsink;
  351. nsrchn = nsort;
  352. /* Randomly pick nsksr sinks and put their names in lsinks. */
  353. ktl = nsink;
  354. for (j = 1; j <= nsksr; j++)
  355. { item = iran(csa, 1, ktl);
  356. ktl--;
  357. for (l = nfsink; l <= nodes; l++)
  358. { if (iflag[l] != 1)
  359. { item--;
  360. if (item == 0) goto L230;
  361. }
  362. }
  363. break;
  364. L230: lsinks[j] = l;
  365. iflag[l] = 1;
  366. }
  367. /* If last source chain, add all sinks with zero demand to
  368. lsinks list. */
  369. if (lsorc == nsorc)
  370. { for (j = nfsink; j <= nodes; j++)
  371. { if (ipred[j] == 0 && iflag[j] != 1)
  372. { nsksr++;
  373. lsinks[nsksr] = j;
  374. iflag[j] = 1;
  375. }
  376. }
  377. }
  378. /* Create demands for group of sinks in lsinks. */
  379. ks = isup[lsorc] / nsksr;
  380. k = ipred[lsorc];
  381. for (i = 1; i <= nsksr; i++)
  382. { nsort++;
  383. ksp = iran(csa, 1, ks);
  384. j = iran(csa, 1, nsksr);
  385. itail[nsort] = k;
  386. li = lsinks[i];
  387. ihead[nsort] = li;
  388. ipred[li] += ksp;
  389. li = lsinks[j];
  390. ipred[li] += ks - ksp;
  391. n = iran(csa, 1, nsrchn);
  392. k = lsorc;
  393. for (ii = 1; ii <= n; ii++)
  394. k = ipred[k];
  395. }
  396. li = lsinks[1];
  397. ipred[li] += isup[lsorc] - ks * nsksr;
  398. nskel += nsort;
  399. /* Sort the arcs in the chain from source lsorc using itail as
  400. sort key. */
  401. sort(csa);
  402. /* Print this part of skeleton and create the arcs for these
  403. nodes. */
  404. i = 1;
  405. itail[nsort+1] = 0;
  406. L300: for (j = nftsor; j <= nodes; j++)
  407. iflag[j] = 0;
  408. ktl = nonsor - 1;
  409. it = itail[i];
  410. iflag[it] = 1;
  411. L320: ih = ihead[i];
  412. iflag[ih] = 1;
  413. narcs++;
  414. ktl--;
  415. /* Determine if this skeleton arc should be capacitated. */
  416. icap = itsup;
  417. jcap = iran(csa, 1, 100);
  418. if (jcap <= ipcap)
  419. { icap = isup[lsorc];
  420. if (mincap > icap) icap = mincap;
  421. }
  422. /* Determine if this skeleton arc should have the maximum
  423. cost. */
  424. icost = maxcst;
  425. jcost = iran(csa, 1, 100);
  426. if (jcost > iphic)
  427. icost = iran(csa, mincst, maxcst);
  428. if (G == NULL)
  429. xprintf("%6s%6d%6d%2s%10d%10d\n", "", it, ih, "", icost,
  430. icap);
  431. else
  432. { glp_arc *a = glp_add_arc(G, it, ih);
  433. if (a_cap >= 0)
  434. { double temp = (double)icap;
  435. memcpy((char *)a->data + a_cap, &temp, sizeof(double));
  436. }
  437. if (a_cost >= 0)
  438. { double temp = (double)icost;
  439. memcpy((char *)a->data + a_cost, &temp, sizeof(double));
  440. }
  441. }
  442. i++;
  443. if (itail[i] == it) goto L320;
  444. pickj(csa, it);
  445. if (i <= nsort) goto L300;
  446. }
  447. /* Create arcs from the transshipment sinks. */
  448. if (ntsink != 0)
  449. { for (i = nfsink; i <= ltsink; i++)
  450. { for (j = nftsor; j <= nodes; j++)
  451. iflag[j] = 0;
  452. ktl = nonsor - 1;
  453. iflag[i] = 1;
  454. pickj(csa, i);
  455. }
  456. }
  457. L390: /* Print the demand records and end record. */
  458. if (G == NULL)
  459. { xprintf("DEMAND\n");
  460. for (i = nfsink; i <= nodes; i++)
  461. xprintf("%6s%6d%18s%10d\n", "", i, "", ipred[i]);
  462. xprintf("END\n");
  463. }
  464. else
  465. { if (v_rhs >= 0)
  466. { for (i = nfsink; i <= nodes; i++)
  467. { double temp = - (double)ipred[i];
  468. glp_vertex *v = G->v[i];
  469. memcpy((char *)v->data + v_rhs, &temp, sizeof(double));
  470. }
  471. }
  472. }
  473. /* Free working arrays. */
  474. xfree(ipred);
  475. xfree(ihead);
  476. xfree(itail);
  477. xfree(iflag);
  478. xfree(isup);
  479. xfree(lsinks);
  480. /* The instance has been successfully generated. */
  481. ret = 0;
  482. done: return ret;
  483. }
  484. /***********************************************************************
  485. * The routine cresup randomly distributes the total supply among the
  486. * source nodes. */
  487. static void cresup(struct csa *csa)
  488. { int i, j, ks, ksp;
  489. xassert(itsup > nsorc);
  490. ks = itsup / nsorc;
  491. for (i = 1; i <= nsorc; i++)
  492. isup[i] = 0;
  493. for (i = 1; i <= nsorc; i++)
  494. { ksp = iran(csa, 1, ks);
  495. j = iran(csa, 1, nsorc);
  496. isup[i] += ksp;
  497. isup[j] += ks - ksp;
  498. }
  499. j = iran(csa, 1, nsorc);
  500. isup[j] += itsup - ks * nsorc;
  501. return;
  502. }
  503. /***********************************************************************
  504. * The routine chain adds node lpick to the end of the chain with source
  505. * node lsorc. */
  506. static void chain(struct csa *csa, int lpick, int lsorc)
  507. { int i, j, k, l, m;
  508. k = 0;
  509. m = ist;
  510. for (i = 1; i <= lpick; i++)
  511. { l = k;
  512. k = m;
  513. m = ipred[k];
  514. }
  515. ipred[l] = m;
  516. j = ipred[lsorc];
  517. ipred[k] = j;
  518. ipred[lsorc] = k;
  519. return;
  520. }
  521. /***********************************************************************
  522. * The routine chnarc puts the arcs in the chain from source lsorc into
  523. * the ihead and itail arrays for sorting. */
  524. static void chnarc(struct csa *csa, int lsorc)
  525. { int ito, ifrom;
  526. nsort = 0;
  527. ito = ipred[lsorc];
  528. L10: if (ito == lsorc) return;
  529. nsort++;
  530. ifrom = ipred[ito];
  531. ihead[nsort] = ito;
  532. itail[nsort] = ifrom;
  533. ito = ifrom;
  534. goto L10;
  535. }
  536. /***********************************************************************
  537. * The routine sort sorts the nsort arcs in the ihead and itail arrays.
  538. * ihead is used as the sort key (i.e. forward star sort order). */
  539. static void sort(struct csa *csa)
  540. { int i, j, k, l, m, n, it;
  541. n = nsort;
  542. m = n;
  543. L10: m /= 2;
  544. if (m == 0) return;
  545. k = n - m;
  546. j = 1;
  547. L20: i = j;
  548. L30: l = i + m;
  549. if (itail[i] <= itail[l]) goto L40;
  550. it = itail[i];
  551. itail[i] = itail[l];
  552. itail[l] = it;
  553. it = ihead[i];
  554. ihead[i] = ihead[l];
  555. ihead[l] = it;
  556. i -= m;
  557. if (i >= 1) goto L30;
  558. L40: j++;
  559. if (j <= k) goto L20;
  560. goto L10;
  561. }
  562. /***********************************************************************
  563. * The routine pickj creates a random number of arcs out of node 'it'.
  564. * Various parameters are dynamically adjusted in an attempt to ensure
  565. * that the generated network has the correct number of arcs. */
  566. static void pickj(struct csa *csa, int it)
  567. { int j, k, l, nn, nupbnd, icap, jcap, icost;
  568. if ((nodlft - 1) * 2 > iarcs - narcs - 1)
  569. { nodlft--;
  570. return;
  571. }
  572. if ((iarcs - narcs + nonsor - ktl - 1) / nodlft - nonsor + 1 >= 0)
  573. k = nonsor;
  574. else
  575. { nupbnd = (iarcs - narcs - nodlft) / nodlft * 2;
  576. L40: k = iran(csa, 1, nupbnd);
  577. if (nodlft == 1) k = iarcs - narcs;
  578. if ((nodlft - 1) * (nonsor - 1) < iarcs - narcs - k) goto L40;
  579. }
  580. nodlft--;
  581. for (j = 1; j <= k; j++)
  582. { nn = iran(csa, 1, ktl);
  583. ktl--;
  584. for (l = nftsor; l <= nodes; l++)
  585. { if (iflag[l] != 1)
  586. { nn--;
  587. if (nn == 0) goto L70;
  588. }
  589. }
  590. return;
  591. L70: iflag[l] = 1;
  592. icap = itsup;
  593. jcap = iran(csa, 1, 100);
  594. if (jcap <= ipcap)
  595. icap = iran(csa, mincap, maxcap);
  596. icost = iran(csa, mincst, maxcst);
  597. if (G == NULL)
  598. xprintf("%6s%6d%6d%2s%10d%10d\n", "", it, l, "", icost,
  599. icap);
  600. else
  601. { glp_arc *a = glp_add_arc(G, it, l);
  602. if (a_cap >= 0)
  603. { double temp = (double)icap;
  604. memcpy((char *)a->data + a_cap, &temp, sizeof(double));
  605. }
  606. if (a_cost >= 0)
  607. { double temp = (double)icost;
  608. memcpy((char *)a->data + a_cost, &temp, sizeof(double));
  609. }
  610. }
  611. narcs++;
  612. }
  613. return;
  614. }
  615. /***********************************************************************
  616. * The routine assign generate assignment problems. It defines the unit
  617. * supplies, builds a skeleton, then calls pickj to create the arcs. */
  618. static void assign(struct csa *csa)
  619. { int i, it, nn, l, ll, icost;
  620. if (G == NULL)
  621. xprintf("SUPPLY\n");
  622. for (i = 1; i <= nsorc; i++)
  623. { isup[i] = 1;
  624. iflag[i] = 0;
  625. if (G == NULL)
  626. xprintf("%6s%6d%18s%10d\n", "", i, "", isup[i]);
  627. else
  628. { if (v_rhs >= 0)
  629. { double temp = (double)isup[i];
  630. glp_vertex *v = G->v[i];
  631. memcpy((char *)v->data + v_rhs, &temp, sizeof(double));
  632. }
  633. }
  634. }
  635. if (G == NULL)
  636. xprintf("ARCS\n");
  637. for (i = nfsink; i <= nodes; i++)
  638. ipred[i] = 1;
  639. for (it = 1; it <= nsorc; it++)
  640. { for (i = nfsink; i <= nodes; i++)
  641. iflag[i] = 0;
  642. ktl = nsink - 1;
  643. nn = iran(csa, 1, nsink - it + 1);
  644. for (l = 1; l <= nsorc; l++)
  645. { if (iflag[l] != 1)
  646. { nn--;
  647. if (nn == 0) break;
  648. }
  649. }
  650. narcs++;
  651. ll = nsorc + l;
  652. icost = iran(csa, mincst, maxcst);
  653. if (G == NULL)
  654. xprintf("%6s%6d%6d%2s%10d%10d\n", "", it, ll, "", icost,
  655. isup[1]);
  656. else
  657. { glp_arc *a = glp_add_arc(G, it, ll);
  658. if (a_cap >= 0)
  659. { double temp = (double)isup[1];
  660. memcpy((char *)a->data + a_cap, &temp, sizeof(double));
  661. }
  662. if (a_cost >= 0)
  663. { double temp = (double)icost;
  664. memcpy((char *)a->data + a_cost, &temp, sizeof(double));
  665. }
  666. }
  667. iflag[l] = 1;
  668. iflag[ll] = 1;
  669. pickj(csa, it);
  670. }
  671. return;
  672. }
  673. /***********************************************************************
  674. * Portable congruential (uniform) random number generator:
  675. *
  676. * next_value = ((7**5) * previous_value) modulo ((2**31)-1)
  677. *
  678. * This generator consists of three routines:
  679. *
  680. * (1) setran - initializes constants and seed
  681. * (2) iran - generates an integer random number
  682. * (3) rran - generates a real random number
  683. *
  684. * The generator requires a machine with at least 32 bits of precision.
  685. * The seed (iseed) must be in the range [1,(2**31)-1]. */
  686. static void setran(struct csa *csa, int iseed)
  687. { xassert(iseed >= 1);
  688. mult = 16807;
  689. modul = 2147483647;
  690. i15 = 1 << 15;
  691. i16 = 1 << 16;
  692. jran = iseed;
  693. return;
  694. }
  695. /***********************************************************************
  696. * The routine iran generates an integer random number between ilow and
  697. * ihigh. If ilow > ihigh then iran returns ihigh. */
  698. static int iran(struct csa *csa, int ilow, int ihigh)
  699. { int ixhi, ixlo, ixalo, leftlo, ixahi, ifulhi, irtlo, iover,
  700. irthi, j;
  701. ixhi = jran / i16;
  702. ixlo = jran - ixhi * i16;
  703. ixalo = ixlo * mult;
  704. leftlo = ixalo / i16;
  705. ixahi = ixhi * mult;
  706. ifulhi = ixahi + leftlo;
  707. irtlo = ixalo - leftlo * i16;
  708. iover = ifulhi / i15;
  709. irthi = ifulhi - iover * i15;
  710. jran = ((irtlo - modul) + irthi * i16) + iover;
  711. if (jran < 0) jran += modul;
  712. j = ihigh - ilow + 1;
  713. if (j > 0)
  714. return jran % j + ilow;
  715. else
  716. return ihigh;
  717. }
  718. /***********************************************************************
  719. * NAME
  720. *
  721. * glp_netgen_prob - Klingman's standard network problem instance
  722. *
  723. * SYNOPSIS
  724. *
  725. * void glp_netgen_prob(int nprob, int parm[1+15]);
  726. *
  727. * DESCRIPTION
  728. *
  729. * The routine glp_netgen_prob provides the set of parameters for
  730. * Klingman's network problem generator (see the routine glp_netgen),
  731. * which describe a standard network problem instance.
  732. *
  733. * The parameter nprob (101 <= nprob <= 150) specifies the problem
  734. * instance number.
  735. *
  736. * The array parm contains description of the network, provided by the
  737. * routine. (For detailed description of these parameters see comments
  738. * to the routine glp_netgen.)
  739. *
  740. * PROBLEM CHARACTERISTICS
  741. *
  742. * The table below shows characteristics of Klingman's standard network
  743. * problem instances.
  744. *
  745. * Problem Nodes Arcs Optimum
  746. * ------- ----- ----- ----------
  747. * 101 5000 25336 6191726
  748. * 102 5000 25387 72337144
  749. * 103 5000 25355 218947553
  750. * 104 5000 25344 -19100371
  751. * 105 5000 25332 31192578
  752. * 106 5000 12870 4314276
  753. * 107 5000 37832 7393769
  754. * 108 5000 50309 8405738
  755. * 109 5000 75299 9190300
  756. * 110 5000 12825 8975048
  757. * 111 5000 37828 4747532
  758. * 112 5000 50325 4012671
  759. * 113 5000 75318 2979725
  760. * 114 5000 26514 5821181
  761. * 115 5000 25962 6353310
  762. * 116 5000 25304 5915426
  763. * 117 5000 12816 4420560
  764. * 118 5000 37797 7045842
  765. * 119 5000 50301 7724179
  766. * 120 5000 75330 8455200
  767. * 121 5000 25000 66366360
  768. * 122 5000 25000 30997529
  769. * 123 5000 25000 23388777
  770. * 124 5000 25000 17803443
  771. * 125 5000 25000 14119622
  772. * 126 5000 12500 18802218
  773. * 127 5000 37500 27674647
  774. * 128 5000 50000 30906194
  775. * 129 5000 75000 40905209
  776. * 130 5000 12500 38939608
  777. * 131 5000 37500 16752978
  778. * 132 5000 50000 13302951
  779. * 133 5000 75000 9830268
  780. * 134 1000 25000 3804874
  781. * 135 2500 25000 11729616
  782. * 136 7500 25000 33318101
  783. * 137 10000 25000 46426030
  784. * 138 5000 25000 60710879
  785. * 139 5000 25000 32729682
  786. * 140 5000 25000 27183831
  787. * 141 5000 25000 19963286
  788. * 142 5000 25000 20243457
  789. * 143 5000 25000 18586777
  790. * 144 5000 25000 2504591
  791. * 145 5000 25000 215956138
  792. * 146 5000 25000 2253113811
  793. * 147 5000 25000 -427908373
  794. * 148 5000 25000 -92965318
  795. * 149 5000 25000 86051224
  796. * 150 5000 25000 619314919 */
  797. static const int data[50][1+15] =
  798. { { 0, 13502460, 101, 5000, 2500, 2500, 25000,
  799. 1, 100, 250000, 0, 0, 0, 100, 1, 1000
  800. },
  801. { 0, 4281922, 102, 5000, 2500, 2500, 25000,
  802. 1, 100, 2500000, 0, 0, 0, 100, 1, 1000
  803. },
  804. { 0, 44820113, 103, 5000, 2500, 2500, 25000,
  805. 1, 100, 6250000, 0, 0, 0, 100, 1, 1000
  806. },
  807. { 0, 13450451, 104, 5000, 2500, 2500, 25000,
  808. -100, -1, 250000, 0, 0, 0, 100, 1, 1000
  809. },
  810. { 0, 14719436, 105, 5000, 2500, 2500, 25000,
  811. 101, 200, 250000, 0, 0, 0, 100, 1, 1000
  812. },
  813. { 0, 17365786, 106, 5000, 2500, 2500, 12500,
  814. 1, 100, 125000, 0, 0, 0, 100, 1, 1000
  815. },
  816. { 0, 19540113, 107, 5000, 2500, 2500, 37500,
  817. 1, 100, 375000, 0, 0, 0, 100, 1, 1000
  818. },
  819. { 0, 19560313, 108, 5000, 2500, 2500, 50000,
  820. 1, 100, 500000, 0, 0, 0, 100, 1, 1000
  821. },
  822. { 0, 2403509, 109, 5000, 2500, 2500, 75000,
  823. 1, 100, 750000, 0, 0, 0, 100, 1, 1000
  824. },
  825. { 0, 92480414, 110, 5000, 2500, 2500, 12500,
  826. 1, 100, 250000, 0, 0, 0, 100, 1, 1000
  827. },
  828. { 0, 4230140, 111, 5000, 2500, 2500, 37500,
  829. 1, 100, 250000, 0, 0, 0, 100, 1, 1000
  830. },
  831. { 0, 10032490, 112, 5000, 2500, 2500, 50000,
  832. 1, 100, 250000, 0, 0, 0, 100, 1, 1000
  833. },
  834. { 0, 17307474, 113, 5000, 2500, 2500, 75000,
  835. 1, 100, 250000, 0, 0, 0, 100, 1, 1000
  836. },
  837. { 0, 4925114, 114, 5000, 500, 4500, 25000,
  838. 1, 100, 250000, 0, 0, 0, 100, 1, 1000
  839. },
  840. { 0, 19842704, 115, 5000, 1500, 3500, 25000,
  841. 1, 100, 250000, 0, 0, 0, 100, 1, 1000
  842. },
  843. { 0, 88392060, 116, 5000, 2500, 2500, 25000,
  844. 1, 100, 250000, 0, 0, 0, 0, 1, 1000
  845. },
  846. { 0, 12904407, 117, 5000, 2500, 2500, 12500,
  847. 1, 100, 125000, 0, 0, 0, 0, 1, 1000
  848. },
  849. { 0, 11811811, 118, 5000, 2500, 2500, 37500,
  850. 1, 100, 375000, 0, 0, 0, 0, 1, 1000
  851. },
  852. { 0, 90023593, 119, 5000, 2500, 2500, 50000,
  853. 1, 100, 500000, 0, 0, 0, 0, 1, 1000
  854. },
  855. { 0, 93028922, 120, 5000, 2500, 2500, 75000,
  856. 1, 100, 750000, 0, 0, 0, 0, 1, 1000
  857. },
  858. { 0, 72707401, 121, 5000, 50, 50, 25000,
  859. 1, 100, 250000, 50, 50, 0, 100, 1, 1000
  860. },
  861. { 0, 93040771, 122, 5000, 250, 250, 25000,
  862. 1, 100, 250000, 250, 250, 0, 100, 1, 1000
  863. },
  864. { 0, 70220611, 123, 5000, 500, 500, 25000,
  865. 1, 100, 250000, 500, 500, 0, 100, 1, 1000
  866. },
  867. { 0, 52774811, 124, 5000, 1000, 1000, 25000,
  868. 1, 100, 250000, 1000, 1000, 0, 100, 1, 1000
  869. },
  870. { 0, 22492311, 125, 5000, 1500, 1500, 25000,
  871. 1, 100, 250000, 1500, 1500, 0, 100, 1, 1000
  872. },
  873. { 0, 35269337, 126, 5000, 500, 500, 12500,
  874. 1, 100, 125000, 500, 500, 0, 100, 1, 1000
  875. },
  876. { 0, 30140502, 127, 5000, 500, 500, 37500,
  877. 1, 100, 375000, 500, 500, 0, 100, 1, 1000
  878. },
  879. { 0, 49205455, 128, 5000, 500, 500, 50000,
  880. 1, 100, 500000, 500, 500, 0, 100, 1, 1000
  881. },
  882. { 0, 42958341, 129, 5000, 500, 500, 75000,
  883. 1, 100, 750000, 500, 500, 0, 100, 1, 1000
  884. },
  885. { 0, 25440925, 130, 5000, 500, 500, 12500,
  886. 1, 100, 250000, 500, 500, 0, 100, 1, 1000
  887. },
  888. { 0, 75294924, 131, 5000, 500, 500, 37500,
  889. 1, 100, 250000, 500, 500, 0, 100, 1, 1000
  890. },
  891. { 0, 4463965, 132, 5000, 500, 500, 50000,
  892. 1, 100, 250000, 500, 500, 0, 100, 1, 1000
  893. },
  894. { 0, 13390427, 133, 5000, 500, 500, 75000,
  895. 1, 100, 250000, 500, 500, 0, 100, 1, 1000
  896. },
  897. { 0, 95250971, 134, 1000, 500, 500, 25000,
  898. 1, 100, 250000, 500, 500, 0, 100, 1, 1000
  899. },
  900. { 0, 54830522, 135, 2500, 500, 500, 25000,
  901. 1, 100, 250000, 500, 500, 0, 100, 1, 1000
  902. },
  903. { 0, 520593, 136, 7500, 500, 500, 25000,
  904. 1, 100, 250000, 500, 500, 0, 100, 1, 1000
  905. },
  906. { 0, 52900925, 137, 10000, 500, 500, 25000,
  907. 1, 100, 250000, 500, 500, 0, 100, 1, 1000
  908. },
  909. { 0, 22603395, 138, 5000, 500, 500, 25000,
  910. 1, 100, 250000, 500, 500, 0, 100, 1, 50
  911. },
  912. { 0, 55253099, 139, 5000, 500, 500, 25000,
  913. 1, 100, 250000, 500, 500, 0, 100, 1, 250
  914. },
  915. { 0, 75357001, 140, 5000, 500, 500, 25000,
  916. 1, 100, 250000, 500, 500, 0, 100, 1, 500
  917. },
  918. { 0, 10072459, 141, 5000, 500, 500, 25000,
  919. 1, 100, 250000, 500, 500, 0, 100, 1, 2500
  920. },
  921. { 0, 55728492, 142, 5000, 500, 500, 25000,
  922. 1, 100, 250000, 500, 500, 0, 100, 1, 5000
  923. },
  924. { 0, 593043, 143, 5000, 500, 500, 25000,
  925. 1, 100, 250000, 500, 500, 0, 0, 1, 1000
  926. },
  927. { 0, 94236572, 144, 5000, 500, 500, 25000,
  928. 1, 10, 250000, 500, 500, 0, 100, 1, 1000
  929. },
  930. { 0, 94882955, 145, 5000, 500, 500, 25000,
  931. 1, 1000, 250000, 500, 500, 0, 100, 1, 1000
  932. },
  933. { 0, 48489922, 146, 5000, 500, 500, 25000,
  934. 1, 10000, 250000, 500, 500, 0, 100, 1, 1000
  935. },
  936. { 0, 75578374, 147, 5000, 500, 500, 25000,
  937. -100, -1, 250000, 500, 500, 0, 100, 1, 1000
  938. },
  939. { 0, 44821152, 148, 5000, 500, 500, 25000,
  940. -50, 49, 250000, 500, 500, 0, 100, 1, 1000
  941. },
  942. { 0, 45224103, 149, 5000, 500, 500, 25000,
  943. 101, 200, 250000, 500, 500, 0, 100, 1, 1000
  944. },
  945. { 0, 63491741, 150, 5000, 500, 500, 25000,
  946. 1001, 1100, 250000, 500, 500, 0, 100, 1, 1000
  947. },
  948. };
  949. void glp_netgen_prob(int nprob, int parm[1+15])
  950. { int k;
  951. if (!(101 <= nprob && nprob <= 150))
  952. xerror("glp_netgen_prob: nprob = %d; invalid problem instance "
  953. "number\n", nprob);
  954. for (k = 1; k <= 15; k++)
  955. parm[k] = data[nprob-101][k];
  956. return;
  957. }
  958. /**********************************************************************/
  959. #if 0
  960. static int scan(char card[80+1], int pos, int len)
  961. { char buf[10+1];
  962. memcpy(buf, &card[pos-1], len);
  963. buf[len] = '\0';
  964. return atoi(buf);
  965. }
  966. int main(void)
  967. { int parm[1+15];
  968. char card[80+1];
  969. xassert(fgets(card, sizeof(card), stdin) == card);
  970. parm[1] = scan(card, 1, 8);
  971. parm[2] = scan(card, 9, 8);
  972. xassert(fgets(card, sizeof(card), stdin) == card);
  973. parm[3] = scan(card, 1, 5);
  974. parm[4] = scan(card, 6, 5);
  975. parm[5] = scan(card, 11, 5);
  976. parm[6] = scan(card, 16, 5);
  977. parm[7] = scan(card, 21, 5);
  978. parm[8] = scan(card, 26, 5);
  979. parm[9] = scan(card, 31, 10);
  980. parm[10] = scan(card, 41, 5);
  981. parm[11] = scan(card, 46, 5);
  982. parm[12] = scan(card, 51, 5);
  983. parm[13] = scan(card, 56, 5);
  984. parm[14] = scan(card, 61, 10);
  985. parm[15] = scan(card, 71, 10);
  986. glp_netgen(NULL, 0, 0, 0, parm);
  987. return 0;
  988. }
  989. #endif
  990. /* eof */