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.

1433 lines
46 KiB

  1. /* glpmps.c (MPS format routines) */
  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. /***********************************************************************
  28. * NAME
  29. *
  30. * glp_init_mpscp - initialize MPS format control parameters
  31. *
  32. * SYNOPSIS
  33. *
  34. * void glp_init_mpscp(glp_mpscp *parm);
  35. *
  36. * DESCRIPTION
  37. *
  38. * The routine glp_init_mpscp initializes control parameters, which are
  39. * used by the MPS input/output routines glp_read_mps and glp_write_mps,
  40. * with default values.
  41. *
  42. * Default values of the control parameters are stored in the glp_mpscp
  43. * structure, which the parameter parm points to. */
  44. void glp_init_mpscp(glp_mpscp *parm)
  45. { parm->blank = '\0';
  46. parm->obj_name = NULL;
  47. parm->tol_mps = 1e-12;
  48. return;
  49. }
  50. static void check_parm(const char *func, const glp_mpscp *parm)
  51. { /* check control parameters */
  52. if (!(0x00 <= parm->blank && parm->blank <= 0xFF) ||
  53. !(parm->blank == '\0' || isprint(parm->blank)))
  54. xerror("%s: blank = 0x%02X; invalid parameter\n",
  55. func, parm->blank);
  56. if (!(parm->obj_name == NULL || strlen(parm->obj_name) <= 255))
  57. xerror("%s: obj_name = \"%.12s...\"; parameter too long\n",
  58. func, parm->obj_name);
  59. if (!(0.0 <= parm->tol_mps && parm->tol_mps < 1.0))
  60. xerror("%s: tol_mps = %g; invalid parameter\n",
  61. func, parm->tol_mps);
  62. return;
  63. }
  64. /***********************************************************************
  65. * NAME
  66. *
  67. * glp_read_mps - read problem data in MPS format
  68. *
  69. * SYNOPSIS
  70. *
  71. * int glp_read_mps(glp_prob *P, int fmt, const glp_mpscp *parm,
  72. * const char *fname);
  73. *
  74. * DESCRIPTION
  75. *
  76. * The routine glp_read_mps reads problem data in MPS format from a
  77. * text file.
  78. *
  79. * The parameter fmt specifies the version of MPS format:
  80. *
  81. * GLP_MPS_DECK - fixed (ancient) MPS format;
  82. * GLP_MPS_FILE - free (modern) MPS format.
  83. *
  84. * The parameter parm is a pointer to the structure glp_mpscp, which
  85. * specifies control parameters used by the routine. If parm is NULL,
  86. * the routine uses default settings.
  87. *
  88. * The character string fname specifies a name of the text file to be
  89. * read.
  90. *
  91. * Note that before reading data the current content of the problem
  92. * object is completely erased with the routine glp_erase_prob.
  93. *
  94. * RETURNS
  95. *
  96. * If the operation was successful, the routine glp_read_mps returns
  97. * zero. Otherwise, it prints an error message and returns non-zero. */
  98. struct csa
  99. { /* common storage area */
  100. glp_prob *P;
  101. /* pointer to problem object */
  102. int deck;
  103. /* MPS format (0 - free, 1 - fixed) */
  104. const glp_mpscp *parm;
  105. /* pointer to control parameters */
  106. const char *fname;
  107. /* name of input MPS file */
  108. glp_file *fp;
  109. /* stream assigned to input MPS file */
  110. jmp_buf jump;
  111. /* label for go to in case of error */
  112. int recno;
  113. /* current record (card) number */
  114. int recpos;
  115. /* current record (card) position */
  116. int c;
  117. /* current character */
  118. int fldno;
  119. /* current field number */
  120. char field[255+1];
  121. /* current field content */
  122. int w80;
  123. /* warning 'record must not be longer than 80 chars' issued */
  124. int wef;
  125. /* warning 'extra fields detected beyond field 6' issued */
  126. int obj_row;
  127. /* objective row number */
  128. void *work1, *work2, *work3;
  129. /* working arrays */
  130. };
  131. static void error(struct csa *csa, const char *fmt, ...)
  132. { /* print error message and terminate processing */
  133. va_list arg;
  134. xprintf("%s:%d: ", csa->fname, csa->recno);
  135. va_start(arg, fmt);
  136. xvprintf(fmt, arg);
  137. va_end(arg);
  138. longjmp(csa->jump, 1);
  139. /* no return */
  140. }
  141. static void warning(struct csa *csa, const char *fmt, ...)
  142. { /* print warning message and continue processing */
  143. va_list arg;
  144. xprintf("%s:%d: warning: ", csa->fname, csa->recno);
  145. va_start(arg, fmt);
  146. xvprintf(fmt, arg);
  147. va_end(arg);
  148. return;
  149. }
  150. static void read_char(struct csa *csa)
  151. { /* read next character */
  152. int c;
  153. if (csa->c == '\n')
  154. csa->recno++, csa->recpos = 0;
  155. csa->recpos++;
  156. read: c = glp_getc(csa->fp);
  157. if (c < 0)
  158. { if (glp_ioerr(csa->fp))
  159. error(csa, "read error - %s\n", get_err_msg());
  160. else if (csa->c == '\n')
  161. error(csa, "unexpected end of file\n");
  162. else
  163. { warning(csa, "missing final end of line\n");
  164. c = '\n';
  165. }
  166. }
  167. else if (c == '\n')
  168. ;
  169. else if (csa->c == '\r')
  170. { c = '\r';
  171. goto badc;
  172. }
  173. else if (csa->deck && c == '\r')
  174. { csa->c = '\r';
  175. goto read;
  176. }
  177. else if (c == ' ')
  178. ;
  179. else if (isspace(c))
  180. { if (csa->deck)
  181. badc: error(csa, "in fixed MPS format white-space character 0x%02"
  182. "X is not allowed\n", c);
  183. c = ' ';
  184. }
  185. else if (iscntrl(c))
  186. error(csa, "invalid control character 0x%02X\n", c);
  187. if (csa->deck && csa->recpos == 81 && c != '\n' && csa->w80 < 1)
  188. { warning(csa, "in fixed MPS format record must not be longer th"
  189. "an 80 characters\n");
  190. csa->w80++;
  191. }
  192. csa->c = c;
  193. return;
  194. }
  195. static int indicator(struct csa *csa, int name)
  196. { /* skip comment records and read possible indicator record */
  197. int ret;
  198. /* reset current field number */
  199. csa->fldno = 0;
  200. loop: /* read the very first character of the next record */
  201. xassert(csa->c == '\n');
  202. read_char(csa);
  203. if (csa->c == ' ' || csa->c == '\n')
  204. { /* data record */
  205. ret = 0;
  206. }
  207. else if (csa->c == '*')
  208. { /* comment record */
  209. while (csa->c != '\n')
  210. read_char(csa);
  211. goto loop;
  212. }
  213. else
  214. { /* indicator record */
  215. int len = 0;
  216. while (csa->c != ' ' && csa->c != '\n' && len < 12)
  217. { csa->field[len++] = (char)csa->c;
  218. read_char(csa);
  219. }
  220. csa->field[len] = '\0';
  221. if (!(strcmp(csa->field, "NAME") == 0 ||
  222. strcmp(csa->field, "ROWS") == 0 ||
  223. strcmp(csa->field, "COLUMNS") == 0 ||
  224. strcmp(csa->field, "RHS") == 0 ||
  225. strcmp(csa->field, "RANGES") == 0 ||
  226. strcmp(csa->field, "BOUNDS") == 0 ||
  227. strcmp(csa->field, "ENDATA") == 0))
  228. error(csa, "invalid indicator record\n");
  229. if (!name)
  230. { while (csa->c != '\n')
  231. read_char(csa);
  232. }
  233. ret = 1;
  234. }
  235. return ret;
  236. }
  237. static void read_field(struct csa *csa)
  238. { /* read next field of the current data record */
  239. csa->fldno++;
  240. if (csa->deck)
  241. { /* fixed MPS format */
  242. int beg, end, pos;
  243. /* determine predefined field positions */
  244. if (csa->fldno == 1)
  245. beg = 2, end = 3;
  246. else if (csa->fldno == 2)
  247. beg = 5, end = 12;
  248. else if (csa->fldno == 3)
  249. beg = 15, end = 22;
  250. else if (csa->fldno == 4)
  251. beg = 25, end = 36;
  252. else if (csa->fldno == 5)
  253. beg = 40, end = 47;
  254. else if (csa->fldno == 6)
  255. beg = 50, end = 61;
  256. else
  257. xassert(csa != csa);
  258. /* skip blanks preceding the current field */
  259. if (csa->c != '\n')
  260. { pos = csa->recpos;
  261. while (csa->recpos < beg)
  262. { if (csa->c == ' ')
  263. ;
  264. else if (csa->c == '\n')
  265. break;
  266. else
  267. error(csa, "in fixed MPS format positions %d-%d must "
  268. "be blank\n", pos, beg-1);
  269. read_char(csa);
  270. }
  271. }
  272. /* skip possible comment beginning in the field 3 or 5 */
  273. if ((csa->fldno == 3 || csa->fldno == 5) && csa->c == '$')
  274. { while (csa->c != '\n')
  275. read_char(csa);
  276. }
  277. /* read the current field */
  278. for (pos = beg; pos <= end; pos++)
  279. { if (csa->c == '\n') break;
  280. csa->field[pos-beg] = (char)csa->c;
  281. read_char(csa);
  282. }
  283. csa->field[pos-beg] = '\0';
  284. strtrim(csa->field);
  285. /* skip blanks following the last field */
  286. if (csa->fldno == 6 && csa->c != '\n')
  287. { while (csa->recpos <= 72)
  288. { if (csa->c == ' ')
  289. ;
  290. else if (csa->c == '\n')
  291. break;
  292. else
  293. error(csa, "in fixed MPS format positions 62-72 must "
  294. "be blank\n");
  295. read_char(csa);
  296. }
  297. while (csa->c != '\n')
  298. read_char(csa);
  299. }
  300. }
  301. else
  302. { /* free MPS format */
  303. int len;
  304. /* skip blanks preceding the current field */
  305. while (csa->c == ' ')
  306. read_char(csa);
  307. /* skip possible comment */
  308. if (csa->c == '$')
  309. { while (csa->c != '\n')
  310. read_char(csa);
  311. }
  312. /* read the current field */
  313. len = 0;
  314. while (!(csa->c == ' ' || csa->c == '\n'))
  315. { if (len == 255)
  316. error(csa, "length of field %d exceeds 255 characters\n",
  317. csa->fldno++);
  318. csa->field[len++] = (char)csa->c;
  319. read_char(csa);
  320. }
  321. csa->field[len] = '\0';
  322. /* skip anything following the last field (any extra fields
  323. are considered to be comments) */
  324. if (csa->fldno == 6)
  325. { while (csa->c == ' ')
  326. read_char(csa);
  327. if (csa->c != '$' && csa->c != '\n' && csa->wef < 1)
  328. { warning(csa, "some extra field(s) detected beyond field "
  329. "6; field(s) ignored\n");
  330. csa->wef++;
  331. }
  332. while (csa->c != '\n')
  333. read_char(csa);
  334. }
  335. }
  336. return;
  337. }
  338. static void patch_name(struct csa *csa, char *name)
  339. { /* process embedded blanks in symbolic name */
  340. int blank = csa->parm->blank;
  341. if (blank == '\0')
  342. { /* remove emedded blanks */
  343. strspx(name);
  344. }
  345. else
  346. { /* replace embedded blanks by specified character */
  347. for (; *name != '\0'; name++)
  348. if (*name == ' ') *name = (char)blank;
  349. }
  350. return;
  351. }
  352. static double read_number(struct csa *csa)
  353. { /* read next field and convert it to floating-point number */
  354. double x;
  355. char *s;
  356. /* read next field */
  357. read_field(csa);
  358. xassert(csa->fldno == 4 || csa->fldno == 6);
  359. if (csa->field[0] == '\0')
  360. error(csa, "missing numeric value in field %d\n", csa->fldno);
  361. /* skip initial spaces of the field */
  362. for (s = csa->field; *s == ' '; s++);
  363. /* perform conversion */
  364. if (str2num(s, &x) != 0)
  365. error(csa, "cannot convert '%s' to floating-point number\n",
  366. s);
  367. return x;
  368. }
  369. static void skip_field(struct csa *csa)
  370. { /* read and skip next field (assumed to be blank) */
  371. read_field(csa);
  372. if (csa->field[0] != '\0')
  373. error(csa, "field %d must be blank\n", csa->fldno);
  374. return;
  375. }
  376. static void read_name(struct csa *csa)
  377. { /* read NAME indicator record */
  378. if (!(indicator(csa, 1) && strcmp(csa->field, "NAME") == 0))
  379. error(csa, "missing NAME indicator record\n");
  380. /* this indicator record looks like a data record; simulate that
  381. fields 1 and 2 were read */
  382. csa->fldno = 2;
  383. /* field 3: model name */
  384. read_field(csa), patch_name(csa, csa->field);
  385. if (csa->field[0] == '\0')
  386. warning(csa, "missing model name in field 3\n");
  387. else
  388. glp_set_prob_name(csa->P, csa->field);
  389. /* skip anything following field 3 */
  390. while (csa->c != '\n')
  391. read_char(csa);
  392. return;
  393. }
  394. static void read_rows(struct csa *csa)
  395. { /* read ROWS section */
  396. int i, type;
  397. loop: if (indicator(csa, 0)) goto done;
  398. /* field 1: row type */
  399. read_field(csa), strspx(csa->field);
  400. if (strcmp(csa->field, "N") == 0)
  401. type = GLP_FR;
  402. else if (strcmp(csa->field, "G") == 0)
  403. type = GLP_LO;
  404. else if (strcmp(csa->field, "L") == 0)
  405. type = GLP_UP;
  406. else if (strcmp(csa->field, "E") == 0)
  407. type = GLP_FX;
  408. else if (csa->field[0] == '\0')
  409. error(csa, "missing row type in field 1\n");
  410. else
  411. error(csa, "invalid row type in field 1\n");
  412. /* field 2: row name */
  413. read_field(csa), patch_name(csa, csa->field);
  414. if (csa->field[0] == '\0')
  415. error(csa, "missing row name in field 2\n");
  416. if (glp_find_row(csa->P, csa->field) != 0)
  417. error(csa, "row '%s' multiply specified\n", csa->field);
  418. i = glp_add_rows(csa->P, 1);
  419. glp_set_row_name(csa->P, i, csa->field);
  420. glp_set_row_bnds(csa->P, i, type, 0.0, 0.0);
  421. /* fields 3, 4, 5, and 6 must be blank */
  422. skip_field(csa);
  423. skip_field(csa);
  424. skip_field(csa);
  425. skip_field(csa);
  426. goto loop;
  427. done: return;
  428. }
  429. static void read_columns(struct csa *csa)
  430. { /* read COLUMNS section */
  431. int i, j, f, len, kind = GLP_CV, *ind;
  432. double aij, *val;
  433. char name[255+1], *flag;
  434. /* allocate working arrays */
  435. csa->work1 = ind = xcalloc(1+csa->P->m, sizeof(int));
  436. csa->work2 = val = xcalloc(1+csa->P->m, sizeof(double));
  437. csa->work3 = flag = xcalloc(1+csa->P->m, sizeof(char));
  438. memset(&flag[1], 0, csa->P->m);
  439. /* no current column exists */
  440. j = 0, len = 0;
  441. loop: if (indicator(csa, 0)) goto done;
  442. /* field 1 must be blank */
  443. if (csa->deck)
  444. { read_field(csa);
  445. if (csa->field[0] != '\0')
  446. error(csa, "field 1 must be blank\n");
  447. }
  448. else
  449. csa->fldno++;
  450. /* field 2: column or kind name */
  451. read_field(csa), patch_name(csa, csa->field);
  452. strcpy(name, csa->field);
  453. /* field 3: row name or keyword 'MARKER' */
  454. read_field(csa), patch_name(csa, csa->field);
  455. if (strcmp(csa->field, "'MARKER'") == 0)
  456. { /* process kind data record */
  457. /* field 4 must be blank */
  458. if (csa->deck)
  459. { read_field(csa);
  460. if (csa->field[0] != '\0')
  461. error(csa, "field 4 must be blank\n");
  462. }
  463. else
  464. csa->fldno++;
  465. /* field 5: keyword 'INTORG' or 'INTEND' */
  466. read_field(csa), patch_name(csa, csa->field);
  467. if (strcmp(csa->field, "'INTORG'") == 0)
  468. kind = GLP_IV;
  469. else if (strcmp(csa->field, "'INTEND'") == 0)
  470. kind = GLP_CV;
  471. else if (csa->field[0] == '\0')
  472. error(csa, "missing keyword in field 5\n");
  473. else
  474. error(csa, "invalid keyword in field 5\n");
  475. /* field 6 must be blank */
  476. skip_field(csa);
  477. goto loop;
  478. }
  479. /* process column name specified in field 2 */
  480. if (name[0] == '\0')
  481. { /* the same column as in previous data record */
  482. if (j == 0)
  483. error(csa, "missing column name in field 2\n");
  484. }
  485. else if (j != 0 && strcmp(name, csa->P->col[j]->name) == 0)
  486. { /* the same column as in previous data record */
  487. xassert(j != 0);
  488. }
  489. else
  490. { /* store the current column */
  491. if (j != 0)
  492. { glp_set_mat_col(csa->P, j, len, ind, val);
  493. while (len > 0) flag[ind[len--]] = 0;
  494. }
  495. /* create new column */
  496. if (glp_find_col(csa->P, name) != 0)
  497. error(csa, "column '%s' multiply specified\n", name);
  498. j = glp_add_cols(csa->P, 1);
  499. glp_set_col_name(csa->P, j, name);
  500. glp_set_col_kind(csa->P, j, kind);
  501. if (kind == GLP_CV)
  502. glp_set_col_bnds(csa->P, j, GLP_LO, 0.0, 0.0);
  503. else if (kind == GLP_IV)
  504. glp_set_col_bnds(csa->P, j, GLP_DB, 0.0, 1.0);
  505. else
  506. xassert(kind != kind);
  507. }
  508. /* process fields 3-4 and 5-6 */
  509. for (f = 3; f <= 5; f += 2)
  510. { /* field 3 or 5: row name */
  511. if (f == 3)
  512. { if (csa->field[0] == '\0')
  513. error(csa, "missing row name in field 3\n");
  514. }
  515. else
  516. { read_field(csa), patch_name(csa, csa->field);
  517. if (csa->field[0] == '\0')
  518. { /* if field 5 is blank, field 6 also must be blank */
  519. skip_field(csa);
  520. continue;
  521. }
  522. }
  523. i = glp_find_row(csa->P, csa->field);
  524. if (i == 0)
  525. error(csa, "row '%s' not found\n", csa->field);
  526. if (flag[i])
  527. error(csa, "duplicate coefficient in row '%s'\n",
  528. csa->field);
  529. /* field 4 or 6: coefficient value */
  530. aij = read_number(csa);
  531. if (fabs(aij) < csa->parm->tol_mps) aij = 0.0;
  532. len++, ind[len] = i, val[len] = aij, flag[i] = 1;
  533. }
  534. goto loop;
  535. done: /* store the last column */
  536. if (j != 0)
  537. glp_set_mat_col(csa->P, j, len, ind, val);
  538. /* free working arrays */
  539. xfree(ind);
  540. xfree(val);
  541. xfree(flag);
  542. csa->work1 = csa->work2 = csa->work3 = NULL;
  543. return;
  544. }
  545. static void read_rhs(struct csa *csa)
  546. { /* read RHS section */
  547. int i, f, v, type;
  548. double rhs;
  549. char name[255+1], *flag;
  550. /* allocate working array */
  551. csa->work3 = flag = xcalloc(1+csa->P->m, sizeof(char));
  552. memset(&flag[1], 0, csa->P->m);
  553. /* no current RHS vector exists */
  554. v = 0;
  555. loop: if (indicator(csa, 0)) goto done;
  556. /* field 1 must be blank */
  557. if (csa->deck)
  558. { read_field(csa);
  559. if (csa->field[0] != '\0')
  560. error(csa, "field 1 must be blank\n");
  561. }
  562. else
  563. csa->fldno++;
  564. /* field 2: RHS vector name */
  565. read_field(csa), patch_name(csa, csa->field);
  566. if (csa->field[0] == '\0')
  567. { /* the same RHS vector as in previous data record */
  568. if (v == 0)
  569. { warning(csa, "missing RHS vector name in field 2\n");
  570. goto blnk;
  571. }
  572. }
  573. else if (v != 0 && strcmp(csa->field, name) == 0)
  574. { /* the same RHS vector as in previous data record */
  575. xassert(v != 0);
  576. }
  577. else
  578. blnk: { /* new RHS vector */
  579. if (v != 0)
  580. error(csa, "multiple RHS vectors not supported\n");
  581. v++;
  582. strcpy(name, csa->field);
  583. }
  584. /* process fields 3-4 and 5-6 */
  585. for (f = 3; f <= 5; f += 2)
  586. { /* field 3 or 5: row name */
  587. read_field(csa), patch_name(csa, csa->field);
  588. if (csa->field[0] == '\0')
  589. { if (f == 3)
  590. error(csa, "missing row name in field 3\n");
  591. else
  592. { /* if field 5 is blank, field 6 also must be blank */
  593. skip_field(csa);
  594. continue;
  595. }
  596. }
  597. i = glp_find_row(csa->P, csa->field);
  598. if (i == 0)
  599. error(csa, "row '%s' not found\n", csa->field);
  600. if (flag[i])
  601. error(csa, "duplicate right-hand side for row '%s'\n",
  602. csa->field);
  603. /* field 4 or 6: right-hand side value */
  604. rhs = read_number(csa);
  605. if (fabs(rhs) < csa->parm->tol_mps) rhs = 0.0;
  606. type = csa->P->row[i]->type;
  607. if (type == GLP_FR)
  608. { if (i == csa->obj_row)
  609. glp_set_obj_coef(csa->P, 0, rhs);
  610. else if (rhs != 0.0)
  611. warning(csa, "non-zero right-hand side for free row '%s'"
  612. " ignored\n", csa->P->row[i]->name);
  613. }
  614. else
  615. glp_set_row_bnds(csa->P, i, type, rhs, rhs);
  616. flag[i] = 1;
  617. }
  618. goto loop;
  619. done: /* free working array */
  620. xfree(flag);
  621. csa->work3 = NULL;
  622. return;
  623. }
  624. static void read_ranges(struct csa *csa)
  625. { /* read RANGES section */
  626. int i, f, v, type;
  627. double rhs, rng;
  628. char name[255+1], *flag;
  629. /* allocate working array */
  630. csa->work3 = flag = xcalloc(1+csa->P->m, sizeof(char));
  631. memset(&flag[1], 0, csa->P->m);
  632. /* no current RANGES vector exists */
  633. v = 0;
  634. loop: if (indicator(csa, 0)) goto done;
  635. /* field 1 must be blank */
  636. if (csa->deck)
  637. { read_field(csa);
  638. if (csa->field[0] != '\0')
  639. error(csa, "field 1 must be blank\n");
  640. }
  641. else
  642. csa->fldno++;
  643. /* field 2: RANGES vector name */
  644. read_field(csa), patch_name(csa, csa->field);
  645. if (csa->field[0] == '\0')
  646. { /* the same RANGES vector as in previous data record */
  647. if (v == 0)
  648. { warning(csa, "missing RANGES vector name in field 2\n");
  649. goto blnk;
  650. }
  651. }
  652. else if (v != 0 && strcmp(csa->field, name) == 0)
  653. { /* the same RANGES vector as in previous data record */
  654. xassert(v != 0);
  655. }
  656. else
  657. blnk: { /* new RANGES vector */
  658. if (v != 0)
  659. error(csa, "multiple RANGES vectors not supported\n");
  660. v++;
  661. strcpy(name, csa->field);
  662. }
  663. /* process fields 3-4 and 5-6 */
  664. for (f = 3; f <= 5; f += 2)
  665. { /* field 3 or 5: row name */
  666. read_field(csa), patch_name(csa, csa->field);
  667. if (csa->field[0] == '\0')
  668. { if (f == 3)
  669. error(csa, "missing row name in field 3\n");
  670. else
  671. { /* if field 5 is blank, field 6 also must be blank */
  672. skip_field(csa);
  673. continue;
  674. }
  675. }
  676. i = glp_find_row(csa->P, csa->field);
  677. if (i == 0)
  678. error(csa, "row '%s' not found\n", csa->field);
  679. if (flag[i])
  680. error(csa, "duplicate range for row '%s'\n", csa->field);
  681. /* field 4 or 6: range value */
  682. rng = read_number(csa);
  683. if (fabs(rng) < csa->parm->tol_mps) rng = 0.0;
  684. type = csa->P->row[i]->type;
  685. if (type == GLP_FR)
  686. warning(csa, "range for free row '%s' ignored\n",
  687. csa->P->row[i]->name);
  688. else if (type == GLP_LO)
  689. { rhs = csa->P->row[i]->lb;
  690. glp_set_row_bnds(csa->P, i, rhs == 0.0 ? GLP_FX : GLP_DB,
  691. rhs, rhs + fabs(rng));
  692. }
  693. else if (type == GLP_UP)
  694. { rhs = csa->P->row[i]->ub;
  695. glp_set_row_bnds(csa->P, i, rhs == 0.0 ? GLP_FX : GLP_DB,
  696. rhs - fabs(rng), rhs);
  697. }
  698. else if (type == GLP_FX)
  699. { rhs = csa->P->row[i]->lb;
  700. if (rng > 0.0)
  701. glp_set_row_bnds(csa->P, i, GLP_DB, rhs, rhs + rng);
  702. else if (rng < 0.0)
  703. glp_set_row_bnds(csa->P, i, GLP_DB, rhs + rng, rhs);
  704. }
  705. else
  706. xassert(type != type);
  707. flag[i] = 1;
  708. }
  709. goto loop;
  710. done: /* free working array */
  711. xfree(flag);
  712. csa->work3 = NULL;
  713. return;
  714. }
  715. static void read_bounds(struct csa *csa)
  716. { /* read BOUNDS section */
  717. GLPCOL *col;
  718. int j, v, mask, data;
  719. double bnd, lb, ub;
  720. char type[2+1], name[255+1], *flag;
  721. /* allocate working array */
  722. csa->work3 = flag = xcalloc(1+csa->P->n, sizeof(char));
  723. memset(&flag[1], 0, csa->P->n);
  724. /* no current BOUNDS vector exists */
  725. v = 0;
  726. loop: if (indicator(csa, 0)) goto done;
  727. /* field 1: bound type */
  728. read_field(csa);
  729. if (strcmp(csa->field, "LO") == 0)
  730. mask = 0x01, data = 1;
  731. else if (strcmp(csa->field, "UP") == 0)
  732. mask = 0x10, data = 1;
  733. else if (strcmp(csa->field, "FX") == 0)
  734. mask = 0x11, data = 1;
  735. else if (strcmp(csa->field, "FR") == 0)
  736. mask = 0x11, data = 0;
  737. else if (strcmp(csa->field, "MI") == 0)
  738. mask = 0x01, data = 0;
  739. else if (strcmp(csa->field, "PL") == 0)
  740. mask = 0x10, data = 0;
  741. else if (strcmp(csa->field, "LI") == 0)
  742. mask = 0x01, data = 1;
  743. else if (strcmp(csa->field, "UI") == 0)
  744. mask = 0x10, data = 1;
  745. else if (strcmp(csa->field, "BV") == 0)
  746. mask = 0x11, data = 0;
  747. else if (csa->field[0] == '\0')
  748. error(csa, "missing bound type in field 1\n");
  749. else
  750. error(csa, "invalid bound type in field 1\n");
  751. strcpy(type, csa->field);
  752. /* field 2: BOUNDS vector name */
  753. read_field(csa), patch_name(csa, csa->field);
  754. if (csa->field[0] == '\0')
  755. { /* the same BOUNDS vector as in previous data record */
  756. if (v == 0)
  757. { warning(csa, "missing BOUNDS vector name in field 2\n");
  758. goto blnk;
  759. }
  760. }
  761. else if (v != 0 && strcmp(csa->field, name) == 0)
  762. { /* the same BOUNDS vector as in previous data record */
  763. xassert(v != 0);
  764. }
  765. else
  766. blnk: { /* new BOUNDS vector */
  767. if (v != 0)
  768. error(csa, "multiple BOUNDS vectors not supported\n");
  769. v++;
  770. strcpy(name, csa->field);
  771. }
  772. /* field 3: column name */
  773. read_field(csa), patch_name(csa, csa->field);
  774. if (csa->field[0] == '\0')
  775. error(csa, "missing column name in field 3\n");
  776. j = glp_find_col(csa->P, csa->field);
  777. if (j == 0)
  778. error(csa, "column '%s' not found\n", csa->field);
  779. if ((flag[j] & mask) == 0x01)
  780. error(csa, "duplicate lower bound for column '%s'\n",
  781. csa->field);
  782. if ((flag[j] & mask) == 0x10)
  783. error(csa, "duplicate upper bound for column '%s'\n",
  784. csa->field);
  785. xassert((flag[j] & mask) == 0x00);
  786. /* field 4: bound value */
  787. if (data)
  788. { bnd = read_number(csa);
  789. if (fabs(bnd) < csa->parm->tol_mps) bnd = 0.0;
  790. }
  791. else
  792. read_field(csa), bnd = 0.0;
  793. /* get current column bounds */
  794. col = csa->P->col[j];
  795. if (col->type == GLP_FR)
  796. lb = -DBL_MAX, ub = +DBL_MAX;
  797. else if (col->type == GLP_LO)
  798. lb = col->lb, ub = +DBL_MAX;
  799. else if (col->type == GLP_UP)
  800. lb = -DBL_MAX, ub = col->ub;
  801. else if (col->type == GLP_DB)
  802. lb = col->lb, ub = col->ub;
  803. else if (col->type == GLP_FX)
  804. lb = ub = col->lb;
  805. else
  806. xassert(col != col);
  807. /* change column bounds */
  808. if (strcmp(type, "LO") == 0)
  809. lb = bnd;
  810. else if (strcmp(type, "UP") == 0)
  811. ub = bnd;
  812. else if (strcmp(type, "FX") == 0)
  813. lb = ub = bnd;
  814. else if (strcmp(type, "FR") == 0)
  815. lb = -DBL_MAX, ub = +DBL_MAX;
  816. else if (strcmp(type, "MI") == 0)
  817. lb = -DBL_MAX;
  818. else if (strcmp(type, "PL") == 0)
  819. ub = +DBL_MAX;
  820. else if (strcmp(type, "LI") == 0)
  821. { glp_set_col_kind(csa->P, j, GLP_IV);
  822. lb = ceil(bnd);
  823. #if 1 /* 16/VII-2013 */
  824. /* if column upper bound has not been explicitly specified,
  825. take it as +inf */
  826. if (!(flag[j] & 0x10))
  827. ub = +DBL_MAX;
  828. #endif
  829. }
  830. else if (strcmp(type, "UI") == 0)
  831. { glp_set_col_kind(csa->P, j, GLP_IV);
  832. ub = floor(bnd);
  833. }
  834. else if (strcmp(type, "BV") == 0)
  835. { glp_set_col_kind(csa->P, j, GLP_IV);
  836. lb = 0.0, ub = 1.0;
  837. }
  838. else
  839. xassert(type != type);
  840. /* set new column bounds */
  841. if (lb == -DBL_MAX && ub == +DBL_MAX)
  842. glp_set_col_bnds(csa->P, j, GLP_FR, lb, ub);
  843. else if (ub == +DBL_MAX)
  844. glp_set_col_bnds(csa->P, j, GLP_LO, lb, ub);
  845. else if (lb == -DBL_MAX)
  846. glp_set_col_bnds(csa->P, j, GLP_UP, lb, ub);
  847. else if (lb != ub)
  848. glp_set_col_bnds(csa->P, j, GLP_DB, lb, ub);
  849. else
  850. glp_set_col_bnds(csa->P, j, GLP_FX, lb, ub);
  851. flag[j] |= (char)mask;
  852. /* fields 5 and 6 must be blank */
  853. skip_field(csa);
  854. skip_field(csa);
  855. goto loop;
  856. done: /* free working array */
  857. xfree(flag);
  858. csa->work3 = NULL;
  859. return;
  860. }
  861. int glp_read_mps(glp_prob *P, int fmt, const glp_mpscp *parm,
  862. const char *fname)
  863. { /* read problem data in MPS format */
  864. glp_mpscp _parm;
  865. struct csa _csa, *csa = &_csa;
  866. int ret;
  867. xprintf("Reading problem data from '%s'...\n", fname);
  868. if (!(fmt == GLP_MPS_DECK || fmt == GLP_MPS_FILE))
  869. xerror("glp_read_mps: fmt = %d; invalid parameter\n", fmt);
  870. if (parm == NULL)
  871. glp_init_mpscp(&_parm), parm = &_parm;
  872. /* check control parameters */
  873. check_parm("glp_read_mps", parm);
  874. /* initialize common storage area */
  875. csa->P = P;
  876. csa->deck = (fmt == GLP_MPS_DECK);
  877. csa->parm = parm;
  878. csa->fname = fname;
  879. csa->fp = NULL;
  880. if (setjmp(csa->jump))
  881. { ret = 1;
  882. goto done;
  883. }
  884. csa->recno = csa->recpos = 0;
  885. csa->c = '\n';
  886. csa->fldno = 0;
  887. csa->field[0] = '\0';
  888. csa->w80 = csa->wef = 0;
  889. csa->obj_row = 0;
  890. csa->work1 = csa->work2 = csa->work3 = NULL;
  891. /* erase problem object */
  892. glp_erase_prob(P);
  893. glp_create_index(P);
  894. /* open input MPS file */
  895. csa->fp = glp_open(fname, "r");
  896. if (csa->fp == NULL)
  897. { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg());
  898. ret = 1;
  899. goto done;
  900. }
  901. /* read NAME indicator record */
  902. read_name(csa);
  903. if (P->name != NULL)
  904. xprintf("Problem: %s\n", P->name);
  905. /* read ROWS section */
  906. if (!(indicator(csa, 0) && strcmp(csa->field, "ROWS") == 0))
  907. error(csa, "missing ROWS indicator record\n");
  908. read_rows(csa);
  909. /* determine objective row */
  910. if (parm->obj_name == NULL || parm->obj_name[0] == '\0')
  911. { /* use the first row of N type */
  912. int i;
  913. for (i = 1; i <= P->m; i++)
  914. { if (P->row[i]->type == GLP_FR)
  915. { csa->obj_row = i;
  916. break;
  917. }
  918. }
  919. if (csa->obj_row == 0)
  920. warning(csa, "unable to determine objective row\n");
  921. }
  922. else
  923. { /* use a row with specified name */
  924. int i;
  925. for (i = 1; i <= P->m; i++)
  926. { xassert(P->row[i]->name != NULL);
  927. if (strcmp(parm->obj_name, P->row[i]->name) == 0)
  928. { csa->obj_row = i;
  929. break;
  930. }
  931. }
  932. if (csa->obj_row == 0)
  933. error(csa, "objective row '%s' not found\n",
  934. parm->obj_name);
  935. }
  936. if (csa->obj_row != 0)
  937. { glp_set_obj_name(P, P->row[csa->obj_row]->name);
  938. xprintf("Objective: %s\n", P->obj);
  939. }
  940. /* read COLUMNS section */
  941. if (strcmp(csa->field, "COLUMNS") != 0)
  942. error(csa, "missing COLUMNS indicator record\n");
  943. read_columns(csa);
  944. /* set objective coefficients */
  945. if (csa->obj_row != 0)
  946. { GLPAIJ *aij;
  947. for (aij = P->row[csa->obj_row]->ptr; aij != NULL; aij =
  948. aij->r_next) glp_set_obj_coef(P, aij->col->j, aij->val);
  949. }
  950. /* read optional RHS section */
  951. if (strcmp(csa->field, "RHS") == 0)
  952. read_rhs(csa);
  953. /* read optional RANGES section */
  954. if (strcmp(csa->field, "RANGES") == 0)
  955. read_ranges(csa);
  956. /* read optional BOUNDS section */
  957. if (strcmp(csa->field, "BOUNDS") == 0)
  958. read_bounds(csa);
  959. /* read ENDATA indicator record */
  960. if (strcmp(csa->field, "ENDATA") != 0)
  961. error(csa, "invalid use of %s indicator record\n",
  962. csa->field);
  963. /* print some statistics */
  964. xprintf("%d row%s, %d column%s, %d non-zero%s\n",
  965. P->m, P->m == 1 ? "" : "s", P->n, P->n == 1 ? "" : "s",
  966. P->nnz, P->nnz == 1 ? "" : "s");
  967. if (glp_get_num_int(P) > 0)
  968. { int ni = glp_get_num_int(P);
  969. int nb = glp_get_num_bin(P);
  970. if (ni == 1)
  971. { if (nb == 0)
  972. xprintf("One variable is integer\n");
  973. else
  974. xprintf("One variable is binary\n");
  975. }
  976. else
  977. { xprintf("%d integer variables, ", ni);
  978. if (nb == 0)
  979. xprintf("none");
  980. else if (nb == 1)
  981. xprintf("one");
  982. else if (nb == ni)
  983. xprintf("all");
  984. else
  985. xprintf("%d", nb);
  986. xprintf(" of which %s binary\n", nb == 1 ? "is" : "are");
  987. }
  988. }
  989. xprintf("%d records were read\n", csa->recno);
  990. #if 1 /* 08/VIII-2013 */
  991. /* remove free rows */
  992. { int i, nrs, *num;
  993. num = talloc(1+P->m, int);
  994. nrs = 0;
  995. for (i = 1; i <= P->m; i++)
  996. { if (P->row[i]->type == GLP_FR)
  997. num[++nrs] = i;
  998. }
  999. if (nrs > 0)
  1000. { glp_del_rows(P, nrs, num);
  1001. if (nrs == 1)
  1002. xprintf("One free row was removed\n");
  1003. else
  1004. xprintf("%d free rows were removed\n", nrs);
  1005. }
  1006. tfree(num);
  1007. }
  1008. #endif
  1009. /* problem data has been successfully read */
  1010. glp_delete_index(P);
  1011. glp_sort_matrix(P);
  1012. ret = 0;
  1013. done: if (csa->fp != NULL) glp_close(csa->fp);
  1014. if (csa->work1 != NULL) xfree(csa->work1);
  1015. if (csa->work2 != NULL) xfree(csa->work2);
  1016. if (csa->work3 != NULL) xfree(csa->work3);
  1017. if (ret != 0) glp_erase_prob(P);
  1018. return ret;
  1019. }
  1020. /***********************************************************************
  1021. * NAME
  1022. *
  1023. * glp_write_mps - write problem data in MPS format
  1024. *
  1025. * SYNOPSIS
  1026. *
  1027. * int glp_write_mps(glp_prob *P, int fmt, const glp_mpscp *parm,
  1028. * const char *fname);
  1029. *
  1030. * DESCRIPTION
  1031. *
  1032. * The routine glp_write_mps writes problem data in MPS format to a
  1033. * text file.
  1034. *
  1035. * The parameter fmt specifies the version of MPS format:
  1036. *
  1037. * GLP_MPS_DECK - fixed (ancient) MPS format;
  1038. * GLP_MPS_FILE - free (modern) MPS format.
  1039. *
  1040. * The parameter parm is a pointer to the structure glp_mpscp, which
  1041. * specifies control parameters used by the routine. If parm is NULL,
  1042. * the routine uses default settings.
  1043. *
  1044. * The character string fname specifies a name of the text file to be
  1045. * written.
  1046. *
  1047. * RETURNS
  1048. *
  1049. * If the operation was successful, the routine glp_read_mps returns
  1050. * zero. Otherwise, it prints an error message and returns non-zero. */
  1051. #define csa csa1
  1052. struct csa
  1053. { /* common storage area */
  1054. glp_prob *P;
  1055. /* pointer to problem object */
  1056. int deck;
  1057. /* MPS format (0 - free, 1 - fixed) */
  1058. const glp_mpscp *parm;
  1059. /* pointer to control parameters */
  1060. char field[255+1];
  1061. /* field buffer */
  1062. };
  1063. static char *mps_name(struct csa *csa)
  1064. { /* make problem name */
  1065. char *f;
  1066. if (csa->P->name == NULL)
  1067. csa->field[0] = '\0';
  1068. else if (csa->deck)
  1069. { strncpy(csa->field, csa->P->name, 8);
  1070. csa->field[8] = '\0';
  1071. }
  1072. else
  1073. strcpy(csa->field, csa->P->name);
  1074. for (f = csa->field; *f != '\0'; f++)
  1075. if (*f == ' ') *f = '_';
  1076. return csa->field;
  1077. }
  1078. static char *row_name(struct csa *csa, int i)
  1079. { /* make i-th row name */
  1080. char *f;
  1081. xassert(0 <= i && i <= csa->P->m);
  1082. if (i == 0 || csa->P->row[i]->name == NULL ||
  1083. csa->deck && strlen(csa->P->row[i]->name) > 8)
  1084. sprintf(csa->field, "R%07d", i);
  1085. else
  1086. { strcpy(csa->field, csa->P->row[i]->name);
  1087. for (f = csa->field; *f != '\0'; f++)
  1088. if (*f == ' ') *f = '_';
  1089. }
  1090. return csa->field;
  1091. }
  1092. static char *col_name(struct csa *csa, int j)
  1093. { /* make j-th column name */
  1094. char *f;
  1095. xassert(1 <= j && j <= csa->P->n);
  1096. if (csa->P->col[j]->name == NULL ||
  1097. csa->deck && strlen(csa->P->col[j]->name) > 8)
  1098. sprintf(csa->field, "C%07d", j);
  1099. else
  1100. { strcpy(csa->field, csa->P->col[j]->name);
  1101. for (f = csa->field; *f != '\0'; f++)
  1102. if (*f == ' ') *f = '_';
  1103. }
  1104. return csa->field;
  1105. }
  1106. static char *mps_numb(struct csa *csa, double val)
  1107. { /* format floating-point number */
  1108. int dig;
  1109. char *exp;
  1110. for (dig = 12; dig >= 6; dig--)
  1111. { if (val != 0.0 && fabs(val) < 0.002)
  1112. sprintf(csa->field, "%.*E", dig-1, val);
  1113. else
  1114. sprintf(csa->field, "%.*G", dig, val);
  1115. exp = strchr(csa->field, 'E');
  1116. if (exp != NULL)
  1117. sprintf(exp+1, "%d", atoi(exp+1));
  1118. if (strlen(csa->field) <= 12) break;
  1119. }
  1120. xassert(strlen(csa->field) <= 12);
  1121. return csa->field;
  1122. }
  1123. int glp_write_mps(glp_prob *P, int fmt, const glp_mpscp *parm,
  1124. const char *fname)
  1125. { /* write problem data in MPS format */
  1126. glp_mpscp _parm;
  1127. struct csa _csa, *csa = &_csa;
  1128. glp_file *fp;
  1129. int out_obj, one_col = 0, empty = 0;
  1130. int i, j, recno, marker, count, gap, ret;
  1131. xprintf("Writing problem data to '%s'...\n", fname);
  1132. if (!(fmt == GLP_MPS_DECK || fmt == GLP_MPS_FILE))
  1133. xerror("glp_write_mps: fmt = %d; invalid parameter\n", fmt);
  1134. if (parm == NULL)
  1135. glp_init_mpscp(&_parm), parm = &_parm;
  1136. /* check control parameters */
  1137. check_parm("glp_write_mps", parm);
  1138. /* initialize common storage area */
  1139. csa->P = P;
  1140. csa->deck = (fmt == GLP_MPS_DECK);
  1141. csa->parm = parm;
  1142. /* create output MPS file */
  1143. fp = glp_open(fname, "w"), recno = 0;
  1144. if (fp == NULL)
  1145. { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg());
  1146. ret = 1;
  1147. goto done;
  1148. }
  1149. /* write comment records */
  1150. xfprintf(fp, "* %-*s%s\n", P->name == NULL ? 1 : 12, "Problem:",
  1151. P->name == NULL ? "" : P->name), recno++;
  1152. xfprintf(fp, "* %-12s%s\n", "Class:", glp_get_num_int(P) == 0 ?
  1153. "LP" : "MIP"), recno++;
  1154. xfprintf(fp, "* %-12s%d\n", "Rows:", P->m), recno++;
  1155. if (glp_get_num_int(P) == 0)
  1156. xfprintf(fp, "* %-12s%d\n", "Columns:", P->n), recno++;
  1157. else
  1158. xfprintf(fp, "* %-12s%d (%d integer, %d binary)\n",
  1159. "Columns:", P->n, glp_get_num_int(P), glp_get_num_bin(P)),
  1160. recno++;
  1161. xfprintf(fp, "* %-12s%d\n", "Non-zeros:", P->nnz), recno++;
  1162. xfprintf(fp, "* %-12s%s\n", "Format:", csa->deck ? "Fixed MPS" :
  1163. "Free MPS"), recno++;
  1164. xfprintf(fp, "*\n", recno++);
  1165. /* write NAME indicator record */
  1166. xfprintf(fp, "NAME%*s%s\n",
  1167. P->name == NULL ? 0 : csa->deck ? 10 : 1, "", mps_name(csa)),
  1168. recno++;
  1169. #if 1
  1170. /* determine whether to write the objective row */
  1171. out_obj = 1;
  1172. for (i = 1; i <= P->m; i++)
  1173. { if (P->row[i]->type == GLP_FR)
  1174. { out_obj = 0;
  1175. break;
  1176. }
  1177. }
  1178. #endif
  1179. /* write ROWS section */
  1180. xfprintf(fp, "ROWS\n"), recno++;
  1181. for (i = (out_obj ? 0 : 1); i <= P->m; i++)
  1182. { int type;
  1183. type = (i == 0 ? GLP_FR : P->row[i]->type);
  1184. if (type == GLP_FR)
  1185. type = 'N';
  1186. else if (type == GLP_LO)
  1187. type = 'G';
  1188. else if (type == GLP_UP)
  1189. type = 'L';
  1190. else if (type == GLP_DB || type == GLP_FX)
  1191. type = 'E';
  1192. else
  1193. xassert(type != type);
  1194. xfprintf(fp, " %c%*s%s\n", type, csa->deck ? 2 : 1, "",
  1195. row_name(csa, i)), recno++;
  1196. }
  1197. /* write COLUMNS section */
  1198. xfprintf(fp, "COLUMNS\n"), recno++;
  1199. marker = 0;
  1200. for (j = 1; j <= P->n; j++)
  1201. { GLPAIJ cj, *aij;
  1202. int kind;
  1203. kind = P->col[j]->kind;
  1204. if (kind == GLP_CV)
  1205. { if (marker % 2 == 1)
  1206. { /* close current integer block */
  1207. marker++;
  1208. xfprintf(fp, "%*sM%07d%*s'MARKER'%*s'INTEND'\n",
  1209. csa->deck ? 4 : 1, "", marker, csa->deck ? 2 : 1, "",
  1210. csa->deck ? 17 : 1, ""), recno++;
  1211. }
  1212. }
  1213. else if (kind == GLP_IV)
  1214. { if (marker % 2 == 0)
  1215. { /* open new integer block */
  1216. marker++;
  1217. xfprintf(fp, "%*sM%07d%*s'MARKER'%*s'INTORG'\n",
  1218. csa->deck ? 4 : 1, "", marker, csa->deck ? 2 : 1, "",
  1219. csa->deck ? 17 : 1, ""), recno++;
  1220. }
  1221. }
  1222. else
  1223. xassert(kind != kind);
  1224. if (out_obj && P->col[j]->coef != 0.0)
  1225. { /* make fake objective coefficient */
  1226. aij = &cj;
  1227. aij->row = NULL;
  1228. aij->val = P->col[j]->coef;
  1229. aij->c_next = P->col[j]->ptr;
  1230. }
  1231. else
  1232. aij = P->col[j]->ptr;
  1233. #if 1 /* FIXME */
  1234. if (aij == NULL)
  1235. { /* empty column */
  1236. empty++;
  1237. xfprintf(fp, "%*s%-*s", csa->deck ? 4 : 1, "",
  1238. csa->deck ? 8 : 1, col_name(csa, j));
  1239. /* we need a row */
  1240. xassert(P->m > 0);
  1241. xfprintf(fp, "%*s%-*s",
  1242. csa->deck ? 2 : 1, "", csa->deck ? 8 : 1,
  1243. row_name(csa, 1));
  1244. xfprintf(fp, "%*s0%*s$ empty column\n",
  1245. csa->deck ? 13 : 1, "", csa->deck ? 3 : 1, ""), recno++;
  1246. }
  1247. #endif
  1248. count = 0;
  1249. for (aij = aij; aij != NULL; aij = aij->c_next)
  1250. { if (one_col || count % 2 == 0)
  1251. xfprintf(fp, "%*s%-*s", csa->deck ? 4 : 1, "",
  1252. csa->deck ? 8 : 1, col_name(csa, j));
  1253. gap = (one_col || count % 2 == 0 ? 2 : 3);
  1254. xfprintf(fp, "%*s%-*s",
  1255. csa->deck ? gap : 1, "", csa->deck ? 8 : 1,
  1256. row_name(csa, aij->row == NULL ? 0 : aij->row->i));
  1257. xfprintf(fp, "%*s%*s",
  1258. csa->deck ? 2 : 1, "", csa->deck ? 12 : 1,
  1259. mps_numb(csa, aij->val)), count++;
  1260. if (one_col || count % 2 == 0)
  1261. xfprintf(fp, "\n"), recno++;
  1262. }
  1263. if (!(one_col || count % 2 == 0))
  1264. xfprintf(fp, "\n"), recno++;
  1265. }
  1266. if (marker % 2 == 1)
  1267. { /* close last integer block */
  1268. marker++;
  1269. xfprintf(fp, "%*sM%07d%*s'MARKER'%*s'INTEND'\n",
  1270. csa->deck ? 4 : 1, "", marker, csa->deck ? 2 : 1, "",
  1271. csa->deck ? 17 : 1, ""), recno++;
  1272. }
  1273. #if 1
  1274. if (empty > 0)
  1275. xprintf("Warning: problem has %d empty column(s)\n", empty);
  1276. #endif
  1277. /* write RHS section */
  1278. xfprintf(fp, "RHS\n"), recno++;
  1279. count = 0;
  1280. for (i = (out_obj ? 0 : 1); i <= P->m; i++)
  1281. { int type;
  1282. double rhs;
  1283. if (i == 0)
  1284. rhs = P->c0;
  1285. else
  1286. { type = P->row[i]->type;
  1287. if (type == GLP_FR)
  1288. rhs = 0.0;
  1289. else if (type == GLP_LO)
  1290. rhs = P->row[i]->lb;
  1291. else if (type == GLP_UP)
  1292. rhs = P->row[i]->ub;
  1293. else if (type == GLP_DB || type == GLP_FX)
  1294. rhs = P->row[i]->lb;
  1295. else
  1296. xassert(type != type);
  1297. }
  1298. if (rhs != 0.0)
  1299. { if (one_col || count % 2 == 0)
  1300. xfprintf(fp, "%*s%-*s", csa->deck ? 4 : 1, "",
  1301. csa->deck ? 8 : 1, "RHS1");
  1302. gap = (one_col || count % 2 == 0 ? 2 : 3);
  1303. xfprintf(fp, "%*s%-*s",
  1304. csa->deck ? gap : 1, "", csa->deck ? 8 : 1,
  1305. row_name(csa, i));
  1306. xfprintf(fp, "%*s%*s",
  1307. csa->deck ? 2 : 1, "", csa->deck ? 12 : 1,
  1308. mps_numb(csa, rhs)), count++;
  1309. if (one_col || count % 2 == 0)
  1310. xfprintf(fp, "\n"), recno++;
  1311. }
  1312. }
  1313. if (!(one_col || count % 2 == 0))
  1314. xfprintf(fp, "\n"), recno++;
  1315. /* write RANGES section */
  1316. for (i = P->m; i >= 1; i--)
  1317. if (P->row[i]->type == GLP_DB) break;
  1318. if (i == 0) goto bnds;
  1319. xfprintf(fp, "RANGES\n"), recno++;
  1320. count = 0;
  1321. for (i = 1; i <= P->m; i++)
  1322. { if (P->row[i]->type == GLP_DB)
  1323. { if (one_col || count % 2 == 0)
  1324. xfprintf(fp, "%*s%-*s", csa->deck ? 4 : 1, "",
  1325. csa->deck ? 8 : 1, "RNG1");
  1326. gap = (one_col || count % 2 == 0 ? 2 : 3);
  1327. xfprintf(fp, "%*s%-*s",
  1328. csa->deck ? gap : 1, "", csa->deck ? 8 : 1,
  1329. row_name(csa, i));
  1330. xfprintf(fp, "%*s%*s",
  1331. csa->deck ? 2 : 1, "", csa->deck ? 12 : 1,
  1332. mps_numb(csa, P->row[i]->ub - P->row[i]->lb)), count++;
  1333. if (one_col || count % 2 == 0)
  1334. xfprintf(fp, "\n"), recno++;
  1335. }
  1336. }
  1337. if (!(one_col || count % 2 == 0))
  1338. xfprintf(fp, "\n"), recno++;
  1339. bnds: /* write BOUNDS section */
  1340. for (j = P->n; j >= 1; j--)
  1341. if (!(P->col[j]->kind == GLP_CV &&
  1342. P->col[j]->type == GLP_LO && P->col[j]->lb == 0.0))
  1343. break;
  1344. if (j == 0) goto endt;
  1345. xfprintf(fp, "BOUNDS\n"), recno++;
  1346. for (j = 1; j <= P->n; j++)
  1347. { int type, data[2];
  1348. double bnd[2];
  1349. char *spec[2];
  1350. spec[0] = spec[1] = NULL;
  1351. type = P->col[j]->type;
  1352. if (type == GLP_FR)
  1353. spec[0] = "FR", data[0] = 0;
  1354. else if (type == GLP_LO)
  1355. { if (P->col[j]->lb != 0.0)
  1356. spec[0] = "LO", data[0] = 1, bnd[0] = P->col[j]->lb;
  1357. if (P->col[j]->kind == GLP_IV)
  1358. spec[1] = "PL", data[1] = 0;
  1359. }
  1360. else if (type == GLP_UP)
  1361. { spec[0] = "MI", data[0] = 0;
  1362. spec[1] = "UP", data[1] = 1, bnd[1] = P->col[j]->ub;
  1363. }
  1364. else if (type == GLP_DB)
  1365. { if (P->col[j]->lb != 0.0)
  1366. spec[0] = "LO", data[0] = 1, bnd[0] = P->col[j]->lb;
  1367. spec[1] = "UP", data[1] = 1, bnd[1] = P->col[j]->ub;
  1368. }
  1369. else if (type == GLP_FX)
  1370. spec[0] = "FX", data[0] = 1, bnd[0] = P->col[j]->lb;
  1371. else
  1372. xassert(type != type);
  1373. for (i = 0; i <= 1; i++)
  1374. { if (spec[i] != NULL)
  1375. { xfprintf(fp, " %s %-*s%*s%-*s", spec[i],
  1376. csa->deck ? 8 : 1, "BND1", csa->deck ? 2 : 1, "",
  1377. csa->deck ? 8 : 1, col_name(csa, j));
  1378. if (data[i])
  1379. xfprintf(fp, "%*s%*s", csa->deck ? 2 : 1, "",
  1380. csa->deck ? 12 : 1, mps_numb(csa, bnd[i]));
  1381. xfprintf(fp, "\n"), recno++;
  1382. }
  1383. }
  1384. }
  1385. endt: /* write ENDATA indicator record */
  1386. xfprintf(fp, "ENDATA\n"), recno++;
  1387. #if 0 /* FIXME */
  1388. xfflush(fp);
  1389. #endif
  1390. if (glp_ioerr(fp))
  1391. { xprintf("Write error on '%s' - %s\n", fname, get_err_msg());
  1392. ret = 1;
  1393. goto done;
  1394. }
  1395. /* problem data has been successfully written */
  1396. xprintf("%d records were written\n", recno);
  1397. ret = 0;
  1398. done: if (fp != NULL) glp_close(fp);
  1399. return ret;
  1400. }
  1401. /* eof */