/farmR/src/glpapi11.c

https://code.google.com/p/javawfm/ · C · 967 lines · 701 code · 20 blank · 246 comment · 260 complexity · c5ca2f35d221beda9e37806526fbcd07 MD5 · raw file

  1. /* glpapi11.c (utility routines) */
  2. /***********************************************************************
  3. * This code is part of GLPK (GNU Linear Programming Kit).
  4. *
  5. * Copyright (C) 2000,01,02,03,04,05,06,07,08,2009 Andrew Makhorin,
  6. * Department for Applied Informatics, Moscow Aviation Institute,
  7. * Moscow, Russia. All rights reserved. E-mail: <mao@mai2.rcnet.ru>.
  8. *
  9. * GLPK is free software: you can redistribute it and/or modify it
  10. * under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation, either version 3 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * GLPK is distributed in the hope that it will be useful, but WITHOUT
  15. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  16. * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
  17. * License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with GLPK. If not, see <http://www.gnu.org/licenses/>.
  21. ***********************************************************************/
  22. #include "glpapi.h"
  23. #define PDS _glp_data
  24. #define pds_open_file _glp_sds_open
  25. #define pds_set_jump _glp_sds_jump
  26. #define pds_error _glp_sds_error
  27. #define pds_scan_int _glp_sds_int
  28. #define pds_scan_num _glp_sds_num
  29. #define pds_close_file _glp_sds_close
  30. #undef FILE
  31. #define FILE XFILE
  32. #undef fopen
  33. #define fopen xfopen
  34. #undef strerror
  35. #define strerror(errno) xerrmsg()
  36. #undef fprintf
  37. #define fprintf xfprintf
  38. #undef fflush
  39. #define fflush xfflush
  40. #undef ferror
  41. #define ferror xferror
  42. #undef fclose
  43. #define fclose xfclose
  44. int glp_print_sol(glp_prob *P, const char *fname)
  45. { /* write basic solution in printable format */
  46. XFILE *fp;
  47. GLPROW *row;
  48. GLPCOL *col;
  49. int i, j, t, ae_ind, re_ind, ret;
  50. double ae_max, re_max;
  51. xprintf("Writing basic solution to `%s'...\n", fname);
  52. fp = xfopen(fname, "w");
  53. if (fp == NULL)
  54. { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg());
  55. ret = 1;
  56. goto done;
  57. }
  58. xfprintf(fp, "%-12s%s\n", "Problem:",
  59. P->name == NULL ? "" : P->name);
  60. xfprintf(fp, "%-12s%d\n", "Rows:", P->m);
  61. xfprintf(fp, "%-12s%d\n", "Columns:", P->n);
  62. xfprintf(fp, "%-12s%d\n", "Non-zeros:", P->nnz);
  63. t = glp_get_status(P);
  64. xfprintf(fp, "%-12s%s\n", "Status:",
  65. t == GLP_OPT ? "OPTIMAL" :
  66. t == GLP_FEAS ? "FEASIBLE" :
  67. t == GLP_INFEAS ? "INFEASIBLE (INTERMEDIATE)" :
  68. t == GLP_NOFEAS ? "INFEASIBLE (FINAL)" :
  69. t == GLP_UNBND ? "UNBOUNDED" :
  70. t == GLP_UNDEF ? "UNDEFINED" : "???");
  71. xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:",
  72. P->obj == NULL ? "" : P->obj,
  73. P->obj == NULL ? "" : " = ", P->obj_val,
  74. P->dir == GLP_MIN ? "MINimum" :
  75. P->dir == GLP_MAX ? "MAXimum" : "???");
  76. xfprintf(fp, "\n");
  77. xfprintf(fp, " No. Row name St Activity Lower bound "
  78. " Upper bound Marginal\n");
  79. xfprintf(fp, "------ ------------ -- ------------- ------------- "
  80. "------------- -------------\n");
  81. for (i = 1; i <= P->m; i++)
  82. { row = P->row[i];
  83. xfprintf(fp, "%6d ", i);
  84. if (row->name == NULL || strlen(row->name) <= 12)
  85. xfprintf(fp, "%-12s ", row->name == NULL ? "" : row->name);
  86. else
  87. xfprintf(fp, "%s\n%20s", row->name, "");
  88. xfprintf(fp, "%s ",
  89. row->stat == GLP_BS ? "B " :
  90. row->stat == GLP_NL ? "NL" :
  91. row->stat == GLP_NU ? "NU" :
  92. row->stat == GLP_NF ? "NF" :
  93. row->stat == GLP_NS ? "NS" : "??");
  94. xfprintf(fp, "%13.6g ",
  95. fabs(row->prim) <= 1e-9 ? 0.0 : row->prim);
  96. if (row->type == GLP_LO || row->type == GLP_DB ||
  97. row->type == GLP_FX)
  98. xfprintf(fp, "%13.6g ", row->lb);
  99. else
  100. xfprintf(fp, "%13s ", "");
  101. if (row->type == GLP_UP || row->type == GLP_DB)
  102. xfprintf(fp, "%13.6g ", row->ub);
  103. else
  104. xfprintf(fp, "%13s ", row->type == GLP_FX ? "=" : "");
  105. if (row->stat != GLP_BS)
  106. { if (fabs(row->dual) <= 1e-9)
  107. xfprintf(fp, "%13s", "< eps");
  108. else
  109. xfprintf(fp, "%13.6g ", row->dual);
  110. }
  111. xfprintf(fp, "\n");
  112. }
  113. xfprintf(fp, "\n");
  114. xfprintf(fp, " No. Column name St Activity Lower bound "
  115. " Upper bound Marginal\n");
  116. xfprintf(fp, "------ ------------ -- ------------- ------------- "
  117. "------------- -------------\n");
  118. for (j = 1; j <= P->n; j++)
  119. { col = P->col[j];
  120. xfprintf(fp, "%6d ", j);
  121. if (col->name == NULL || strlen(col->name) <= 12)
  122. xfprintf(fp, "%-12s ", col->name == NULL ? "" : col->name);
  123. else
  124. xfprintf(fp, "%s\n%20s", col->name, "");
  125. xfprintf(fp, "%s ",
  126. col->stat == GLP_BS ? "B " :
  127. col->stat == GLP_NL ? "NL" :
  128. col->stat == GLP_NU ? "NU" :
  129. col->stat == GLP_NF ? "NF" :
  130. col->stat == GLP_NS ? "NS" : "??");
  131. xfprintf(fp, "%13.6g ",
  132. fabs(col->prim) <= 1e-9 ? 0.0 : col->prim);
  133. if (col->type == GLP_LO || col->type == GLP_DB ||
  134. col->type == GLP_FX)
  135. xfprintf(fp, "%13.6g ", col->lb);
  136. else
  137. xfprintf(fp, "%13s ", "");
  138. if (col->type == GLP_UP || col->type == GLP_DB)
  139. xfprintf(fp, "%13.6g ", col->ub);
  140. else
  141. xfprintf(fp, "%13s ", col->type == GLP_FX ? "=" : "");
  142. if (col->stat != GLP_BS)
  143. { if (fabs(col->dual) <= 1e-9)
  144. xfprintf(fp, "%13s", "< eps");
  145. else
  146. xfprintf(fp, "%13.6g ", col->dual);
  147. }
  148. xfprintf(fp, "\n");
  149. }
  150. xfprintf(fp, "\n");
  151. xfprintf(fp, "Karush-Kuhn-Tucker optimality conditions:\n");
  152. xfprintf(fp, "\n");
  153. _glp_check_kkt(P, GLP_SOL, GLP_KKT_PE, &ae_max, &ae_ind, &re_max,
  154. &re_ind);
  155. xfprintf(fp, "KKT.PE: max.abs.err = %.2e on row %d\n",
  156. ae_max, ae_ind);
  157. xfprintf(fp, " max.rel.err = %.2e on row %d\n",
  158. re_max, re_ind);
  159. xfprintf(fp, "%8s%s\n", "",
  160. re_max <= 1e-9 ? "High quality" :
  161. re_max <= 1e-6 ? "Medium quality" :
  162. re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS WRONG");
  163. xfprintf(fp, "\n");
  164. _glp_check_kkt(P, GLP_SOL, GLP_KKT_PB, &ae_max, &ae_ind, &re_max,
  165. &re_ind);
  166. xfprintf(fp, "KKT.PB: max.abs.err = %.2e on %s %d\n",
  167. ae_max, ae_ind <= P->m ? "row" : "column",
  168. ae_ind <= P->m ? ae_ind : ae_ind - P->m);
  169. xfprintf(fp, " max.rel.err = %.2e on %s %d\n",
  170. re_max, re_ind <= P->m ? "row" : "column",
  171. re_ind <= P->m ? re_ind : re_ind - P->m);
  172. xfprintf(fp, "%8s%s\n", "",
  173. re_max <= 1e-9 ? "High quality" :
  174. re_max <= 1e-6 ? "Medium quality" :
  175. re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS INFEASIBL"
  176. "E");
  177. xfprintf(fp, "\n");
  178. _glp_check_kkt(P, GLP_SOL, GLP_KKT_DE, &ae_max, &ae_ind, &re_max,
  179. &re_ind);
  180. xfprintf(fp, "KKT.DE: max.abs.err = %.2e on column %d\n",
  181. ae_max, ae_ind == 0 ? 0 : ae_ind - P->m);
  182. xfprintf(fp, " max.rel.err = %.2e on column %d\n",
  183. re_max, re_ind == 0 ? 0 : re_ind - P->m);
  184. xfprintf(fp, "%8s%s\n", "",
  185. re_max <= 1e-9 ? "High quality" :
  186. re_max <= 1e-6 ? "Medium quality" :
  187. re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS WRONG");
  188. xfprintf(fp, "\n");
  189. _glp_check_kkt(P, GLP_SOL, GLP_KKT_DB, &ae_max, &ae_ind, &re_max,
  190. &re_ind);
  191. xfprintf(fp, "KKT.DB: max.abs.err = %.2e on %s %d\n",
  192. ae_max, ae_ind <= P->m ? "row" : "column",
  193. ae_ind <= P->m ? ae_ind : ae_ind - P->m);
  194. xfprintf(fp, " max.rel.err = %.2e on %s %d\n",
  195. re_max, re_ind <= P->m ? "row" : "column",
  196. re_ind <= P->m ? re_ind : re_ind - P->m);
  197. xfprintf(fp, "%8s%s\n", "",
  198. re_max <= 1e-9 ? "High quality" :
  199. re_max <= 1e-6 ? "Medium quality" :
  200. re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS INFEASIBLE")
  201. ;
  202. xfprintf(fp, "\n");
  203. xfprintf(fp, "End of output\n");
  204. xfflush(fp);
  205. if (xferror(fp))
  206. { xprintf("Write error on `%s' - %s\n", fname, xerrmsg());
  207. ret = 1;
  208. goto done;
  209. }
  210. ret = 0;
  211. done: if (fp != NULL) xfclose(fp);
  212. return ret;
  213. }
  214. /***********************************************************************
  215. * NAME
  216. *
  217. * glp_read_sol - read basic solution from text file
  218. *
  219. * SYNOPSIS
  220. *
  221. * int glp_read_sol(glp_prob *lp, const char *fname);
  222. *
  223. * DESCRIPTION
  224. *
  225. * The routine glp_read_sol reads basic solution from a text file whose
  226. * name is specified by the parameter fname into the problem object.
  227. *
  228. * For the file format see description of the routine glp_write_sol.
  229. *
  230. * RETURNS
  231. *
  232. * On success the routine returns zero, otherwise non-zero. */
  233. int glp_read_sol(glp_prob *lp, const char *fname)
  234. { PDS *pds;
  235. jmp_buf jump;
  236. int i, j, k, ret = 0;
  237. xprintf("Reading basic solution from `%s'...\n", fname);
  238. pds = pds_open_file(fname);
  239. if (pds == NULL)
  240. { ret = 1;
  241. goto done;
  242. }
  243. if (setjmp(jump))
  244. { ret = 1;
  245. goto done;
  246. }
  247. pds_set_jump(pds, jump);
  248. /* number of rows, number of columns */
  249. k = pds_scan_int(pds);
  250. if (k != lp->m)
  251. pds_error(pds, "wrong number of rows\n");
  252. k = pds_scan_int(pds);
  253. if (k != lp->n)
  254. pds_error(pds, "wrong number of columns\n");
  255. /* primal status, dual status, objective value */
  256. k = pds_scan_int(pds);
  257. if (!(k == GLP_UNDEF || k == GLP_FEAS || k == GLP_INFEAS ||
  258. k == GLP_NOFEAS))
  259. pds_error(pds, "invalid primal status\n");
  260. lp->pbs_stat = k;
  261. k = pds_scan_int(pds);
  262. if (!(k == GLP_UNDEF || k == GLP_FEAS || k == GLP_INFEAS ||
  263. k == GLP_NOFEAS))
  264. pds_error(pds, "invalid dual status\n");
  265. lp->dbs_stat = k;
  266. lp->obj_val = pds_scan_num(pds);
  267. /* rows (auxiliary variables) */
  268. for (i = 1; i <= lp->m; i++)
  269. { GLPROW *row = lp->row[i];
  270. /* status, primal value, dual value */
  271. k = pds_scan_int(pds);
  272. if (!(k == GLP_BS || k == GLP_NL || k == GLP_NU ||
  273. k == GLP_NF || k == GLP_NS))
  274. pds_error(pds, "invalid row status\n");
  275. glp_set_row_stat(lp, i, k);
  276. row->prim = pds_scan_num(pds);
  277. row->dual = pds_scan_num(pds);
  278. }
  279. /* columns (structural variables) */
  280. for (j = 1; j <= lp->n; j++)
  281. { GLPCOL *col = lp->col[j];
  282. /* status, primal value, dual value */
  283. k = pds_scan_int(pds);
  284. if (!(k == GLP_BS || k == GLP_NL || k == GLP_NU ||
  285. k == GLP_NF || k == GLP_NS))
  286. pds_error(pds, "invalid column status\n");
  287. glp_set_col_stat(lp, j, k);
  288. col->prim = pds_scan_num(pds);
  289. col->dual = pds_scan_num(pds);
  290. }
  291. xprintf("%d lines were read\n", _glp_sds_line(pds));
  292. done: if (ret) lp->pbs_stat = lp->dbs_stat = GLP_UNDEF;
  293. if (pds != NULL) pds_close_file(pds);
  294. return ret;
  295. }
  296. /***********************************************************************
  297. * NAME
  298. *
  299. * glp_write_sol - write basic solution to text file
  300. *
  301. * SYNOPSIS
  302. *
  303. * int glp_write_sol(glp_prob *lp, const char *fname);
  304. *
  305. * DESCRIPTION
  306. *
  307. * The routine glp_write_sol writes the current basic solution to a
  308. * text file whose name is specified by the parameter fname. This file
  309. * can be read back with the routine glp_read_sol.
  310. *
  311. * RETURNS
  312. *
  313. * On success the routine returns zero, otherwise non-zero.
  314. *
  315. * FILE FORMAT
  316. *
  317. * The file created by the routine glp_write_sol is a plain text file,
  318. * which contains the following information:
  319. *
  320. * m n
  321. * p_stat d_stat obj_val
  322. * r_stat[1] r_prim[1] r_dual[1]
  323. * . . .
  324. * r_stat[m] r_prim[m] r_dual[m]
  325. * c_stat[1] c_prim[1] c_dual[1]
  326. * . . .
  327. * c_stat[n] c_prim[n] c_dual[n]
  328. *
  329. * where:
  330. * m is the number of rows (auxiliary variables);
  331. * n is the number of columns (structural variables);
  332. * p_stat is the primal status of the basic solution (GLP_UNDEF = 1,
  333. * GLP_FEAS = 2, GLP_INFEAS = 3, or GLP_NOFEAS = 4);
  334. * d_stat is the dual status of the basic solution (GLP_UNDEF = 1,
  335. * GLP_FEAS = 2, GLP_INFEAS = 3, or GLP_NOFEAS = 4);
  336. * obj_val is the objective value;
  337. * r_stat[i], i = 1,...,m, is the status of i-th row (GLP_BS = 1,
  338. * GLP_NL = 2, GLP_NU = 3, GLP_NF = 4, or GLP_NS = 5);
  339. * r_prim[i], i = 1,...,m, is the primal value of i-th row;
  340. * r_dual[i], i = 1,...,m, is the dual value of i-th row;
  341. * c_stat[j], j = 1,...,n, is the status of j-th column (GLP_BS = 1,
  342. * GLP_NL = 2, GLP_NU = 3, GLP_NF = 4, or GLP_NS = 5);
  343. * c_prim[j], j = 1,...,n, is the primal value of j-th column;
  344. * c_dual[j], j = 1,...,n, is the dual value of j-th column. */
  345. int glp_write_sol(glp_prob *lp, const char *fname)
  346. { FILE *fp;
  347. int i, j, ret = 0;
  348. xprintf("Writing basic solution to `%s'...\n", fname);
  349. fp = fopen(fname, "w");
  350. if (fp == NULL)
  351. { xprintf("Unable to create `%s' - %s\n", fname,
  352. strerror(errno));
  353. ret = 1;
  354. goto done;
  355. }
  356. /* number of rows, number of columns */
  357. fprintf(fp, "%d %d\n", lp->m, lp->n);
  358. /* primal status, dual status, objective value */
  359. fprintf(fp, "%d %d %.*g\n", lp->pbs_stat, lp->dbs_stat, DBL_DIG,
  360. lp->obj_val);
  361. /* rows (auxiliary variables) */
  362. for (i = 1; i <= lp->m; i++)
  363. { GLPROW *row = lp->row[i];
  364. /* status, primal value, dual value */
  365. fprintf(fp, "%d %.*g %.*g\n", row->stat, DBL_DIG, row->prim,
  366. DBL_DIG, row->dual);
  367. }
  368. /* columns (structural variables) */
  369. for (j = 1; j <= lp->n; j++)
  370. { GLPCOL *col = lp->col[j];
  371. /* status, primal value, dual value */
  372. fprintf(fp, "%d %.*g %.*g\n", col->stat, DBL_DIG, col->prim,
  373. DBL_DIG, col->dual);
  374. }
  375. fflush(fp);
  376. if (ferror(fp))
  377. { xprintf("Write error on `%s' - %s\n", fname, strerror(errno));
  378. ret = 1;
  379. goto done;
  380. }
  381. xprintf("%d lines were written\n", 2 + lp->m + lp->n);
  382. done: if (fp != NULL) fclose(fp);
  383. return ret;
  384. }
  385. /**********************************************************************/
  386. int glp_print_ipt(glp_prob *P, const char *fname)
  387. { /* write interior-point solution in printable format */
  388. XFILE *fp;
  389. GLPROW *row;
  390. GLPCOL *col;
  391. int i, j, t, ae_ind, re_ind, ret;
  392. double ae_max, re_max;
  393. xprintf("Writing interior-point solution to `%s'...\n", fname);
  394. fp = xfopen(fname, "w");
  395. if (fp == NULL)
  396. { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg());
  397. ret = 1;
  398. goto done;
  399. }
  400. xfprintf(fp, "%-12s%s\n", "Problem:",
  401. P->name == NULL ? "" : P->name);
  402. xfprintf(fp, "%-12s%d\n", "Rows:", P->m);
  403. xfprintf(fp, "%-12s%d\n", "Columns:", P->n);
  404. xfprintf(fp, "%-12s%d\n", "Non-zeros:", P->nnz);
  405. t = glp_ipt_status(P);
  406. xfprintf(fp, "%-12s%s\n", "Status:",
  407. t == GLP_OPT ? "OPTIMAL" :
  408. t == GLP_UNDEF ? "UNDEFINED" : "???");
  409. xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:",
  410. P->obj == NULL ? "" : P->obj,
  411. P->obj == NULL ? "" : " = ", P->ipt_obj,
  412. P->dir == GLP_MIN ? "MINimum" :
  413. P->dir == GLP_MAX ? "MAXimum" : "???");
  414. xfprintf(fp, "\n");
  415. xfprintf(fp, " No. Row name Activity Lower bound "
  416. " Upper bound Marginal\n");
  417. xfprintf(fp, "------ ------------ ------------- ------------- "
  418. "------------- -------------\n");
  419. for (i = 1; i <= P->m; i++)
  420. { row = P->row[i];
  421. xfprintf(fp, "%6d ", i);
  422. if (row->name == NULL || strlen(row->name) <= 12)
  423. xfprintf(fp, "%-12s ", row->name == NULL ? "" : row->name);
  424. else
  425. xfprintf(fp, "%s\n%20s", row->name, "");
  426. xfprintf(fp, "%3s", "");
  427. xfprintf(fp, "%13.6g ",
  428. fabs(row->pval) <= 1e-9 ? 0.0 : row->pval);
  429. if (row->type == GLP_LO || row->type == GLP_DB ||
  430. row->type == GLP_FX)
  431. xfprintf(fp, "%13.6g ", row->lb);
  432. else
  433. xfprintf(fp, "%13s ", "");
  434. if (row->type == GLP_UP || row->type == GLP_DB)
  435. xfprintf(fp, "%13.6g ", row->ub);
  436. else
  437. xfprintf(fp, "%13s ", row->type == GLP_FX ? "=" : "");
  438. if (fabs(row->dval) <= 1e-9)
  439. xfprintf(fp, "%13s", "< eps");
  440. else
  441. xfprintf(fp, "%13.6g ", row->dval);
  442. xfprintf(fp, "\n");
  443. }
  444. xfprintf(fp, "\n");
  445. xfprintf(fp, " No. Column name Activity Lower bound "
  446. " Upper bound Marginal\n");
  447. xfprintf(fp, "------ ------------ ------------- ------------- "
  448. "------------- -------------\n");
  449. for (j = 1; j <= P->n; j++)
  450. { col = P->col[j];
  451. xfprintf(fp, "%6d ", j);
  452. if (col->name == NULL || strlen(col->name) <= 12)
  453. xfprintf(fp, "%-12s ", col->name == NULL ? "" : col->name);
  454. else
  455. xfprintf(fp, "%s\n%20s", col->name, "");
  456. xfprintf(fp, "%3s", "");
  457. xfprintf(fp, "%13.6g ",
  458. fabs(col->pval) <= 1e-9 ? 0.0 : col->pval);
  459. if (col->type == GLP_LO || col->type == GLP_DB ||
  460. col->type == GLP_FX)
  461. xfprintf(fp, "%13.6g ", col->lb);
  462. else
  463. xfprintf(fp, "%13s ", "");
  464. if (col->type == GLP_UP || col->type == GLP_DB)
  465. xfprintf(fp, "%13.6g ", col->ub);
  466. else
  467. xfprintf(fp, "%13s ", col->type == GLP_FX ? "=" : "");
  468. if (fabs(col->dval) <= 1e-9)
  469. xfprintf(fp, "%13s", "< eps");
  470. else
  471. xfprintf(fp, "%13.6g ", col->dval);
  472. xfprintf(fp, "\n");
  473. }
  474. xfprintf(fp, "\n");
  475. xfprintf(fp, "Karush-Kuhn-Tucker optimality conditions:\n");
  476. xfprintf(fp, "\n");
  477. _glp_check_kkt(P, GLP_IPT, GLP_KKT_PE, &ae_max, &ae_ind, &re_max,
  478. &re_ind);
  479. xfprintf(fp, "KKT.PE: max.abs.err = %.2e on row %d\n",
  480. ae_max, ae_ind);
  481. xfprintf(fp, " max.rel.err = %.2e on row %d\n",
  482. re_max, re_ind);
  483. xfprintf(fp, "%8s%s\n", "",
  484. re_max <= 1e-9 ? "High quality" :
  485. re_max <= 1e-6 ? "Medium quality" :
  486. re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS WRONG");
  487. xfprintf(fp, "\n");
  488. _glp_check_kkt(P, GLP_IPT, GLP_KKT_PB, &ae_max, &ae_ind, &re_max,
  489. &re_ind);
  490. xfprintf(fp, "KKT.PB: max.abs.err = %.2e on %s %d\n",
  491. ae_max, ae_ind <= P->m ? "row" : "column",
  492. ae_ind <= P->m ? ae_ind : ae_ind - P->m);
  493. xfprintf(fp, " max.rel.err = %.2e on %s %d\n",
  494. re_max, re_ind <= P->m ? "row" : "column",
  495. re_ind <= P->m ? re_ind : re_ind - P->m);
  496. xfprintf(fp, "%8s%s\n", "",
  497. re_max <= 1e-9 ? "High quality" :
  498. re_max <= 1e-6 ? "Medium quality" :
  499. re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS INFEASIBL"
  500. "E");
  501. xfprintf(fp, "\n");
  502. _glp_check_kkt(P, GLP_IPT, GLP_KKT_DE, &ae_max, &ae_ind, &re_max,
  503. &re_ind);
  504. xfprintf(fp, "KKT.DE: max.abs.err = %.2e on column %d\n",
  505. ae_max, ae_ind == 0 ? 0 : ae_ind - P->m);
  506. xfprintf(fp, " max.rel.err = %.2e on column %d\n",
  507. re_max, re_ind == 0 ? 0 : re_ind - P->m);
  508. xfprintf(fp, "%8s%s\n", "",
  509. re_max <= 1e-9 ? "High quality" :
  510. re_max <= 1e-6 ? "Medium quality" :
  511. re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS WRONG");
  512. xfprintf(fp, "\n");
  513. _glp_check_kkt(P, GLP_IPT, GLP_KKT_DB, &ae_max, &ae_ind, &re_max,
  514. &re_ind);
  515. xfprintf(fp, "KKT.DB: max.abs.err = %.2e on %s %d\n",
  516. ae_max, ae_ind <= P->m ? "row" : "column",
  517. ae_ind <= P->m ? ae_ind : ae_ind - P->m);
  518. xfprintf(fp, " max.rel.err = %.2e on %s %d\n",
  519. re_max, re_ind <= P->m ? "row" : "column",
  520. re_ind <= P->m ? re_ind : re_ind - P->m);
  521. xfprintf(fp, "%8s%s\n", "",
  522. re_max <= 1e-9 ? "High quality" :
  523. re_max <= 1e-6 ? "Medium quality" :
  524. re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS INFEASIBLE")
  525. ;
  526. xfprintf(fp, "\n");
  527. xfprintf(fp, "End of output\n");
  528. xfflush(fp);
  529. if (xferror(fp))
  530. { xprintf("Write error on `%s' - %s\n", fname, xerrmsg());
  531. ret = 1;
  532. goto done;
  533. }
  534. ret = 0;
  535. done: if (fp != NULL) xfclose(fp);
  536. return ret;
  537. }
  538. /***********************************************************************
  539. * NAME
  540. *
  541. * glp_read_ipt - read interior-point solution from text file
  542. *
  543. * SYNOPSIS
  544. *
  545. * int glp_read_ipt(glp_prob *lp, const char *fname);
  546. *
  547. * DESCRIPTION
  548. *
  549. * The routine glp_read_ipt reads interior-point solution from a text
  550. * file whose name is specified by the parameter fname into the problem
  551. * object.
  552. *
  553. * For the file format see description of the routine glp_write_ipt.
  554. *
  555. * RETURNS
  556. *
  557. * On success the routine returns zero, otherwise non-zero. */
  558. int glp_read_ipt(glp_prob *lp, const char *fname)
  559. { PDS *pds;
  560. jmp_buf jump;
  561. int i, j, k, ret = 0;
  562. xprintf("Reading interior-point solution from `%s'...\n", fname);
  563. pds = pds_open_file(fname);
  564. if (pds == NULL)
  565. { ret = 1;
  566. goto done;
  567. }
  568. if (setjmp(jump))
  569. { ret = 1;
  570. goto done;
  571. }
  572. pds_set_jump(pds, jump);
  573. /* number of rows, number of columns */
  574. k = pds_scan_int(pds);
  575. if (k != lp->m)
  576. pds_error(pds, "wrong number of rows\n");
  577. k = pds_scan_int(pds);
  578. if (k != lp->n)
  579. pds_error(pds, "wrong number of columns\n");
  580. /* solution status, objective value */
  581. k = pds_scan_int(pds);
  582. if (!(k == GLP_UNDEF || k == GLP_OPT))
  583. pds_error(pds, "invalid solution status\n");
  584. lp->ipt_stat = k;
  585. lp->ipt_obj = pds_scan_num(pds);
  586. /* rows (auxiliary variables) */
  587. for (i = 1; i <= lp->m; i++)
  588. { GLPROW *row = lp->row[i];
  589. /* primal value, dual value */
  590. row->pval = pds_scan_num(pds);
  591. row->dval = pds_scan_num(pds);
  592. }
  593. /* columns (structural variables) */
  594. for (j = 1; j <= lp->n; j++)
  595. { GLPCOL *col = lp->col[j];
  596. /* primal value, dual value */
  597. col->pval = pds_scan_num(pds);
  598. col->dval = pds_scan_num(pds);
  599. }
  600. xprintf("%d lines were read\n", _glp_sds_line(pds));
  601. done: if (ret) lp->ipt_stat = GLP_UNDEF;
  602. if (pds != NULL) pds_close_file(pds);
  603. return ret;
  604. }
  605. /***********************************************************************
  606. * NAME
  607. *
  608. * glp_write_ipt - write interior-point solution to text file
  609. *
  610. * SYNOPSIS
  611. *
  612. * int glp_write_ipt(glp_prob *lp, const char *fname);
  613. *
  614. * DESCRIPTION
  615. *
  616. * The routine glp_write_ipt writes the current interior-point solution
  617. * to a text file whose name is specified by the parameter fname. This
  618. * file can be read back with the routine glp_read_ipt.
  619. *
  620. * RETURNS
  621. *
  622. * On success the routine returns zero, otherwise non-zero.
  623. *
  624. * FILE FORMAT
  625. *
  626. * The file created by the routine glp_write_ipt is a plain text file,
  627. * which contains the following information:
  628. *
  629. * m n
  630. * stat obj_val
  631. * r_prim[1] r_dual[1]
  632. * . . .
  633. * r_prim[m] r_dual[m]
  634. * c_prim[1] c_dual[1]
  635. * . . .
  636. * c_prim[n] c_dual[n]
  637. *
  638. * where:
  639. * m is the number of rows (auxiliary variables);
  640. * n is the number of columns (structural variables);
  641. * stat is the solution status (GLP_UNDEF = 1 or GLP_OPT = 5);
  642. * obj_val is the objective value;
  643. * r_prim[i], i = 1,...,m, is the primal value of i-th row;
  644. * r_dual[i], i = 1,...,m, is the dual value of i-th row;
  645. * c_prim[j], j = 1,...,n, is the primal value of j-th column;
  646. * c_dual[j], j = 1,...,n, is the dual value of j-th column. */
  647. int glp_write_ipt(glp_prob *lp, const char *fname)
  648. { FILE *fp;
  649. int i, j, ret = 0;
  650. xprintf("Writing interior-point solution to `%s'...\n", fname);
  651. fp = fopen(fname, "w");
  652. if (fp == NULL)
  653. { xprintf("Unable to create `%s' - %s\n", fname,
  654. strerror(errno));
  655. ret = 1;
  656. goto done;
  657. }
  658. /* number of rows, number of columns */
  659. fprintf(fp, "%d %d\n", lp->m, lp->n);
  660. /* solution status, objective value */
  661. fprintf(fp, "%d %.*g\n", lp->ipt_stat, DBL_DIG, lp->ipt_obj);
  662. /* rows (auxiliary variables) */
  663. for (i = 1; i <= lp->m; i++)
  664. { GLPROW *row = lp->row[i];
  665. /* primal value, dual value */
  666. fprintf(fp, "%.*g %.*g\n", DBL_DIG, row->pval, DBL_DIG,
  667. row->dval);
  668. }
  669. /* columns (structural variables) */
  670. for (j = 1; j <= lp->n; j++)
  671. { GLPCOL *col = lp->col[j];
  672. /* primal value, dual value */
  673. fprintf(fp, "%.*g %.*g\n", DBL_DIG, col->pval, DBL_DIG,
  674. col->dval);
  675. }
  676. fflush(fp);
  677. if (ferror(fp))
  678. { xprintf("Write error on `%s' - %s\n", fname, strerror(errno));
  679. ret = 1;
  680. goto done;
  681. }
  682. xprintf("%d lines were written\n", 2 + lp->m + lp->n);
  683. done: if (fp != NULL) fclose(fp);
  684. return ret;
  685. }
  686. /**********************************************************************/
  687. int glp_print_mip(glp_prob *P, const char *fname)
  688. { /* write MIP solution in printable format */
  689. XFILE *fp;
  690. GLPROW *row;
  691. GLPCOL *col;
  692. int i, j, t, ae_ind, re_ind, ret;
  693. double ae_max, re_max;
  694. xprintf("Writing MIP solution to `%s'...\n", fname);
  695. fp = xfopen(fname, "w");
  696. if (fp == NULL)
  697. { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg());
  698. ret = 1;
  699. goto done;
  700. }
  701. xfprintf(fp, "%-12s%s\n", "Problem:",
  702. P->name == NULL ? "" : P->name);
  703. xfprintf(fp, "%-12s%d\n", "Rows:", P->m);
  704. xfprintf(fp, "%-12s%d (%d integer, %d binary)\n", "Columns:",
  705. P->n, glp_get_num_int(P), glp_get_num_bin(P));
  706. xfprintf(fp, "%-12s%d\n", "Non-zeros:", P->nnz);
  707. t = glp_mip_status(P);
  708. xfprintf(fp, "%-12s%s\n", "Status:",
  709. t == GLP_OPT ? "INTEGER OPTIMAL" :
  710. t == GLP_FEAS ? "INTEGER NON-OPTIMAL" :
  711. t == GLP_NOFEAS ? "INTEGER EMPTY" :
  712. t == GLP_UNDEF ? "INTEGER UNDEFINED" : "???");
  713. xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:",
  714. P->obj == NULL ? "" : P->obj,
  715. P->obj == NULL ? "" : " = ", P->mip_obj,
  716. P->dir == GLP_MIN ? "MINimum" :
  717. P->dir == GLP_MAX ? "MAXimum" : "???");
  718. xfprintf(fp, "\n");
  719. xfprintf(fp, " No. Row name Activity Lower bound "
  720. " Upper bound\n");
  721. xfprintf(fp, "------ ------------ ------------- ------------- "
  722. "-------------\n");
  723. for (i = 1; i <= P->m; i++)
  724. { row = P->row[i];
  725. xfprintf(fp, "%6d ", i);
  726. if (row->name == NULL || strlen(row->name) <= 12)
  727. xfprintf(fp, "%-12s ", row->name == NULL ? "" : row->name);
  728. else
  729. xfprintf(fp, "%s\n%20s", row->name, "");
  730. xfprintf(fp, "%3s", "");
  731. xfprintf(fp, "%13.6g ",
  732. fabs(row->mipx) <= 1e-9 ? 0.0 : row->mipx);
  733. if (row->type == GLP_LO || row->type == GLP_DB ||
  734. row->type == GLP_FX)
  735. xfprintf(fp, "%13.6g ", row->lb);
  736. else
  737. xfprintf(fp, "%13s ", "");
  738. if (row->type == GLP_UP || row->type == GLP_DB)
  739. xfprintf(fp, "%13.6g ", row->ub);
  740. else
  741. xfprintf(fp, "%13s ", row->type == GLP_FX ? "=" : "");
  742. xfprintf(fp, "\n");
  743. }
  744. xfprintf(fp, "\n");
  745. xfprintf(fp, " No. Column name Activity Lower bound "
  746. " Upper bound\n");
  747. xfprintf(fp, "------ ------------ ------------- ------------- "
  748. "-------------\n");
  749. for (j = 1; j <= P->n; j++)
  750. { col = P->col[j];
  751. xfprintf(fp, "%6d ", j);
  752. if (col->name == NULL || strlen(col->name) <= 12)
  753. xfprintf(fp, "%-12s ", col->name == NULL ? "" : col->name);
  754. else
  755. xfprintf(fp, "%s\n%20s", col->name, "");
  756. xfprintf(fp, "%s ",
  757. col->kind == GLP_CV ? " " :
  758. col->kind == GLP_IV ? "*" : "?");
  759. xfprintf(fp, "%13.6g ",
  760. fabs(col->mipx) <= 1e-9 ? 0.0 : col->mipx);
  761. if (col->type == GLP_LO || col->type == GLP_DB ||
  762. col->type == GLP_FX)
  763. xfprintf(fp, "%13.6g ", col->lb);
  764. else
  765. xfprintf(fp, "%13s ", "");
  766. if (col->type == GLP_UP || col->type == GLP_DB)
  767. xfprintf(fp, "%13.6g ", col->ub);
  768. else
  769. xfprintf(fp, "%13s ", col->type == GLP_FX ? "=" : "");
  770. xfprintf(fp, "\n");
  771. }
  772. xfprintf(fp, "\n");
  773. xfprintf(fp, "Integer feasibility conditions:\n");
  774. xfprintf(fp, "\n");
  775. _glp_check_kkt(P, GLP_MIP, GLP_KKT_PE, &ae_max, &ae_ind, &re_max,
  776. &re_ind);
  777. xfprintf(fp, "KKT.PE: max.abs.err = %.2e on row %d\n",
  778. ae_max, ae_ind);
  779. xfprintf(fp, " max.rel.err = %.2e on row %d\n",
  780. re_max, re_ind);
  781. xfprintf(fp, "%8s%s\n", "",
  782. re_max <= 1e-9 ? "High quality" :
  783. re_max <= 1e-6 ? "Medium quality" :
  784. re_max <= 1e-3 ? "Low quality" : "SOLUTION IS WRONG");
  785. xfprintf(fp, "\n");
  786. _glp_check_kkt(P, GLP_MIP, GLP_KKT_PB, &ae_max, &ae_ind, &re_max,
  787. &re_ind);
  788. xfprintf(fp, "KKT.PB: max.abs.err = %.2e on %s %d\n",
  789. ae_max, ae_ind <= P->m ? "row" : "column",
  790. ae_ind <= P->m ? ae_ind : ae_ind - P->m);
  791. xfprintf(fp, " max.rel.err = %.2e on %s %d\n",
  792. re_max, re_ind <= P->m ? "row" : "column",
  793. re_ind <= P->m ? re_ind : re_ind - P->m);
  794. xfprintf(fp, "%8s%s\n", "",
  795. re_max <= 1e-9 ? "High quality" :
  796. re_max <= 1e-6 ? "Medium quality" :
  797. re_max <= 1e-3 ? "Low quality" : "SOLUTION IS INFEASIBLE");
  798. xfprintf(fp, "\n");
  799. xfprintf(fp, "End of output\n");
  800. xfflush(fp);
  801. if (xferror(fp))
  802. { xprintf("Write error on `%s' - %s\n", fname, xerrmsg());
  803. ret = 1;
  804. goto done;
  805. }
  806. ret = 0;
  807. done: if (fp != NULL) xfclose(fp);
  808. return ret;
  809. }
  810. /***********************************************************************
  811. * NAME
  812. *
  813. * glp_read_mip - read MIP solution from text file
  814. *
  815. * SYNOPSIS
  816. *
  817. * int glp_read_mip(glp_prob *mip, const char *fname);
  818. *
  819. * DESCRIPTION
  820. *
  821. * The routine glp_read_mip reads MIP solution from a text file whose
  822. * name is specified by the parameter fname into the problem object.
  823. *
  824. * For the file format see description of the routine glp_write_mip.
  825. *
  826. * RETURNS
  827. *
  828. * On success the routine returns zero, otherwise non-zero. */
  829. int glp_read_mip(glp_prob *mip, const char *fname)
  830. { PDS *pds;
  831. jmp_buf jump;
  832. int i, j, k, ret = 0;
  833. xprintf("Reading MIP solution from `%s'...\n", fname);
  834. pds = pds_open_file(fname);
  835. if (pds == NULL)
  836. { ret = 1;
  837. goto done;
  838. }
  839. if (setjmp(jump))
  840. { ret = 1;
  841. goto done;
  842. }
  843. pds_set_jump(pds, jump);
  844. /* number of rows, number of columns */
  845. k = pds_scan_int(pds);
  846. if (k != mip->m)
  847. pds_error(pds, "wrong number of rows\n");
  848. k = pds_scan_int(pds);
  849. if (k != mip->n)
  850. pds_error(pds, "wrong number of columns\n");
  851. /* solution status, objective value */
  852. k = pds_scan_int(pds);
  853. if (!(k == GLP_UNDEF || k == GLP_OPT || k == GLP_FEAS ||
  854. k == GLP_NOFEAS))
  855. pds_error(pds, "invalid solution status\n");
  856. mip->mip_stat = k;
  857. mip->mip_obj = pds_scan_num(pds);
  858. /* rows (auxiliary variables) */
  859. for (i = 1; i <= mip->m; i++)
  860. { GLPROW *row = mip->row[i];
  861. row->mipx = pds_scan_num(pds);
  862. }
  863. /* columns (structural variables) */
  864. for (j = 1; j <= mip->n; j++)
  865. { GLPCOL *col = mip->col[j];
  866. col->mipx = pds_scan_num(pds);
  867. if (col->kind == GLP_IV && col->mipx != floor(col->mipx))
  868. pds_error(pds, "non-integer column value");
  869. }
  870. xprintf("%d lines were read\n", _glp_sds_line(pds));
  871. done: if (ret) mip->mip_stat = GLP_UNDEF;
  872. if (pds != NULL) pds_close_file(pds);
  873. return ret;
  874. }
  875. /***********************************************************************
  876. * NAME
  877. *
  878. * glp_write_mip - write MIP solution to text file
  879. *
  880. * SYNOPSIS
  881. *
  882. * int glp_write_mip(glp_prob *mip, const char *fname);
  883. *
  884. * DESCRIPTION
  885. *
  886. * The routine glp_write_mip writes the current MIP solution to a text
  887. * file whose name is specified by the parameter fname. This file can
  888. * be read back with the routine glp_read_mip.
  889. *
  890. * RETURNS
  891. *
  892. * On success the routine returns zero, otherwise non-zero.
  893. *
  894. * FILE FORMAT
  895. *
  896. * The file created by the routine glp_write_sol is a plain text file,
  897. * which contains the following information:
  898. *
  899. * m n
  900. * stat obj_val
  901. * r_val[1]
  902. * . . .
  903. * r_val[m]
  904. * c_val[1]
  905. * . . .
  906. * c_val[n]
  907. *
  908. * where:
  909. * m is the number of rows (auxiliary variables);
  910. * n is the number of columns (structural variables);
  911. * stat is the solution status (GLP_UNDEF = 1, GLP_FEAS = 2,
  912. * GLP_NOFEAS = 4, or GLP_OPT = 5);
  913. * obj_val is the objective value;
  914. * r_val[i], i = 1,...,m, is the value of i-th row;
  915. * c_val[j], j = 1,...,n, is the value of j-th column. */
  916. int glp_write_mip(glp_prob *mip, const char *fname)
  917. { FILE *fp;
  918. int i, j, ret = 0;
  919. xprintf("Writing MIP solution to `%s'...\n", fname);
  920. fp = fopen(fname, "w");
  921. if (fp == NULL)
  922. { xprintf("Unable to create `%s' - %s\n", fname,
  923. strerror(errno));
  924. ret = 1;
  925. goto done;
  926. }
  927. /* number of rows, number of columns */
  928. fprintf(fp, "%d %d\n", mip->m, mip->n);
  929. /* solution status, objective value */
  930. fprintf(fp, "%d %.*g\n", mip->mip_stat, DBL_DIG, mip->mip_obj);
  931. /* rows (auxiliary variables) */
  932. for (i = 1; i <= mip->m; i++)
  933. fprintf(fp, "%.*g\n", DBL_DIG, mip->row[i]->mipx);
  934. /* columns (structural variables) */
  935. for (j = 1; j <= mip->n; j++)
  936. fprintf(fp, "%.*g\n", DBL_DIG, mip->col[j]->mipx);
  937. fflush(fp);
  938. if (ferror(fp))
  939. { xprintf("Write error on `%s' - %s\n", fname, strerror(errno));
  940. ret = 1;
  941. goto done;
  942. }
  943. xprintf("%d lines were written\n", 2 + mip->m + mip->n);
  944. done: if (fp != NULL) fclose(fp);
  945. return ret;
  946. }
  947. /* eof */