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.

1693 lines
57 KiB

  1. /* glpdmx.c (reading/writing data in DIMACS format) */
  2. /***********************************************************************
  3. * This code is part of GLPK (GNU Linear Programming Kit).
  4. *
  5. * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
  6. * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied
  7. * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
  8. * reserved. E-mail: <mao@gnu.org>.
  9. *
  10. * GLPK is free software: you can redistribute it and/or modify it
  11. * under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation, either version 3 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * GLPK is distributed in the hope that it will be useful, but WITHOUT
  16. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  17. * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
  18. * License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with GLPK. If not, see <http://www.gnu.org/licenses/>.
  22. ***********************************************************************/
  23. #include "env.h"
  24. #include "misc.h"
  25. #include "prob.h"
  26. #define xfprintf glp_format
  27. struct csa
  28. { /* common storage area */
  29. jmp_buf jump;
  30. /* label for go to in case of error */
  31. const char *fname;
  32. /* name of input text file */
  33. glp_file *fp;
  34. /* stream assigned to input text file */
  35. int count;
  36. /* line count */
  37. int c;
  38. /* current character */
  39. char field[255+1];
  40. /* data field */
  41. int empty;
  42. /* warning 'empty line ignored' was printed */
  43. int nonint;
  44. /* warning 'non-integer data detected' was printed */
  45. };
  46. static void error(struct csa *csa, const char *fmt, ...)
  47. { /* print error message and terminate processing */
  48. va_list arg;
  49. xprintf("%s:%d: error: ", csa->fname, csa->count);
  50. va_start(arg, fmt);
  51. xvprintf(fmt, arg);
  52. va_end(arg);
  53. xprintf("\n");
  54. longjmp(csa->jump, 1);
  55. /* no return */
  56. }
  57. static void warning(struct csa *csa, const char *fmt, ...)
  58. { /* print warning message and continue processing */
  59. va_list arg;
  60. xprintf("%s:%d: warning: ", csa->fname, csa->count);
  61. va_start(arg, fmt);
  62. xvprintf(fmt, arg);
  63. va_end(arg);
  64. xprintf("\n");
  65. return;
  66. }
  67. static void read_char(struct csa *csa)
  68. { /* read character from input text file */
  69. int c;
  70. if (csa->c == '\n') csa->count++;
  71. c = glp_getc(csa->fp);
  72. if (c < 0)
  73. { if (glp_ioerr(csa->fp))
  74. error(csa, "read error - %s", get_err_msg());
  75. else if (csa->c == '\n')
  76. error(csa, "unexpected end of file");
  77. else
  78. { warning(csa, "missing final end of line");
  79. c = '\n';
  80. }
  81. }
  82. else if (c == '\n')
  83. ;
  84. else if (isspace(c))
  85. c = ' ';
  86. else if (iscntrl(c))
  87. error(csa, "invalid control character 0x%02X", c);
  88. csa->c = c;
  89. return;
  90. }
  91. static void read_designator(struct csa *csa)
  92. { /* read one-character line designator */
  93. xassert(csa->c == '\n');
  94. read_char(csa);
  95. for (;;)
  96. { /* skip preceding white-space characters */
  97. while (csa->c == ' ')
  98. read_char(csa);
  99. if (csa->c == '\n')
  100. { /* ignore empty line */
  101. if (!csa->empty)
  102. { warning(csa, "empty line ignored");
  103. csa->empty = 1;
  104. }
  105. read_char(csa);
  106. }
  107. else if (csa->c == 'c')
  108. { /* skip comment line */
  109. while (csa->c != '\n')
  110. read_char(csa);
  111. read_char(csa);
  112. }
  113. else
  114. { /* hmm... looks like a line designator */
  115. csa->field[0] = (char)csa->c, csa->field[1] = '\0';
  116. /* check that it is followed by a white-space character */
  117. read_char(csa);
  118. if (!(csa->c == ' ' || csa->c == '\n'))
  119. error(csa, "line designator missing or invalid");
  120. break;
  121. }
  122. }
  123. return;
  124. }
  125. static void read_field(struct csa *csa)
  126. { /* read data field */
  127. int len = 0;
  128. /* skip preceding white-space characters */
  129. while (csa->c == ' ')
  130. read_char(csa);
  131. /* scan data field */
  132. if (csa->c == '\n')
  133. error(csa, "unexpected end of line");
  134. while (!(csa->c == ' ' || csa->c == '\n'))
  135. { if (len == sizeof(csa->field)-1)
  136. error(csa, "data field `%.15s...' too long", csa->field);
  137. csa->field[len++] = (char)csa->c;
  138. read_char(csa);
  139. }
  140. csa->field[len] = '\0';
  141. return;
  142. }
  143. static void end_of_line(struct csa *csa)
  144. { /* skip white-space characters until end of line */
  145. while (csa->c == ' ')
  146. read_char(csa);
  147. if (csa->c != '\n')
  148. error(csa, "too many data fields specified");
  149. return;
  150. }
  151. static void check_int(struct csa *csa, double num)
  152. { /* print a warning if non-integer data are detected */
  153. if (!csa->nonint && num != floor(num))
  154. { warning(csa, "non-integer data detected");
  155. csa->nonint = 1;
  156. }
  157. return;
  158. }
  159. /***********************************************************************
  160. * NAME
  161. *
  162. * glp_read_mincost - read min-cost flow problem data in DIMACS format
  163. *
  164. * SYNOPSIS
  165. *
  166. * int glp_read_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap,
  167. * int a_cost, const char *fname);
  168. *
  169. * DESCRIPTION
  170. *
  171. * The routine glp_read_mincost reads minimum cost flow problem data in
  172. * DIMACS format from a text file.
  173. *
  174. * RETURNS
  175. *
  176. * If the operation was successful, the routine returns zero. Otherwise
  177. * it prints an error message and returns non-zero. */
  178. int glp_read_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap,
  179. int a_cost, const char *fname)
  180. { struct csa _csa, *csa = &_csa;
  181. glp_vertex *v;
  182. glp_arc *a;
  183. int i, j, k, nv, na, ret = 0;
  184. double rhs, low, cap, cost;
  185. char *flag = NULL;
  186. if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double))
  187. xerror("glp_read_mincost: v_rhs = %d; invalid offset\n",
  188. v_rhs);
  189. if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double))
  190. xerror("glp_read_mincost: a_low = %d; invalid offset\n",
  191. a_low);
  192. if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
  193. xerror("glp_read_mincost: a_cap = %d; invalid offset\n",
  194. a_cap);
  195. if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
  196. xerror("glp_read_mincost: a_cost = %d; invalid offset\n",
  197. a_cost);
  198. glp_erase_graph(G, G->v_size, G->a_size);
  199. if (setjmp(csa->jump))
  200. { ret = 1;
  201. goto done;
  202. }
  203. csa->fname = fname;
  204. csa->fp = NULL;
  205. csa->count = 0;
  206. csa->c = '\n';
  207. csa->field[0] = '\0';
  208. csa->empty = csa->nonint = 0;
  209. xprintf("Reading min-cost flow problem data from `%s'...\n",
  210. fname);
  211. csa->fp = glp_open(fname, "r");
  212. if (csa->fp == NULL)
  213. { xprintf("Unable to open `%s' - %s\n", fname, get_err_msg());
  214. longjmp(csa->jump, 1);
  215. }
  216. /* read problem line */
  217. read_designator(csa);
  218. if (strcmp(csa->field, "p") != 0)
  219. error(csa, "problem line missing or invalid");
  220. read_field(csa);
  221. if (strcmp(csa->field, "min") != 0)
  222. error(csa, "wrong problem designator; `min' expected");
  223. read_field(csa);
  224. if (!(str2int(csa->field, &nv) == 0 && nv >= 0))
  225. error(csa, "number of nodes missing or invalid");
  226. read_field(csa);
  227. if (!(str2int(csa->field, &na) == 0 && na >= 0))
  228. error(csa, "number of arcs missing or invalid");
  229. xprintf("Flow network has %d node%s and %d arc%s\n",
  230. nv, nv == 1 ? "" : "s", na, na == 1 ? "" : "s");
  231. if (nv > 0) glp_add_vertices(G, nv);
  232. end_of_line(csa);
  233. /* read node descriptor lines */
  234. flag = xcalloc(1+nv, sizeof(char));
  235. memset(&flag[1], 0, nv * sizeof(char));
  236. if (v_rhs >= 0)
  237. { rhs = 0.0;
  238. for (i = 1; i <= nv; i++)
  239. { v = G->v[i];
  240. memcpy((char *)v->data + v_rhs, &rhs, sizeof(double));
  241. }
  242. }
  243. for (;;)
  244. { read_designator(csa);
  245. if (strcmp(csa->field, "n") != 0) break;
  246. read_field(csa);
  247. if (str2int(csa->field, &i) != 0)
  248. error(csa, "node number missing or invalid");
  249. if (!(1 <= i && i <= nv))
  250. error(csa, "node number %d out of range", i);
  251. if (flag[i])
  252. error(csa, "duplicate descriptor of node %d", i);
  253. read_field(csa);
  254. if (str2num(csa->field, &rhs) != 0)
  255. error(csa, "node supply/demand missing or invalid");
  256. check_int(csa, rhs);
  257. if (v_rhs >= 0)
  258. { v = G->v[i];
  259. memcpy((char *)v->data + v_rhs, &rhs, sizeof(double));
  260. }
  261. flag[i] = 1;
  262. end_of_line(csa);
  263. }
  264. xfree(flag), flag = NULL;
  265. /* read arc descriptor lines */
  266. for (k = 1; k <= na; k++)
  267. { if (k > 1) read_designator(csa);
  268. if (strcmp(csa->field, "a") != 0)
  269. error(csa, "wrong line designator; `a' expected");
  270. read_field(csa);
  271. if (str2int(csa->field, &i) != 0)
  272. error(csa, "starting node number missing or invalid");
  273. if (!(1 <= i && i <= nv))
  274. error(csa, "starting node number %d out of range", i);
  275. read_field(csa);
  276. if (str2int(csa->field, &j) != 0)
  277. error(csa, "ending node number missing or invalid");
  278. if (!(1 <= j && j <= nv))
  279. error(csa, "ending node number %d out of range", j);
  280. read_field(csa);
  281. if (!(str2num(csa->field, &low) == 0 && low >= 0.0))
  282. error(csa, "lower bound of arc flow missing or invalid");
  283. check_int(csa, low);
  284. read_field(csa);
  285. if (!(str2num(csa->field, &cap) == 0 && cap >= low))
  286. error(csa, "upper bound of arc flow missing or invalid");
  287. check_int(csa, cap);
  288. read_field(csa);
  289. if (str2num(csa->field, &cost) != 0)
  290. error(csa, "per-unit cost of arc flow missing or invalid");
  291. check_int(csa, cost);
  292. a = glp_add_arc(G, i, j);
  293. if (a_low >= 0)
  294. memcpy((char *)a->data + a_low, &low, sizeof(double));
  295. if (a_cap >= 0)
  296. memcpy((char *)a->data + a_cap, &cap, sizeof(double));
  297. if (a_cost >= 0)
  298. memcpy((char *)a->data + a_cost, &cost, sizeof(double));
  299. end_of_line(csa);
  300. }
  301. xprintf("%d lines were read\n", csa->count);
  302. done: if (ret) glp_erase_graph(G, G->v_size, G->a_size);
  303. if (csa->fp != NULL) glp_close(csa->fp);
  304. if (flag != NULL) xfree(flag);
  305. return ret;
  306. }
  307. /***********************************************************************
  308. * NAME
  309. *
  310. * glp_write_mincost - write min-cost flow problem data in DIMACS format
  311. *
  312. * SYNOPSIS
  313. *
  314. * int glp_write_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap,
  315. * int a_cost, const char *fname);
  316. *
  317. * DESCRIPTION
  318. *
  319. * The routine glp_write_mincost writes minimum cost flow problem data
  320. * in DIMACS format to a text file.
  321. *
  322. * RETURNS
  323. *
  324. * If the operation was successful, the routine returns zero. Otherwise
  325. * it prints an error message and returns non-zero. */
  326. int glp_write_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap,
  327. int a_cost, const char *fname)
  328. { glp_file *fp;
  329. glp_vertex *v;
  330. glp_arc *a;
  331. int i, count = 0, ret;
  332. double rhs, low, cap, cost;
  333. if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double))
  334. xerror("glp_write_mincost: v_rhs = %d; invalid offset\n",
  335. v_rhs);
  336. if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double))
  337. xerror("glp_write_mincost: a_low = %d; invalid offset\n",
  338. a_low);
  339. if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
  340. xerror("glp_write_mincost: a_cap = %d; invalid offset\n",
  341. a_cap);
  342. if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
  343. xerror("glp_write_mincost: a_cost = %d; invalid offset\n",
  344. a_cost);
  345. xprintf("Writing min-cost flow problem data to `%s'...\n",
  346. fname);
  347. fp = glp_open(fname, "w");
  348. if (fp == NULL)
  349. { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg());
  350. ret = 1;
  351. goto done;
  352. }
  353. xfprintf(fp, "c %s\n",
  354. G->name == NULL ? "unknown" : G->name), count++;
  355. xfprintf(fp, "p min %d %d\n", G->nv, G->na), count++;
  356. if (v_rhs >= 0)
  357. { for (i = 1; i <= G->nv; i++)
  358. { v = G->v[i];
  359. memcpy(&rhs, (char *)v->data + v_rhs, sizeof(double));
  360. if (rhs != 0.0)
  361. xfprintf(fp, "n %d %.*g\n", i, DBL_DIG, rhs), count++;
  362. }
  363. }
  364. for (i = 1; i <= G->nv; i++)
  365. { v = G->v[i];
  366. for (a = v->out; a != NULL; a = a->t_next)
  367. { if (a_low >= 0)
  368. memcpy(&low, (char *)a->data + a_low, sizeof(double));
  369. else
  370. low = 0.0;
  371. if (a_cap >= 0)
  372. memcpy(&cap, (char *)a->data + a_cap, sizeof(double));
  373. else
  374. cap = 1.0;
  375. if (a_cost >= 0)
  376. memcpy(&cost, (char *)a->data + a_cost, sizeof(double));
  377. else
  378. cost = 0.0;
  379. xfprintf(fp, "a %d %d %.*g %.*g %.*g\n",
  380. a->tail->i, a->head->i, DBL_DIG, low, DBL_DIG, cap,
  381. DBL_DIG, cost), count++;
  382. }
  383. }
  384. xfprintf(fp, "c eof\n"), count++;
  385. #if 0 /* FIXME */
  386. xfflush(fp);
  387. #endif
  388. if (glp_ioerr(fp))
  389. { xprintf("Write error on `%s' - %s\n", fname, get_err_msg());
  390. ret = 1;
  391. goto done;
  392. }
  393. xprintf("%d lines were written\n", count);
  394. ret = 0;
  395. done: if (fp != NULL) glp_close(fp);
  396. return ret;
  397. }
  398. /***********************************************************************
  399. * NAME
  400. *
  401. * glp_read_maxflow - read maximum flow problem data in DIMACS format
  402. *
  403. * SYNOPSIS
  404. *
  405. * int glp_read_maxflow(glp_graph *G, int *s, int *t, int a_cap,
  406. * const char *fname);
  407. *
  408. * DESCRIPTION
  409. *
  410. * The routine glp_read_maxflow reads maximum flow problem data in
  411. * DIMACS format from a text file.
  412. *
  413. * RETURNS
  414. *
  415. * If the operation was successful, the routine returns zero. Otherwise
  416. * it prints an error message and returns non-zero. */
  417. int glp_read_maxflow(glp_graph *G, int *_s, int *_t, int a_cap,
  418. const char *fname)
  419. { struct csa _csa, *csa = &_csa;
  420. glp_arc *a;
  421. int i, j, k, s, t, nv, na, ret = 0;
  422. double cap;
  423. if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
  424. xerror("glp_read_maxflow: a_cap = %d; invalid offset\n",
  425. a_cap);
  426. glp_erase_graph(G, G->v_size, G->a_size);
  427. if (setjmp(csa->jump))
  428. { ret = 1;
  429. goto done;
  430. }
  431. csa->fname = fname;
  432. csa->fp = NULL;
  433. csa->count = 0;
  434. csa->c = '\n';
  435. csa->field[0] = '\0';
  436. csa->empty = csa->nonint = 0;
  437. xprintf("Reading maximum flow problem data from `%s'...\n",
  438. fname);
  439. csa->fp = glp_open(fname, "r");
  440. if (csa->fp == NULL)
  441. { xprintf("Unable to open `%s' - %s\n", fname, get_err_msg());
  442. longjmp(csa->jump, 1);
  443. }
  444. /* read problem line */
  445. read_designator(csa);
  446. if (strcmp(csa->field, "p") != 0)
  447. error(csa, "problem line missing or invalid");
  448. read_field(csa);
  449. if (strcmp(csa->field, "max") != 0)
  450. error(csa, "wrong problem designator; `max' expected");
  451. read_field(csa);
  452. if (!(str2int(csa->field, &nv) == 0 && nv >= 2))
  453. error(csa, "number of nodes missing or invalid");
  454. read_field(csa);
  455. if (!(str2int(csa->field, &na) == 0 && na >= 0))
  456. error(csa, "number of arcs missing or invalid");
  457. xprintf("Flow network has %d node%s and %d arc%s\n",
  458. nv, nv == 1 ? "" : "s", na, na == 1 ? "" : "s");
  459. if (nv > 0) glp_add_vertices(G, nv);
  460. end_of_line(csa);
  461. /* read node descriptor lines */
  462. s = t = 0;
  463. for (;;)
  464. { read_designator(csa);
  465. if (strcmp(csa->field, "n") != 0) break;
  466. read_field(csa);
  467. if (str2int(csa->field, &i) != 0)
  468. error(csa, "node number missing or invalid");
  469. if (!(1 <= i && i <= nv))
  470. error(csa, "node number %d out of range", i);
  471. read_field(csa);
  472. if (strcmp(csa->field, "s") == 0)
  473. { if (s > 0)
  474. error(csa, "only one source node allowed");
  475. s = i;
  476. }
  477. else if (strcmp(csa->field, "t") == 0)
  478. { if (t > 0)
  479. error(csa, "only one sink node allowed");
  480. t = i;
  481. }
  482. else
  483. error(csa, "wrong node designator; `s' or `t' expected");
  484. if (s > 0 && s == t)
  485. error(csa, "source and sink nodes must be distinct");
  486. end_of_line(csa);
  487. }
  488. if (s == 0)
  489. error(csa, "source node descriptor missing\n");
  490. if (t == 0)
  491. error(csa, "sink node descriptor missing\n");
  492. if (_s != NULL) *_s = s;
  493. if (_t != NULL) *_t = t;
  494. /* read arc descriptor lines */
  495. for (k = 1; k <= na; k++)
  496. { if (k > 1) read_designator(csa);
  497. if (strcmp(csa->field, "a") != 0)
  498. error(csa, "wrong line designator; `a' expected");
  499. read_field(csa);
  500. if (str2int(csa->field, &i) != 0)
  501. error(csa, "starting node number missing or invalid");
  502. if (!(1 <= i && i <= nv))
  503. error(csa, "starting node number %d out of range", i);
  504. read_field(csa);
  505. if (str2int(csa->field, &j) != 0)
  506. error(csa, "ending node number missing or invalid");
  507. if (!(1 <= j && j <= nv))
  508. error(csa, "ending node number %d out of range", j);
  509. read_field(csa);
  510. if (!(str2num(csa->field, &cap) == 0 && cap >= 0.0))
  511. error(csa, "arc capacity missing or invalid");
  512. check_int(csa, cap);
  513. a = glp_add_arc(G, i, j);
  514. if (a_cap >= 0)
  515. memcpy((char *)a->data + a_cap, &cap, sizeof(double));
  516. end_of_line(csa);
  517. }
  518. xprintf("%d lines were read\n", csa->count);
  519. done: if (ret) glp_erase_graph(G, G->v_size, G->a_size);
  520. if (csa->fp != NULL) glp_close(csa->fp);
  521. return ret;
  522. }
  523. /***********************************************************************
  524. * NAME
  525. *
  526. * glp_write_maxflow - write maximum flow problem data in DIMACS format
  527. *
  528. * SYNOPSIS
  529. *
  530. * int glp_write_maxflow(glp_graph *G, int s, int t, int a_cap,
  531. * const char *fname);
  532. *
  533. * DESCRIPTION
  534. *
  535. * The routine glp_write_maxflow writes maximum flow problem data in
  536. * DIMACS format to a text file.
  537. *
  538. * RETURNS
  539. *
  540. * If the operation was successful, the routine returns zero. Otherwise
  541. * it prints an error message and returns non-zero. */
  542. int glp_write_maxflow(glp_graph *G, int s, int t, int a_cap,
  543. const char *fname)
  544. { glp_file *fp;
  545. glp_vertex *v;
  546. glp_arc *a;
  547. int i, count = 0, ret;
  548. double cap;
  549. if (!(1 <= s && s <= G->nv))
  550. xerror("glp_write_maxflow: s = %d; source node number out of r"
  551. "ange\n", s);
  552. if (!(1 <= t && t <= G->nv))
  553. xerror("glp_write_maxflow: t = %d: sink node number out of ran"
  554. "ge\n", t);
  555. if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
  556. xerror("glp_write_mincost: a_cap = %d; invalid offset\n",
  557. a_cap);
  558. xprintf("Writing maximum flow problem data to `%s'...\n",
  559. fname);
  560. fp = glp_open(fname, "w");
  561. if (fp == NULL)
  562. { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg());
  563. ret = 1;
  564. goto done;
  565. }
  566. xfprintf(fp, "c %s\n",
  567. G->name == NULL ? "unknown" : G->name), count++;
  568. xfprintf(fp, "p max %d %d\n", G->nv, G->na), count++;
  569. xfprintf(fp, "n %d s\n", s), count++;
  570. xfprintf(fp, "n %d t\n", t), count++;
  571. for (i = 1; i <= G->nv; i++)
  572. { v = G->v[i];
  573. for (a = v->out; a != NULL; a = a->t_next)
  574. { if (a_cap >= 0)
  575. memcpy(&cap, (char *)a->data + a_cap, sizeof(double));
  576. else
  577. cap = 1.0;
  578. xfprintf(fp, "a %d %d %.*g\n",
  579. a->tail->i, a->head->i, DBL_DIG, cap), count++;
  580. }
  581. }
  582. xfprintf(fp, "c eof\n"), count++;
  583. #if 0 /* FIXME */
  584. xfflush(fp);
  585. #endif
  586. if (glp_ioerr(fp))
  587. { xprintf("Write error on `%s' - %s\n", fname, get_err_msg());
  588. ret = 1;
  589. goto done;
  590. }
  591. xprintf("%d lines were written\n", count);
  592. ret = 0;
  593. done: if (fp != NULL) glp_close(fp);
  594. return ret;
  595. }
  596. /***********************************************************************
  597. * NAME
  598. *
  599. * glp_read_asnprob - read assignment problem data in DIMACS format
  600. *
  601. * SYNOPSIS
  602. *
  603. * int glp_read_asnprob(glp_graph *G, int v_set, int a_cost,
  604. * const char *fname);
  605. *
  606. * DESCRIPTION
  607. *
  608. * The routine glp_read_asnprob reads assignment problem data in DIMACS
  609. * format from a text file.
  610. *
  611. * RETURNS
  612. *
  613. * If the operation was successful, the routine returns zero. Otherwise
  614. * it prints an error message and returns non-zero. */
  615. int glp_read_asnprob(glp_graph *G, int v_set, int a_cost, const char
  616. *fname)
  617. { struct csa _csa, *csa = &_csa;
  618. glp_vertex *v;
  619. glp_arc *a;
  620. int nv, na, n1, i, j, k, ret = 0;
  621. double cost;
  622. char *flag = NULL;
  623. if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int))
  624. xerror("glp_read_asnprob: v_set = %d; invalid offset\n",
  625. v_set);
  626. if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
  627. xerror("glp_read_asnprob: a_cost = %d; invalid offset\n",
  628. a_cost);
  629. glp_erase_graph(G, G->v_size, G->a_size);
  630. if (setjmp(csa->jump))
  631. { ret = 1;
  632. goto done;
  633. }
  634. csa->fname = fname;
  635. csa->fp = NULL;
  636. csa->count = 0;
  637. csa->c = '\n';
  638. csa->field[0] = '\0';
  639. csa->empty = csa->nonint = 0;
  640. xprintf("Reading assignment problem data from `%s'...\n", fname);
  641. csa->fp = glp_open(fname, "r");
  642. if (csa->fp == NULL)
  643. { xprintf("Unable to open `%s' - %s\n", fname, get_err_msg());
  644. longjmp(csa->jump, 1);
  645. }
  646. /* read problem line */
  647. read_designator(csa);
  648. if (strcmp(csa->field, "p") != 0)
  649. error(csa, "problem line missing or invalid");
  650. read_field(csa);
  651. if (strcmp(csa->field, "asn") != 0)
  652. error(csa, "wrong problem designator; `asn' expected");
  653. read_field(csa);
  654. if (!(str2int(csa->field, &nv) == 0 && nv >= 0))
  655. error(csa, "number of nodes missing or invalid");
  656. read_field(csa);
  657. if (!(str2int(csa->field, &na) == 0 && na >= 0))
  658. error(csa, "number of arcs missing or invalid");
  659. if (nv > 0) glp_add_vertices(G, nv);
  660. end_of_line(csa);
  661. /* read node descriptor lines */
  662. flag = xcalloc(1+nv, sizeof(char));
  663. memset(&flag[1], 0, nv * sizeof(char));
  664. n1 = 0;
  665. for (;;)
  666. { read_designator(csa);
  667. if (strcmp(csa->field, "n") != 0) break;
  668. read_field(csa);
  669. if (str2int(csa->field, &i) != 0)
  670. error(csa, "node number missing or invalid");
  671. if (!(1 <= i && i <= nv))
  672. error(csa, "node number %d out of range", i);
  673. if (flag[i])
  674. error(csa, "duplicate descriptor of node %d", i);
  675. flag[i] = 1, n1++;
  676. end_of_line(csa);
  677. }
  678. xprintf(
  679. "Assignment problem has %d + %d = %d node%s and %d arc%s\n",
  680. n1, nv - n1, nv, nv == 1 ? "" : "s", na, na == 1 ? "" : "s");
  681. if (v_set >= 0)
  682. { for (i = 1; i <= nv; i++)
  683. { v = G->v[i];
  684. k = (flag[i] ? 0 : 1);
  685. memcpy((char *)v->data + v_set, &k, sizeof(int));
  686. }
  687. }
  688. /* read arc descriptor lines */
  689. for (k = 1; k <= na; k++)
  690. { if (k > 1) read_designator(csa);
  691. if (strcmp(csa->field, "a") != 0)
  692. error(csa, "wrong line designator; `a' expected");
  693. read_field(csa);
  694. if (str2int(csa->field, &i) != 0)
  695. error(csa, "starting node number missing or invalid");
  696. if (!(1 <= i && i <= nv))
  697. error(csa, "starting node number %d out of range", i);
  698. if (!flag[i])
  699. error(csa, "node %d cannot be a starting node", i);
  700. read_field(csa);
  701. if (str2int(csa->field, &j) != 0)
  702. error(csa, "ending node number missing or invalid");
  703. if (!(1 <= j && j <= nv))
  704. error(csa, "ending node number %d out of range", j);
  705. if (flag[j])
  706. error(csa, "node %d cannot be an ending node", j);
  707. read_field(csa);
  708. if (str2num(csa->field, &cost) != 0)
  709. error(csa, "arc cost missing or invalid");
  710. check_int(csa, cost);
  711. a = glp_add_arc(G, i, j);
  712. if (a_cost >= 0)
  713. memcpy((char *)a->data + a_cost, &cost, sizeof(double));
  714. end_of_line(csa);
  715. }
  716. xprintf("%d lines were read\n", csa->count);
  717. done: if (ret) glp_erase_graph(G, G->v_size, G->a_size);
  718. if (csa->fp != NULL) glp_close(csa->fp);
  719. if (flag != NULL) xfree(flag);
  720. return ret;
  721. }
  722. /***********************************************************************
  723. * NAME
  724. *
  725. * glp_write_asnprob - write assignment problem data in DIMACS format
  726. *
  727. * SYNOPSIS
  728. *
  729. * int glp_write_asnprob(glp_graph *G, int v_set, int a_cost,
  730. * const char *fname);
  731. *
  732. * DESCRIPTION
  733. *
  734. * The routine glp_write_asnprob writes assignment problem data in
  735. * DIMACS format to a text file.
  736. *
  737. * RETURNS
  738. *
  739. * If the operation was successful, the routine returns zero. Otherwise
  740. * it prints an error message and returns non-zero. */
  741. int glp_write_asnprob(glp_graph *G, int v_set, int a_cost, const char
  742. *fname)
  743. { glp_file *fp;
  744. glp_vertex *v;
  745. glp_arc *a;
  746. int i, k, count = 0, ret;
  747. double cost;
  748. if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int))
  749. xerror("glp_write_asnprob: v_set = %d; invalid offset\n",
  750. v_set);
  751. if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
  752. xerror("glp_write_asnprob: a_cost = %d; invalid offset\n",
  753. a_cost);
  754. xprintf("Writing assignment problem data to `%s'...\n", fname);
  755. fp = glp_open(fname, "w");
  756. if (fp == NULL)
  757. { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg());
  758. ret = 1;
  759. goto done;
  760. }
  761. xfprintf(fp, "c %s\n",
  762. G->name == NULL ? "unknown" : G->name), count++;
  763. xfprintf(fp, "p asn %d %d\n", G->nv, G->na), count++;
  764. for (i = 1; i <= G->nv; i++)
  765. { v = G->v[i];
  766. if (v_set >= 0)
  767. memcpy(&k, (char *)v->data + v_set, sizeof(int));
  768. else
  769. k = (v->out != NULL ? 0 : 1);
  770. if (k == 0)
  771. xfprintf(fp, "n %d\n", i), count++;
  772. }
  773. for (i = 1; i <= G->nv; i++)
  774. { v = G->v[i];
  775. for (a = v->out; a != NULL; a = a->t_next)
  776. { if (a_cost >= 0)
  777. memcpy(&cost, (char *)a->data + a_cost, sizeof(double));
  778. else
  779. cost = 1.0;
  780. xfprintf(fp, "a %d %d %.*g\n",
  781. a->tail->i, a->head->i, DBL_DIG, cost), count++;
  782. }
  783. }
  784. xfprintf(fp, "c eof\n"), count++;
  785. #if 0 /* FIXME */
  786. xfflush(fp);
  787. #endif
  788. if (glp_ioerr(fp))
  789. { xprintf("Write error on `%s' - %s\n", fname, get_err_msg());
  790. ret = 1;
  791. goto done;
  792. }
  793. xprintf("%d lines were written\n", count);
  794. ret = 0;
  795. done: if (fp != NULL) glp_close(fp);
  796. return ret;
  797. }
  798. /***********************************************************************
  799. * NAME
  800. *
  801. * glp_read_ccdata - read graph in DIMACS clique/coloring format
  802. *
  803. * SYNOPSIS
  804. *
  805. * int glp_read_ccdata(glp_graph *G, int v_wgt, const char *fname);
  806. *
  807. * DESCRIPTION
  808. *
  809. * The routine glp_read_ccdata reads an (undirected) graph in DIMACS
  810. * clique/coloring format from a text file.
  811. *
  812. * RETURNS
  813. *
  814. * If the operation was successful, the routine returns zero. Otherwise
  815. * it prints an error message and returns non-zero. */
  816. int glp_read_ccdata(glp_graph *G, int v_wgt, const char *fname)
  817. { struct csa _csa, *csa = &_csa;
  818. glp_vertex *v;
  819. int i, j, k, nv, ne, ret = 0;
  820. double w;
  821. char *flag = NULL;
  822. if (v_wgt >= 0 && v_wgt > G->v_size - (int)sizeof(double))
  823. xerror("glp_read_ccdata: v_wgt = %d; invalid offset\n",
  824. v_wgt);
  825. glp_erase_graph(G, G->v_size, G->a_size);
  826. if (setjmp(csa->jump))
  827. { ret = 1;
  828. goto done;
  829. }
  830. csa->fname = fname;
  831. csa->fp = NULL;
  832. csa->count = 0;
  833. csa->c = '\n';
  834. csa->field[0] = '\0';
  835. csa->empty = csa->nonint = 0;
  836. xprintf("Reading graph from `%s'...\n", fname);
  837. csa->fp = glp_open(fname, "r");
  838. if (csa->fp == NULL)
  839. { xprintf("Unable to open `%s' - %s\n", fname, get_err_msg());
  840. longjmp(csa->jump, 1);
  841. }
  842. /* read problem line */
  843. read_designator(csa);
  844. if (strcmp(csa->field, "p") != 0)
  845. error(csa, "problem line missing or invalid");
  846. read_field(csa);
  847. if (strcmp(csa->field, "edge") != 0)
  848. error(csa, "wrong problem designator; `edge' expected");
  849. read_field(csa);
  850. if (!(str2int(csa->field, &nv) == 0 && nv >= 0))
  851. error(csa, "number of vertices missing or invalid");
  852. read_field(csa);
  853. if (!(str2int(csa->field, &ne) == 0 && ne >= 0))
  854. error(csa, "number of edges missing or invalid");
  855. xprintf("Graph has %d vert%s and %d edge%s\n",
  856. nv, nv == 1 ? "ex" : "ices", ne, ne == 1 ? "" : "s");
  857. if (nv > 0) glp_add_vertices(G, nv);
  858. end_of_line(csa);
  859. /* read node descriptor lines */
  860. flag = xcalloc(1+nv, sizeof(char));
  861. memset(&flag[1], 0, nv * sizeof(char));
  862. if (v_wgt >= 0)
  863. { w = 1.0;
  864. for (i = 1; i <= nv; i++)
  865. { v = G->v[i];
  866. memcpy((char *)v->data + v_wgt, &w, sizeof(double));
  867. }
  868. }
  869. for (;;)
  870. { read_designator(csa);
  871. if (strcmp(csa->field, "n") != 0) break;
  872. read_field(csa);
  873. if (str2int(csa->field, &i) != 0)
  874. error(csa, "vertex number missing or invalid");
  875. if (!(1 <= i && i <= nv))
  876. error(csa, "vertex number %d out of range", i);
  877. if (flag[i])
  878. error(csa, "duplicate descriptor of vertex %d", i);
  879. read_field(csa);
  880. if (str2num(csa->field, &w) != 0)
  881. error(csa, "vertex weight missing or invalid");
  882. check_int(csa, w);
  883. if (v_wgt >= 0)
  884. { v = G->v[i];
  885. memcpy((char *)v->data + v_wgt, &w, sizeof(double));
  886. }
  887. flag[i] = 1;
  888. end_of_line(csa);
  889. }
  890. xfree(flag), flag = NULL;
  891. /* read edge descriptor lines */
  892. for (k = 1; k <= ne; k++)
  893. { if (k > 1) read_designator(csa);
  894. if (strcmp(csa->field, "e") != 0)
  895. error(csa, "wrong line designator; `e' expected");
  896. read_field(csa);
  897. if (str2int(csa->field, &i) != 0)
  898. error(csa, "first vertex number missing or invalid");
  899. if (!(1 <= i && i <= nv))
  900. error(csa, "first vertex number %d out of range", i);
  901. read_field(csa);
  902. if (str2int(csa->field, &j) != 0)
  903. error(csa, "second vertex number missing or invalid");
  904. if (!(1 <= j && j <= nv))
  905. error(csa, "second vertex number %d out of range", j);
  906. glp_add_arc(G, i, j);
  907. end_of_line(csa);
  908. }
  909. xprintf("%d lines were read\n", csa->count);
  910. done: if (ret) glp_erase_graph(G, G->v_size, G->a_size);
  911. if (csa->fp != NULL) glp_close(csa->fp);
  912. if (flag != NULL) xfree(flag);
  913. return ret;
  914. }
  915. /***********************************************************************
  916. * NAME
  917. *
  918. * glp_write_ccdata - write graph in DIMACS clique/coloring format
  919. *
  920. * SYNOPSIS
  921. *
  922. * int glp_write_ccdata(glp_graph *G, int v_wgt, const char *fname);
  923. *
  924. * DESCRIPTION
  925. *
  926. * The routine glp_write_ccdata writes the specified graph in DIMACS
  927. * clique/coloring format to a text file.
  928. *
  929. * RETURNS
  930. *
  931. * If the operation was successful, the routine returns zero. Otherwise
  932. * it prints an error message and returns non-zero. */
  933. int glp_write_ccdata(glp_graph *G, int v_wgt, const char *fname)
  934. { glp_file *fp;
  935. glp_vertex *v;
  936. glp_arc *e;
  937. int i, count = 0, ret;
  938. double w;
  939. if (v_wgt >= 0 && v_wgt > G->v_size - (int)sizeof(double))
  940. xerror("glp_write_ccdata: v_wgt = %d; invalid offset\n",
  941. v_wgt);
  942. xprintf("Writing graph to `%s'\n", fname);
  943. fp = glp_open(fname, "w");
  944. if (fp == NULL)
  945. { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg());
  946. ret = 1;
  947. goto done;
  948. }
  949. xfprintf(fp, "c %s\n",
  950. G->name == NULL ? "unknown" : G->name), count++;
  951. xfprintf(fp, "p edge %d %d\n", G->nv, G->na), count++;
  952. if (v_wgt >= 0)
  953. { for (i = 1; i <= G->nv; i++)
  954. { v = G->v[i];
  955. memcpy(&w, (char *)v->data + v_wgt, sizeof(double));
  956. if (w != 1.0)
  957. xfprintf(fp, "n %d %.*g\n", i, DBL_DIG, w), count++;
  958. }
  959. }
  960. for (i = 1; i <= G->nv; i++)
  961. { v = G->v[i];
  962. for (e = v->out; e != NULL; e = e->t_next)
  963. xfprintf(fp, "e %d %d\n", e->tail->i, e->head->i), count++;
  964. }
  965. xfprintf(fp, "c eof\n"), count++;
  966. #if 0 /* FIXME */
  967. xfflush(fp);
  968. #endif
  969. if (glp_ioerr(fp))
  970. { xprintf("Write error on `%s' - %s\n", fname, get_err_msg());
  971. ret = 1;
  972. goto done;
  973. }
  974. xprintf("%d lines were written\n", count);
  975. ret = 0;
  976. done: if (fp != NULL) glp_close(fp);
  977. return ret;
  978. }
  979. /***********************************************************************
  980. * NAME
  981. *
  982. * glp_read_prob - read problem data in GLPK format
  983. *
  984. * SYNOPSIS
  985. *
  986. * int glp_read_prob(glp_prob *P, int flags, const char *fname);
  987. *
  988. * The routine glp_read_prob reads problem data in GLPK LP/MIP format
  989. * from a text file.
  990. *
  991. * RETURNS
  992. *
  993. * If the operation was successful, the routine returns zero. Otherwise
  994. * it prints an error message and returns non-zero. */
  995. int glp_read_prob(glp_prob *P, int flags, const char *fname)
  996. { struct csa _csa, *csa = &_csa;
  997. int mip, m, n, nnz, ne, i, j, k, type, kind, ret, *ln = NULL,
  998. *ia = NULL, *ja = NULL;
  999. double lb, ub, temp, *ar = NULL;
  1000. char *rf = NULL, *cf = NULL;
  1001. if (P == NULL || P->magic != GLP_PROB_MAGIC)
  1002. xerror("glp_read_prob: P = %p; invalid problem object\n",
  1003. P);
  1004. if (flags != 0)
  1005. xerror("glp_read_prob: flags = %d; invalid parameter\n",
  1006. flags);
  1007. if (fname == NULL)
  1008. xerror("glp_read_prob: fname = %d; invalid parameter\n",
  1009. fname);
  1010. glp_erase_prob(P);
  1011. if (setjmp(csa->jump))
  1012. { ret = 1;
  1013. goto done;
  1014. }
  1015. csa->fname = fname;
  1016. csa->fp = NULL;
  1017. csa->count = 0;
  1018. csa->c = '\n';
  1019. csa->field[0] = '\0';
  1020. csa->empty = csa->nonint = 0;
  1021. xprintf("Reading problem data from `%s'...\n", fname);
  1022. csa->fp = glp_open(fname, "r");
  1023. if (csa->fp == NULL)
  1024. { xprintf("Unable to open `%s' - %s\n", fname, get_err_msg());
  1025. longjmp(csa->jump, 1);
  1026. }
  1027. /* read problem line */
  1028. read_designator(csa);
  1029. if (strcmp(csa->field, "p") != 0)
  1030. error(csa, "problem line missing or invalid");
  1031. read_field(csa);
  1032. if (strcmp(csa->field, "lp") == 0)
  1033. mip = 0;
  1034. else if (strcmp(csa->field, "mip") == 0)
  1035. mip = 1;
  1036. else
  1037. error(csa, "wrong problem designator; `lp' or `mip' expected\n"
  1038. );
  1039. read_field(csa);
  1040. if (strcmp(csa->field, "min") == 0)
  1041. glp_set_obj_dir(P, GLP_MIN);
  1042. else if (strcmp(csa->field, "max") == 0)
  1043. glp_set_obj_dir(P, GLP_MAX);
  1044. else
  1045. error(csa, "objective sense missing or invalid");
  1046. read_field(csa);
  1047. if (!(str2int(csa->field, &m) == 0 && m >= 0))
  1048. error(csa, "number of rows missing or invalid");
  1049. read_field(csa);
  1050. if (!(str2int(csa->field, &n) == 0 && n >= 0))
  1051. error(csa, "number of columns missing or invalid");
  1052. read_field(csa);
  1053. if (!(str2int(csa->field, &nnz) == 0 && nnz >= 0))
  1054. error(csa, "number of constraint coefficients missing or inval"
  1055. "id");
  1056. if (m > 0)
  1057. { glp_add_rows(P, m);
  1058. for (i = 1; i <= m; i++)
  1059. glp_set_row_bnds(P, i, GLP_FX, 0.0, 0.0);
  1060. }
  1061. if (n > 0)
  1062. { glp_add_cols(P, n);
  1063. for (j = 1; j <= n; j++)
  1064. { if (!mip)
  1065. glp_set_col_bnds(P, j, GLP_LO, 0.0, 0.0);
  1066. else
  1067. glp_set_col_kind(P, j, GLP_BV);
  1068. }
  1069. }
  1070. end_of_line(csa);
  1071. /* allocate working arrays */
  1072. rf = xcalloc(1+m, sizeof(char));
  1073. memset(rf, 0, 1+m);
  1074. cf = xcalloc(1+n, sizeof(char));
  1075. memset(cf, 0, 1+n);
  1076. ln = xcalloc(1+nnz, sizeof(int));
  1077. ia = xcalloc(1+nnz, sizeof(int));
  1078. ja = xcalloc(1+nnz, sizeof(int));
  1079. ar = xcalloc(1+nnz, sizeof(double));
  1080. /* read descriptor lines */
  1081. ne = 0;
  1082. for (;;)
  1083. { read_designator(csa);
  1084. if (strcmp(csa->field, "i") == 0)
  1085. { /* row descriptor */
  1086. read_field(csa);
  1087. if (str2int(csa->field, &i) != 0)
  1088. error(csa, "row number missing or invalid");
  1089. if (!(1 <= i && i <= m))
  1090. error(csa, "row number out of range");
  1091. read_field(csa);
  1092. if (strcmp(csa->field, "f") == 0)
  1093. type = GLP_FR;
  1094. else if (strcmp(csa->field, "l") == 0)
  1095. type = GLP_LO;
  1096. else if (strcmp(csa->field, "u") == 0)
  1097. type = GLP_UP;
  1098. else if (strcmp(csa->field, "d") == 0)
  1099. type = GLP_DB;
  1100. else if (strcmp(csa->field, "s") == 0)
  1101. type = GLP_FX;
  1102. else
  1103. error(csa, "row type missing or invalid");
  1104. if (type == GLP_LO || type == GLP_DB || type == GLP_FX)
  1105. { read_field(csa);
  1106. if (str2num(csa->field, &lb) != 0)
  1107. error(csa, "row lower bound/fixed value missing or in"
  1108. "valid");
  1109. }
  1110. else
  1111. lb = 0.0;
  1112. if (type == GLP_UP || type == GLP_DB)
  1113. { read_field(csa);
  1114. if (str2num(csa->field, &ub) != 0)
  1115. error(csa, "row upper bound missing or invalid");
  1116. }
  1117. else
  1118. ub = 0.0;
  1119. if (rf[i] & 0x01)
  1120. error(csa, "duplicate row descriptor");
  1121. glp_set_row_bnds(P, i, type, lb, ub), rf[i] |= 0x01;
  1122. }
  1123. else if (strcmp(csa->field, "j") == 0)
  1124. { /* column descriptor */
  1125. read_field(csa);
  1126. if (str2int(csa->field, &j) != 0)
  1127. error(csa, "column number missing or invalid");
  1128. if (!(1 <= j && j <= n))
  1129. error(csa, "column number out of range");
  1130. if (!mip)
  1131. kind = GLP_CV;
  1132. else
  1133. { read_field(csa);
  1134. if (strcmp(csa->field, "c") == 0)
  1135. kind = GLP_CV;
  1136. else if (strcmp(csa->field, "i") == 0)
  1137. kind = GLP_IV;
  1138. else if (strcmp(csa->field, "b") == 0)
  1139. { kind = GLP_IV;
  1140. type = GLP_DB, lb = 0.0, ub = 1.0;
  1141. goto skip;
  1142. }
  1143. else
  1144. error(csa, "column kind missing or invalid");
  1145. }
  1146. read_field(csa);
  1147. if (strcmp(csa->field, "f") == 0)
  1148. type = GLP_FR;
  1149. else if (strcmp(csa->field, "l") == 0)
  1150. type = GLP_LO;
  1151. else if (strcmp(csa->field, "u") == 0)
  1152. type = GLP_UP;
  1153. else if (strcmp(csa->field, "d") == 0)
  1154. type = GLP_DB;
  1155. else if (strcmp(csa->field, "s") == 0)
  1156. type = GLP_FX;
  1157. else
  1158. error(csa, "column type missing or invalid");
  1159. if (type == GLP_LO || type == GLP_DB || type == GLP_FX)
  1160. { read_field(csa);
  1161. if (str2num(csa->field, &lb) != 0)
  1162. error(csa, "column lower bound/fixed value missing or"
  1163. " invalid");
  1164. }
  1165. else
  1166. lb = 0.0;
  1167. if (type == GLP_UP || type == GLP_DB)
  1168. { read_field(csa);
  1169. if (str2num(csa->field, &ub) != 0)
  1170. error(csa, "column upper bound missing or invalid");
  1171. }
  1172. else
  1173. ub = 0.0;
  1174. skip: if (cf[j] & 0x01)
  1175. error(csa, "duplicate column descriptor");
  1176. glp_set_col_kind(P, j, kind);
  1177. glp_set_col_bnds(P, j, type, lb, ub), cf[j] |= 0x01;
  1178. }
  1179. else if (strcmp(csa->field, "a") == 0)
  1180. { /* coefficient descriptor */
  1181. read_field(csa);
  1182. if (str2int(csa->field, &i) != 0)
  1183. error(csa, "row number missing or invalid");
  1184. if (!(0 <= i && i <= m))
  1185. error(csa, "row number out of range");
  1186. read_field(csa);
  1187. if (str2int(csa->field, &j) != 0)
  1188. error(csa, "column number missing or invalid");
  1189. if (!((i == 0 ? 0 : 1) <= j && j <= n))
  1190. error(csa, "column number out of range");
  1191. read_field(csa);
  1192. if (i == 0)
  1193. { if (str2num(csa->field, &temp) != 0)
  1194. error(csa, "objective %s missing or invalid",
  1195. j == 0 ? "constant term" : "coefficient");
  1196. if (cf[j] & 0x10)
  1197. error(csa, "duplicate objective %s",
  1198. j == 0 ? "constant term" : "coefficient");
  1199. glp_set_obj_coef(P, j, temp), cf[j] |= 0x10;
  1200. }
  1201. else
  1202. { if (str2num(csa->field, &temp) != 0)
  1203. error(csa, "constraint coefficient missing or invalid"
  1204. );
  1205. if (ne == nnz)
  1206. error(csa, "too many constraint coefficient descripto"
  1207. "rs");
  1208. ln[++ne] = csa->count;
  1209. ia[ne] = i, ja[ne] = j, ar[ne] = temp;
  1210. }
  1211. }
  1212. else if (strcmp(csa->field, "n") == 0)
  1213. { /* symbolic name descriptor */
  1214. read_field(csa);
  1215. if (strcmp(csa->field, "p") == 0)
  1216. { /* problem name */
  1217. read_field(csa);
  1218. if (P->name != NULL)
  1219. error(csa, "duplicate problem name");
  1220. glp_set_prob_name(P, csa->field);
  1221. }
  1222. else if (strcmp(csa->field, "z") == 0)
  1223. { /* objective name */
  1224. read_field(csa);
  1225. if (P->obj != NULL)
  1226. error(csa, "duplicate objective name");
  1227. glp_set_obj_name(P, csa->field);
  1228. }
  1229. else if (strcmp(csa->field, "i") == 0)
  1230. { /* row name */
  1231. read_field(csa);
  1232. if (str2int(csa->field, &i) != 0)
  1233. error(csa, "row number missing or invalid");
  1234. if (!(1 <= i && i <= m))
  1235. error(csa, "row number out of range");
  1236. read_field(csa);
  1237. if (P->row[i]->name != NULL)
  1238. error(csa, "duplicate row name");
  1239. glp_set_row_name(P, i, csa->field);
  1240. }
  1241. else if (strcmp(csa->field, "j") == 0)
  1242. { /* column name */
  1243. read_field(csa);
  1244. if (str2int(csa->field, &j) != 0)
  1245. error(csa, "column number missing or invalid");
  1246. if (!(1 <= j && j <= n))
  1247. error(csa, "column number out of range");
  1248. read_field(csa);
  1249. if (P->col[j]->name != NULL)
  1250. error(csa, "duplicate column name");
  1251. glp_set_col_name(P, j, csa->field);
  1252. }
  1253. else
  1254. error(csa, "object designator missing or invalid");
  1255. }
  1256. else if (strcmp(csa->field, "e") == 0)
  1257. break;
  1258. else
  1259. error(csa, "line designator missing or invalid");
  1260. end_of_line(csa);
  1261. }
  1262. if (ne < nnz)
  1263. error(csa, "too few constraint coefficient descriptors");
  1264. xassert(ne == nnz);
  1265. k = glp_check_dup(m, n, ne, ia, ja);
  1266. xassert(0 <= k && k <= nnz);
  1267. if (k > 0)
  1268. { csa->count = ln[k];
  1269. error(csa, "duplicate constraint coefficient");
  1270. }
  1271. glp_load_matrix(P, ne, ia, ja, ar);
  1272. /* print some statistics */
  1273. if (P->name != NULL)
  1274. xprintf("Problem: %s\n", P->name);
  1275. if (P->obj != NULL)
  1276. xprintf("Objective: %s\n", P->obj);
  1277. xprintf("%d row%s, %d column%s, %d non-zero%s\n",
  1278. m, m == 1 ? "" : "s", n, n == 1 ? "" : "s", nnz, nnz == 1 ?
  1279. "" : "s");
  1280. if (glp_get_num_int(P) > 0)
  1281. { int ni = glp_get_num_int(P);
  1282. int nb = glp_get_num_bin(P);
  1283. if (ni == 1)
  1284. { if (nb == 0)
  1285. xprintf("One variable is integer\n");
  1286. else
  1287. xprintf("One variable is binary\n");
  1288. }
  1289. else
  1290. { xprintf("%d integer variables, ", ni);
  1291. if (nb == 0)
  1292. xprintf("none");
  1293. else if (nb == 1)
  1294. xprintf("one");
  1295. else if (nb == ni)
  1296. xprintf("all");
  1297. else
  1298. xprintf("%d", nb);
  1299. xprintf(" of which %s binary\n", nb == 1 ? "is" : "are");
  1300. }
  1301. }
  1302. xprintf("%d lines were read\n", csa->count);
  1303. /* problem data has been successfully read */
  1304. glp_sort_matrix(P);
  1305. ret = 0;
  1306. done: if (csa->fp != NULL) glp_close(csa->fp);
  1307. if (rf != NULL) xfree(rf);
  1308. if (cf != NULL) xfree(cf);
  1309. if (ln != NULL) xfree(ln);
  1310. if (ia != NULL) xfree(ia);
  1311. if (ja != NULL) xfree(ja);
  1312. if (ar != NULL) xfree(ar);
  1313. if (ret) glp_erase_prob(P);
  1314. return ret;
  1315. }
  1316. /***********************************************************************
  1317. * NAME
  1318. *
  1319. * glp_write_prob - write problem data in GLPK format
  1320. *
  1321. * SYNOPSIS
  1322. *
  1323. * int glp_write_prob(glp_prob *P, int flags, const char *fname);
  1324. *
  1325. * The routine glp_write_prob writes problem data in GLPK LP/MIP format
  1326. * to a text file.
  1327. *
  1328. * RETURNS
  1329. *
  1330. * If the operation was successful, the routine returns zero. Otherwise
  1331. * it prints an error message and returns non-zero. */
  1332. int glp_write_prob(glp_prob *P, int flags, const char *fname)
  1333. { glp_file *fp;
  1334. GLPROW *row;
  1335. GLPCOL *col;
  1336. GLPAIJ *aij;
  1337. int mip, i, j, count, ret;
  1338. if (P == NULL || P->magic != GLP_PROB_MAGIC)
  1339. xerror("glp_write_prob: P = %p; invalid problem object\n",
  1340. P);
  1341. if (flags != 0)
  1342. xerror("glp_write_prob: flags = %d; invalid parameter\n",
  1343. flags);
  1344. if (fname == NULL)
  1345. xerror("glp_write_prob: fname = %d; invalid parameter\n",
  1346. fname);
  1347. xprintf("Writing problem data to `%s'...\n", fname);
  1348. fp = glp_open(fname, "w"), count = 0;
  1349. if (fp == NULL)
  1350. { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg());
  1351. ret = 1;
  1352. goto done;
  1353. }
  1354. /* write problem line */
  1355. mip = (glp_get_num_int(P) > 0);
  1356. xfprintf(fp, "p %s %s %d %d %d\n", !mip ? "lp" : "mip",
  1357. P->dir == GLP_MIN ? "min" : P->dir == GLP_MAX ? "max" : "???",
  1358. P->m, P->n, P->nnz), count++;
  1359. if (P->name != NULL)
  1360. xfprintf(fp, "n p %s\n", P->name), count++;
  1361. if (P->obj != NULL)
  1362. xfprintf(fp, "n z %s\n", P->obj), count++;
  1363. /* write row descriptors */
  1364. for (i = 1; i <= P->m; i++)
  1365. { row = P->row[i];
  1366. if (row->type == GLP_FX && row->lb == 0.0)
  1367. goto skip1;
  1368. xfprintf(fp, "i %d ", i), count++;
  1369. if (row->type == GLP_FR)
  1370. xfprintf(fp, "f\n");
  1371. else if (row->type == GLP_LO)
  1372. xfprintf(fp, "l %.*g\n", DBL_DIG, row->lb);
  1373. else if (row->type == GLP_UP)
  1374. xfprintf(fp, "u %.*g\n", DBL_DIG, row->ub);
  1375. else if (row->type == GLP_DB)
  1376. xfprintf(fp, "d %.*g %.*g\n", DBL_DIG, row->lb, DBL_DIG,
  1377. row->ub);
  1378. else if (row->type == GLP_FX)
  1379. xfprintf(fp, "s %.*g\n", DBL_DIG, row->lb);
  1380. else
  1381. xassert(row != row);
  1382. skip1: if (row->name != NULL)
  1383. xfprintf(fp, "n i %d %s\n", i, row->name), count++;
  1384. }
  1385. /* write column descriptors */
  1386. for (j = 1; j <= P->n; j++)
  1387. { col = P->col[j];
  1388. if (!mip && col->type == GLP_LO && col->lb == 0.0)
  1389. goto skip2;
  1390. if (mip && col->kind == GLP_IV && col->type == GLP_DB &&
  1391. col->lb == 0.0 && col->ub == 1.0)
  1392. goto skip2;
  1393. xfprintf(fp, "j %d ", j), count++;
  1394. if (mip)
  1395. { if (col->kind == GLP_CV)
  1396. xfprintf(fp, "c ");
  1397. else if (col->kind == GLP_IV)
  1398. xfprintf(fp, "i ");
  1399. else
  1400. xassert(col != col);
  1401. }
  1402. if (col->type == GLP_FR)
  1403. xfprintf(fp, "f\n");
  1404. else if (col->type == GLP_LO)
  1405. xfprintf(fp, "l %.*g\n", DBL_DIG, col->lb);
  1406. else if (col->type == GLP_UP)
  1407. xfprintf(fp, "u %.*g\n", DBL_DIG, col->ub);
  1408. else if (col->type == GLP_DB)
  1409. xfprintf(fp, "d %.*g %.*g\n", DBL_DIG, col->lb, DBL_DIG,
  1410. col->ub);
  1411. else if (col->type == GLP_FX)
  1412. xfprintf(fp, "s %.*g\n", DBL_DIG, col->lb);
  1413. else
  1414. xassert(col != col);
  1415. skip2: if (col->name != NULL)
  1416. xfprintf(fp, "n j %d %s\n", j, col->name), count++;
  1417. }
  1418. /* write objective coefficient descriptors */
  1419. if (P->c0 != 0.0)
  1420. xfprintf(fp, "a 0 0 %.*g\n", DBL_DIG, P->c0), count++;
  1421. for (j = 1; j <= P->n; j++)
  1422. { col = P->col[j];
  1423. if (col->coef != 0.0)
  1424. xfprintf(fp, "a 0 %d %.*g\n", j, DBL_DIG, col->coef),
  1425. count++;
  1426. }
  1427. /* write constraint coefficient descriptors */
  1428. for (i = 1; i <= P->m; i++)
  1429. { row = P->row[i];
  1430. for (aij = row->ptr; aij != NULL; aij = aij->r_next)
  1431. xfprintf(fp, "a %d %d %.*g\n", i, aij->col->j, DBL_DIG,
  1432. aij->val), count++;
  1433. }
  1434. /* write end line */
  1435. xfprintf(fp, "e o f\n"), count++;
  1436. #if 0 /* FIXME */
  1437. xfflush(fp);
  1438. #endif
  1439. if (glp_ioerr(fp))
  1440. { xprintf("Write error on `%s' - %s\n", fname, get_err_msg());
  1441. ret = 1;
  1442. goto done;
  1443. }
  1444. xprintf("%d lines were written\n", count);
  1445. ret = 0;
  1446. done: if (fp != NULL) glp_close(fp);
  1447. return ret;
  1448. }
  1449. /**********************************************************************/
  1450. int glp_read_cnfsat(glp_prob *P, const char *fname)
  1451. { /* read CNF-SAT problem data in DIMACS format */
  1452. struct csa _csa, *csa = &_csa;
  1453. int m, n, i, j, len, neg, rhs, ret = 0, *ind = NULL;
  1454. double *val = NULL;
  1455. char *map = NULL;
  1456. if (P == NULL || P->magic != GLP_PROB_MAGIC)
  1457. xerror("glp_read_cnfsat: P = %p; invalid problem object\n",
  1458. P);
  1459. if (fname == NULL)
  1460. xerror("glp_read_cnfsat: fname = %p; invalid parameter\n",
  1461. fname);
  1462. glp_erase_prob(P);
  1463. if (setjmp(csa->jump))
  1464. { ret = 1;
  1465. goto done;
  1466. }
  1467. csa->fname = fname;
  1468. csa->fp = NULL;
  1469. csa->count = 0;
  1470. csa->c = '\n';
  1471. csa->field[0] = '\0';
  1472. csa->empty = csa->nonint = 0;
  1473. xprintf("Reading CNF-SAT problem data from `%s'...\n", fname);
  1474. csa->fp = glp_open(fname, "r");
  1475. if (csa->fp == NULL)
  1476. { xprintf("Unable to open `%s' - %s\n", fname, get_err_msg());
  1477. longjmp(csa->jump, 1);
  1478. }
  1479. /* read problem line */
  1480. read_designator(csa);
  1481. if (strcmp(csa->field, "p") != 0)
  1482. error(csa, "problem line missing or invalid");
  1483. read_field(csa);
  1484. if (strcmp(csa->field, "cnf") != 0)
  1485. error(csa, "wrong problem designator; `cnf' expected\n");
  1486. read_field(csa);
  1487. if (!(str2int(csa->field, &n) == 0 && n >= 0))
  1488. error(csa, "number of variables missing or invalid\n");
  1489. read_field(csa);
  1490. if (!(str2int(csa->field, &m) == 0 && m >= 0))
  1491. error(csa, "number of clauses missing or invalid\n");
  1492. xprintf("Instance has %d variable%s and %d clause%s\n",
  1493. n, n == 1 ? "" : "s", m, m == 1 ? "" : "s");
  1494. end_of_line(csa);
  1495. if (m > 0)
  1496. glp_add_rows(P, m);
  1497. if (n > 0)
  1498. { glp_add_cols(P, n);
  1499. for (j = 1; j <= n; j++)
  1500. glp_set_col_kind(P, j, GLP_BV);
  1501. }
  1502. /* allocate working arrays */
  1503. ind = xcalloc(1+n, sizeof(int));
  1504. val = xcalloc(1+n, sizeof(double));
  1505. map = xcalloc(1+n, sizeof(char));
  1506. for (j = 1; j <= n; j++) map[j] = 0;
  1507. /* read clauses */
  1508. for (i = 1; i <= m; i++)
  1509. { /* read i-th clause */
  1510. len = 0, rhs = 1;
  1511. for (;;)
  1512. { /* skip white-space characters */
  1513. while (csa->c == ' ' || csa->c == '\n')
  1514. read_char(csa);
  1515. /* read term */
  1516. read_field(csa);
  1517. if (str2int(csa->field, &j) != 0)
  1518. error(csa, "variable number missing or invalid\n");
  1519. if (j > 0)
  1520. neg = 0;
  1521. else if (j < 0)
  1522. neg = 1, j = -j, rhs--;
  1523. else
  1524. break;
  1525. if (!(1 <= j && j <= n))
  1526. error(csa, "variable number out of range\n");
  1527. if (map[j])
  1528. error(csa, "duplicate variable number\n");
  1529. len++, ind[len] = j, val[len] = (neg ? -1.0 : +1.0);
  1530. map[j] = 1;
  1531. }
  1532. glp_set_row_bnds(P, i, GLP_LO, (double)rhs, 0.0);
  1533. glp_set_mat_row(P, i, len, ind, val);
  1534. while (len > 0) map[ind[len--]] = 0;
  1535. }
  1536. xprintf("%d lines were read\n", csa->count);
  1537. /* problem data has been successfully read */
  1538. glp_sort_matrix(P);
  1539. done: if (csa->fp != NULL) glp_close(csa->fp);
  1540. if (ind != NULL) xfree(ind);
  1541. if (val != NULL) xfree(val);
  1542. if (map != NULL) xfree(map);
  1543. if (ret) glp_erase_prob(P);
  1544. return ret;
  1545. }
  1546. /**********************************************************************/
  1547. int glp_check_cnfsat(glp_prob *P)
  1548. { /* check for CNF-SAT problem instance */
  1549. int m = P->m;
  1550. int n = P->n;
  1551. GLPROW *row;
  1552. GLPCOL *col;
  1553. GLPAIJ *aij;
  1554. int i, j, neg;
  1555. if (P == NULL || P->magic != GLP_PROB_MAGIC)
  1556. xerror("glp_check_cnfsat: P = %p; invalid problem object\n",
  1557. P);
  1558. /* check columns */
  1559. for (j = 1; j <= n; j++)
  1560. { col = P->col[j];
  1561. /* the variable should be binary */
  1562. if (!(col->kind == GLP_IV && col->type == GLP_DB &&
  1563. col->lb == 0.0 && col->ub == 1.0))
  1564. return 1;
  1565. }
  1566. /* objective function should be zero */
  1567. if (P->c0 != 0.0)
  1568. return 2;
  1569. for (j = 1; j <= n; j++)
  1570. { col = P->col[j];
  1571. if (col->coef != 0.0)
  1572. return 3;
  1573. }
  1574. /* check rows */
  1575. for (i = 1; i <= m; i++)
  1576. { row = P->row[i];
  1577. /* the row should be of ">=" type */
  1578. if (row->type != GLP_LO)
  1579. return 4;
  1580. /* check constraint coefficients */
  1581. neg = 0;
  1582. for (aij = row->ptr; aij != NULL; aij = aij->r_next)
  1583. { /* the constraint coefficient should be +1 or -1 */
  1584. if (aij->val == +1.0)
  1585. ;
  1586. else if (aij->val == -1.0)
  1587. neg++;
  1588. else
  1589. return 5;
  1590. }
  1591. /* the right-hand side should be (1 - neg), where neg is the
  1592. number of negative constraint coefficients in the row */
  1593. if (row->lb != (double)(1 - neg))
  1594. return 6;
  1595. }
  1596. /* congratulations; this is CNF-SAT */
  1597. return 0;
  1598. }
  1599. /**********************************************************************/
  1600. int glp_write_cnfsat(glp_prob *P, const char *fname)
  1601. { /* write CNF-SAT problem data in DIMACS format */
  1602. glp_file *fp = NULL;
  1603. GLPAIJ *aij;
  1604. int i, j, len, count = 0, ret;
  1605. char s[50];
  1606. if (P == NULL || P->magic != GLP_PROB_MAGIC)
  1607. xerror("glp_write_cnfsat: P = %p; invalid problem object\n",
  1608. P);
  1609. if (glp_check_cnfsat(P) != 0)
  1610. { xprintf("glp_write_cnfsat: problem object does not encode CNF-"
  1611. "SAT instance\n");
  1612. ret = 1;
  1613. goto done;
  1614. }
  1615. xprintf("Writing CNF-SAT problem data to `%s'...\n", fname);
  1616. fp = glp_open(fname, "w");
  1617. if (fp == NULL)
  1618. { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg());
  1619. ret = 1;
  1620. goto done;
  1621. }
  1622. xfprintf(fp, "c %s\n",
  1623. P->name == NULL ? "unknown" : P->name), count++;
  1624. xfprintf(fp, "p cnf %d %d\n", P->n, P->m), count++;
  1625. for (i = 1; i <= P->m; i++)
  1626. { len = 0;
  1627. for (aij = P->row[i]->ptr; aij != NULL; aij = aij->r_next)
  1628. { j = aij->col->j;
  1629. if (aij->val < 0.0) j = -j;
  1630. sprintf(s, "%d", j);
  1631. if (len > 0 && len + 1 + strlen(s) > 72)
  1632. xfprintf(fp, "\n"), count++, len = 0;
  1633. xfprintf(fp, "%s%s", len == 0 ? "" : " ", s);
  1634. if (len > 0) len++;
  1635. len += strlen(s);
  1636. }
  1637. if (len > 0 && len + 1 + 1 > 72)
  1638. xfprintf(fp, "\n"), count++, len = 0;
  1639. xfprintf(fp, "%s0\n", len == 0 ? "" : " "), count++;
  1640. }
  1641. xfprintf(fp, "c eof\n"), count++;
  1642. #if 0 /* FIXME */
  1643. xfflush(fp);
  1644. #endif
  1645. if (glp_ioerr(fp))
  1646. { xprintf("Write error on `%s' - %s\n", fname, get_err_msg());
  1647. ret = 1;
  1648. goto done;
  1649. }
  1650. xprintf("%d lines were written\n", count);
  1651. ret = 0;
  1652. done: if (fp != NULL) glp_close(fp);
  1653. return ret;
  1654. }
  1655. /* eof */