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.

1584 lines
56 KiB

2 months ago
  1. /* glpsol.c (stand-alone GLPK LP/MIP solver) */
  2. /***********************************************************************
  3. * This code is part of GLPK (GNU Linear Programming Kit).
  4. *
  5. * Copyright (C) 2000-2017 Andrew Makhorin, Department for Applied
  6. * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
  7. * reserved. E-mail: <mao@gnu.org>.
  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. #ifdef HAVE_CONFIG_H
  23. #include <config.h>
  24. #endif
  25. #include <ctype.h>
  26. #include <float.h>
  27. #include <limits.h>
  28. #include <math.h>
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include <glpk.h>
  33. #define xassert glp_assert
  34. #define xerror glp_error
  35. #define xprintf glp_printf
  36. struct csa
  37. { /* common storage area */
  38. glp_prob *prob;
  39. /* LP/MIP problem object */
  40. glp_bfcp bfcp;
  41. /* basis factorization control parameters */
  42. glp_smcp smcp;
  43. /* simplex method control parameters */
  44. glp_iptcp iptcp;
  45. /* interior-point method control parameters */
  46. glp_iocp iocp;
  47. /* integer optimizer control parameters */
  48. glp_tran *tran;
  49. /* model translator workspace */
  50. glp_graph *graph;
  51. /* network problem object */
  52. int format;
  53. /* problem file format: */
  54. #define FMT_MPS_DECK 1 /* fixed MPS */
  55. #define FMT_MPS_FILE 2 /* free MPS */
  56. #define FMT_LP 3 /* CPLEX LP */
  57. #define FMT_GLP 4 /* GLPK LP/MIP */
  58. #define FMT_MATHPROG 5 /* MathProg */
  59. #define FMT_MIN_COST 6 /* DIMACS min-cost flow */
  60. #define FMT_MAX_FLOW 7 /* DIMACS maximum flow */
  61. #if 1 /* 06/VIII-2011 */
  62. #define FMT_CNF 8 /* DIMACS CNF-SAT */
  63. #endif
  64. const char *in_file;
  65. /* name of input problem file */
  66. #define DATA_MAX 10
  67. /* maximal number of input data files */
  68. int ndf;
  69. /* number of input data files specified */
  70. const char *in_data[1+DATA_MAX];
  71. /* name(s) of input data file(s) */
  72. const char *out_dpy;
  73. /* name of output file to send display output; NULL means the
  74. display output is sent to the terminal */
  75. int seed;
  76. /* seed value to be passed to the MathProg translator; initially
  77. set to 1; 0x80000000 means the value is omitted */
  78. int solution;
  79. /* solution type flag: */
  80. #define SOL_BASIC 1 /* basic */
  81. #define SOL_INTERIOR 2 /* interior-point */
  82. #define SOL_INTEGER 3 /* mixed integer */
  83. const char *in_res;
  84. /* name of input solution file in raw format */
  85. int dir;
  86. /* optimization direction flag:
  87. 0 - not specified
  88. GLP_MIN - minimization
  89. GLP_MAX - maximization */
  90. int scale;
  91. /* automatic problem scaling flag */
  92. const char *out_sol;
  93. /* name of output solution file in printable format */
  94. const char *out_res;
  95. /* name of output solution file in raw format */
  96. const char *out_ranges;
  97. /* name of output file to write sensitivity analysis report */
  98. int check;
  99. /* input data checking flag; no solution is performed */
  100. const char *new_name;
  101. /* new name to be assigned to the problem */
  102. #if 1 /* 18/I-2018 */
  103. int hide;
  104. /* clear all symbolic names in the problem object */
  105. #endif
  106. const char *out_mps;
  107. /* name of output problem file in fixed MPS format */
  108. const char *out_freemps;
  109. /* name of output problem file in free MPS format */
  110. const char *out_cpxlp;
  111. /* name of output problem file in CPLEX LP format */
  112. const char *out_glp;
  113. /* name of output problem file in GLPK format */
  114. #if 0
  115. const char *out_pb;
  116. /* name of output problem file in OPB format */
  117. const char *out_npb;
  118. /* name of output problem file in normalized OPB format */
  119. #endif
  120. #if 1 /* 06/VIII-2011 */
  121. const char *out_cnf;
  122. /* name of output problem file in DIMACS CNF-SAT format */
  123. #endif
  124. const char *log_file;
  125. /* name of output file to hardcopy terminal output */
  126. int crash;
  127. /* initial basis option: */
  128. #define USE_STD_BASIS 1 /* use standard basis */
  129. #define USE_ADV_BASIS 2 /* use advanced basis */
  130. #define USE_CPX_BASIS 3 /* use Bixby's basis */
  131. #define USE_INI_BASIS 4 /* use initial basis from ini_file */
  132. const char *ini_file;
  133. /* name of input file containing initial basis */
  134. int exact;
  135. /* flag to use glp_exact rather than glp_simplex */
  136. int xcheck;
  137. /* flag to check final basis with glp_exact */
  138. int nomip;
  139. /* flag to consider MIP as pure LP */
  140. #if 1 /* 15/VIII-2011 */
  141. int minisat;
  142. /* option to solve feasibility problem with MiniSat solver */
  143. int use_bnd;
  144. /* option to bound objective function */
  145. int obj_bnd;
  146. /* upper (minization) or lower (maximization) objective bound */
  147. #endif
  148. #if 1 /* 11/VII-2013 */
  149. const char *use_sol;
  150. /* name of input mip solution file in GLPK format */
  151. #endif
  152. };
  153. static int str2int(const char *s, int *x)
  154. { /* convert string to integer */
  155. long t;
  156. char *endptr;
  157. t = strtol(s, &endptr, 10);
  158. if (*endptr != '\0')
  159. return 2;
  160. if (!(INT_MIN <= t && t <= INT_MAX))
  161. return 1;
  162. *x = t;
  163. #if 0
  164. xprintf("str2int: x = %d\n", *x);
  165. #endif
  166. return 0;
  167. }
  168. static int str2num(const char *s, double *x)
  169. { /* convert string to floating point */
  170. double t;
  171. char *endptr;
  172. t = strtod(s, &endptr);
  173. if (*endptr != '\0')
  174. return 2;
  175. if (!(-DBL_MAX <= t && t <= +DBL_MAX))
  176. return 1;
  177. *x = t;
  178. #if 0
  179. xprintf("str2num: x = %g\n", *x);
  180. #endif
  181. return 0;
  182. }
  183. static void print_help(const char *my_name)
  184. { /* print help information */
  185. xprintf("Usage: %s [options...] filename\n", my_name);
  186. xprintf("\n");
  187. xprintf("General options:\n");
  188. xprintf(" --mps read LP/MIP problem in fixed MPS fo"
  189. "rmat\n");
  190. xprintf(" --freemps read LP/MIP problem in free MPS for"
  191. "mat (default)\n");
  192. xprintf(" --lp read LP/MIP problem in CPLEX LP for"
  193. "mat\n");
  194. xprintf(" --glp read LP/MIP problem in GLPK format "
  195. "\n");
  196. xprintf(" --math read LP/MIP model written in GNU Ma"
  197. "thProg modeling\n");
  198. xprintf(" language\n");
  199. xprintf(" -m filename, --model filename\n");
  200. xprintf(" read model section and optional dat"
  201. "a section from\n");
  202. xprintf(" filename (same as --math)\n");
  203. xprintf(" -d filename, --data filename\n");
  204. xprintf(" read data section from filename (fo"
  205. "r --math only);\n");
  206. xprintf(" if model file also has data section"
  207. ", it is ignored\n");
  208. xprintf(" -y filename, --display filename\n");
  209. xprintf(" send display output to filename (fo"
  210. "r --math only);\n");
  211. xprintf(" by default the output is sent to te"
  212. "rminal\n");
  213. xprintf(" --seed value initialize pseudo-random number gen"
  214. "erator used in\n");
  215. xprintf(" MathProg model with specified seed "
  216. "(any integer);\n");
  217. xprintf(" if seed value is ?, some random see"
  218. "d will be used\n");
  219. xprintf(" --mincost read min-cost flow problem in DIMAC"
  220. "S format\n");
  221. xprintf(" --maxflow read maximum flow problem in DIMACS"
  222. " format\n");
  223. #if 1 /* 06/VIII-2011 */
  224. xprintf(" --cnf read CNF-SAT problem in DIMACS form"
  225. "at\n");
  226. #endif
  227. xprintf(" --simplex use simplex method (default)\n");
  228. xprintf(" --interior use interior point method (LP only)"
  229. "\n");
  230. xprintf(" -r filename, --read filename\n");
  231. xprintf(" read solution from filename rather "
  232. "to find it with\n");
  233. xprintf(" the solver\n");
  234. xprintf(" --min minimization\n");
  235. xprintf(" --max maximization\n");
  236. xprintf(" --scale scale problem (default)\n");
  237. xprintf(" --noscale do not scale problem\n");
  238. xprintf(" -o filename, --output filename\n");
  239. xprintf(" write solution to filename in print"
  240. "able format\n");
  241. xprintf(" -w filename, --write filename\n");
  242. xprintf(" write solution to filename in plain"
  243. " text format\n");
  244. xprintf(" --ranges filename\n");
  245. xprintf(" write sensitivity analysis report t"
  246. "o filename in\n");
  247. xprintf(" printable format (simplex only)\n");
  248. xprintf(" --tmlim nnn limit solution time to nnn seconds "
  249. "\n");
  250. xprintf(" --memlim nnn limit available memory to nnn megab"
  251. "ytes\n");
  252. xprintf(" --check do not solve problem, check input d"
  253. "ata only\n");
  254. xprintf(" --name probname change problem name to probname\n");
  255. #if 1 /* 18/I-2018 */
  256. xprintf(" --hide remove all symbolic names from prob"
  257. "lem object\n");
  258. #endif
  259. xprintf(" --wmps filename write problem to filename in fixed "
  260. "MPS format\n");
  261. xprintf(" --wfreemps filename\n");
  262. xprintf(" write problem to filename in free M"
  263. "PS format\n");
  264. xprintf(" --wlp filename write problem to filename in CPLEX "
  265. "LP format\n");
  266. xprintf(" --wglp filename write problem to filename in GLPK f"
  267. "ormat\n");
  268. #if 0
  269. xprintf(" --wpb filename write problem to filename in OPB fo"
  270. "rmat\n");
  271. xprintf(" --wnpb filename write problem to filename in normal"
  272. "ized OPB format\n");
  273. #endif
  274. #if 1 /* 06/VIII-2011 */
  275. xprintf(" --wcnf filename write problem to filename in DIMACS"
  276. " CNF-SAT format\n");
  277. #endif
  278. xprintf(" --log filename write copy of terminal output to fi"
  279. "lename\n");
  280. xprintf(" -h, --help display this help information and e"
  281. "xit\n");
  282. xprintf(" -v, --version display program version and exit\n")
  283. ;
  284. xprintf("\n");
  285. xprintf("LP basis factorization options:\n");
  286. #if 0 /* 08/III-2014 */
  287. xprintf(" --luf LU + Forrest-Tomlin update\n");
  288. xprintf(" (faster, less stable; default)\n");
  289. xprintf(" --cbg LU + Schur complement + Bartels-Gol"
  290. "ub update\n");
  291. xprintf(" (slower, more stable)\n");
  292. xprintf(" --cgr LU + Schur complement + Givens rota"
  293. "tion update\n");
  294. xprintf(" (slower, more stable)\n");
  295. #else
  296. xprintf(" --luf plain LU-factorization (default)\n")
  297. ;
  298. xprintf(" --btf block triangular LU-factorization\n"
  299. );
  300. xprintf(" --ft Forrest-Tomlin update (requires --l"
  301. "uf; default)\n");
  302. xprintf(" --cbg Schur complement + Bartels-Golub up"
  303. "date\n");
  304. xprintf(" --cgr Schur complement + Givens rotation "
  305. "update\n");
  306. #endif
  307. xprintf("\n");
  308. xprintf("Options specific to simplex solver:\n");
  309. xprintf(" --primal use primal simplex (default)\n");
  310. xprintf(" --dual use dual simplex\n");
  311. xprintf(" --std use standard initial basis of all s"
  312. "lacks\n");
  313. xprintf(" --adv use advanced initial basis (default"
  314. ")\n");
  315. xprintf(" --bib use Bixby's initial basis\n");
  316. xprintf(" --ini filename use as initial basis previously sav"
  317. "ed with -w\n");
  318. xprintf(" (disables LP presolver)\n");
  319. xprintf(" --steep use steepest edge technique (defaul"
  320. "t)\n");
  321. xprintf(" --nosteep use standard \"textbook\" pricing\n"
  322. );
  323. xprintf(" --relax use Harris' two-pass ratio test (de"
  324. "fault)\n");
  325. xprintf(" --norelax use standard \"textbook\" ratio tes"
  326. "t\n");
  327. #if 0 /* 23/VI-2017 */
  328. #if 1 /* 28/III-2016 */
  329. xprintf(" --flip use flip-flop ratio test (assumes -"
  330. "-dual)\n");
  331. #endif
  332. #else
  333. /* now this option is implemented in both primal and dual */
  334. xprintf(" --flip use long-step ratio test\n");
  335. #endif
  336. xprintf(" --presol use presolver (default; assumes --s"
  337. "cale and --adv)\n");
  338. xprintf(" --nopresol do not use presolver\n");
  339. xprintf(" --exact use simplex method based on exact a"
  340. "rithmetic\n");
  341. xprintf(" --xcheck check final basis using exact arith"
  342. "metic\n");
  343. xprintf("\n");
  344. xprintf("Options specific to interior-point solver:\n");
  345. xprintf(" --nord use natural (original) ordering\n");
  346. xprintf(" --qmd use quotient minimum degree orderin"
  347. "g\n");
  348. xprintf(" --amd use approximate minimum degree orde"
  349. "ring (default)\n");
  350. xprintf(" --symamd use approximate minimum degree orde"
  351. "ring\n");
  352. xprintf("\n");
  353. xprintf("Options specific to MIP solver:\n");
  354. xprintf(" --nomip consider all integer variables as c"
  355. "ontinuous\n");
  356. xprintf(" (allows solving MIP as pure LP)\n");
  357. xprintf(" --first branch on first integer variable\n")
  358. ;
  359. xprintf(" --last branch on last integer variable\n");
  360. xprintf(" --mostf branch on most fractional variable "
  361. "\n");
  362. xprintf(" --drtom branch using heuristic by Driebeck "
  363. "and Tomlin\n");
  364. xprintf(" (default)\n");
  365. xprintf(" --pcost branch using hybrid pseudocost heur"
  366. "istic (may be\n");
  367. xprintf(" useful for hard instances)\n");
  368. xprintf(" --dfs backtrack using depth first search "
  369. "\n");
  370. xprintf(" --bfs backtrack using breadth first searc"
  371. "h\n");
  372. xprintf(" --bestp backtrack using the best projection"
  373. " heuristic\n");
  374. xprintf(" --bestb backtrack using node with best loca"
  375. "l bound\n");
  376. xprintf(" (default)\n");
  377. xprintf(" --intopt use MIP presolver (default)\n");
  378. xprintf(" --nointopt do not use MIP presolver\n");
  379. xprintf(" --binarize replace general integer variables b"
  380. "y binary ones\n");
  381. xprintf(" (assumes --intopt)\n");
  382. xprintf(" --fpump apply feasibility pump heuristic\n")
  383. ;
  384. #if 1 /* 29/VI-2013 */
  385. xprintf(" --proxy [nnn] apply proximity search heuristic (n"
  386. "nn is time limit\n");
  387. xprintf(" in seconds; default is 60)\n");
  388. #endif
  389. xprintf(" --gomory generate Gomory's mixed integer cut"
  390. "s\n");
  391. xprintf(" --mir generate MIR (mixed integer roundin"
  392. "g) cuts\n");
  393. xprintf(" --cover generate mixed cover cuts\n");
  394. xprintf(" --clique generate clique cuts\n");
  395. xprintf(" --cuts generate all cuts above\n");
  396. xprintf(" --mipgap tol set relative mip gap tolerance to t"
  397. "ol\n");
  398. #if 1 /* 15/VIII-2011 */
  399. xprintf(" --minisat translate integer feasibility probl"
  400. "em to CNF-SAT\n");
  401. xprintf(" and solve it with MiniSat solver\n")
  402. ;
  403. xprintf(" --objbnd bound add inequality obj <= bound (minimi"
  404. "zation) or\n");
  405. xprintf(" obj >= bound (maximization) to inte"
  406. "ger feasibility\n");
  407. xprintf(" problem (assumes --minisat)\n");
  408. #endif
  409. xprintf("\n");
  410. xprintf("For description of the MPS and CPLEX LP formats see Refe"
  411. "rence Manual.\n");
  412. xprintf("For description of the modeling language see \"GLPK: Mod"
  413. "eling Language\n");
  414. xprintf("GNU MathProg\". Both documents are included in the GLPK "
  415. "distribution.\n");
  416. xprintf("\n");
  417. xprintf("See GLPK web page at <http://www.gnu.org/software/glpk/g"
  418. "lpk.html>.\n");
  419. xprintf("\n");
  420. xprintf("Please report bugs to <bug-glpk@gnu.org>.\n");
  421. return;
  422. }
  423. static void print_version(int briefly)
  424. { /* print version information */
  425. xprintf("GLPSOL: GLPK LP/MIP Solver, v%s\n", glp_version());
  426. if (briefly) goto done;
  427. xprintf("Copyright (C) 2000-2017 Andrew Makhorin, Department for "
  428. "Applied\n");
  429. xprintf("Informatics, Moscow Aviation Institute, Moscow, Russia. "
  430. "All rights\n");
  431. xprintf("reserved. E-mail: <mao@gnu.org>.\n");
  432. xprintf("\n");
  433. xprintf("This program has ABSOLUTELY NO WARRANTY.\n");
  434. xprintf("\n");
  435. xprintf("This program is free software; you may re-distribute it "
  436. "under the terms\n");
  437. xprintf("of the GNU General Public License version 3 or later.\n")
  438. ;
  439. done: return;
  440. }
  441. static int parse_cmdline(struct csa *csa, int argc, char *argv[])
  442. { /* parse command-line parameters */
  443. int k;
  444. #define p(str) (strcmp(argv[k], str) == 0)
  445. for (k = 1; k < argc; k++)
  446. { if (p("--mps"))
  447. csa->format = FMT_MPS_DECK;
  448. else if (p("--freemps"))
  449. csa->format = FMT_MPS_FILE;
  450. else if (p("--lp") || p("--cpxlp"))
  451. csa->format = FMT_LP;
  452. else if (p("--glp"))
  453. csa->format = FMT_GLP;
  454. else if (p("--math") || p("-m") || p("--model"))
  455. csa->format = FMT_MATHPROG;
  456. else if (p("-d") || p("--data"))
  457. { k++;
  458. if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
  459. { xprintf("No input data file specified\n");
  460. return 1;
  461. }
  462. if (csa->ndf == DATA_MAX)
  463. { xprintf("Too many input data files\n");
  464. return 1;
  465. }
  466. csa->in_data[++(csa->ndf)] = argv[k];
  467. }
  468. else if (p("-y") || p("--display"))
  469. { k++;
  470. if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
  471. { xprintf("No display output file specified\n");
  472. return 1;
  473. }
  474. if (csa->out_dpy != NULL)
  475. { xprintf("Only one display output file allowed\n");
  476. return 1;
  477. }
  478. csa->out_dpy = argv[k];
  479. }
  480. else if (p("--seed"))
  481. { k++;
  482. if (k == argc || argv[k][0] == '\0' ||
  483. argv[k][0] == '-' && !isdigit((unsigned char)argv[k][1]))
  484. { xprintf("No seed value specified\n");
  485. return 1;
  486. }
  487. if (strcmp(argv[k], "?") == 0)
  488. csa->seed = 0x80000000;
  489. else if (str2int(argv[k], &csa->seed))
  490. { xprintf("Invalid seed value '%s'\n", argv[k]);
  491. return 1;
  492. }
  493. }
  494. else if (p("--mincost"))
  495. csa->format = FMT_MIN_COST;
  496. else if (p("--maxflow"))
  497. csa->format = FMT_MAX_FLOW;
  498. #if 1 /* 06/VIII-2011 */
  499. else if (p("--cnf"))
  500. csa->format = FMT_CNF;
  501. #endif
  502. else if (p("--simplex"))
  503. csa->solution = SOL_BASIC;
  504. else if (p("--interior"))
  505. csa->solution = SOL_INTERIOR;
  506. #if 1 /* 28/V-2010 */
  507. else if (p("--alien"))
  508. csa->iocp.alien = GLP_ON;
  509. #endif
  510. else if (p("-r") || p("--read"))
  511. { k++;
  512. if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
  513. { xprintf("No input solution file specified\n");
  514. return 1;
  515. }
  516. if (csa->in_res != NULL)
  517. { xprintf("Only one input solution file allowed\n");
  518. return 1;
  519. }
  520. csa->in_res = argv[k];
  521. }
  522. else if (p("--min"))
  523. csa->dir = GLP_MIN;
  524. else if (p("--max"))
  525. csa->dir = GLP_MAX;
  526. else if (p("--scale"))
  527. csa->scale = 1;
  528. else if (p("--noscale"))
  529. csa->scale = 0;
  530. else if (p("-o") || p("--output"))
  531. { k++;
  532. if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
  533. { xprintf("No output solution file specified\n");
  534. return 1;
  535. }
  536. if (csa->out_sol != NULL)
  537. { xprintf("Only one output solution file allowed\n");
  538. return 1;
  539. }
  540. csa->out_sol = argv[k];
  541. }
  542. else if (p("-w") || p("--write"))
  543. { k++;
  544. if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
  545. { xprintf("No output solution file specified\n");
  546. return 1;
  547. }
  548. if (csa->out_res != NULL)
  549. { xprintf("Only one output solution file allowed\n");
  550. return 1;
  551. }
  552. csa->out_res = argv[k];
  553. }
  554. else if (p("--ranges") || p("--bounds"))
  555. { k++;
  556. if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
  557. { xprintf("No output file specified to write sensitivity a"
  558. "nalysis report\n");
  559. return 1;
  560. }
  561. if (csa->out_ranges != NULL)
  562. { xprintf("Only one output file allowed to write sensitivi"
  563. "ty analysis report\n");
  564. return 1;
  565. }
  566. csa->out_ranges = argv[k];
  567. }
  568. else if (p("--tmlim"))
  569. { int tm_lim;
  570. k++;
  571. if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
  572. { xprintf("No time limit specified\n");
  573. return 1;
  574. }
  575. if (str2int(argv[k], &tm_lim) || tm_lim < 0)
  576. { xprintf("Invalid time limit '%s'\n", argv[k]);
  577. return 1;
  578. }
  579. if (tm_lim <= INT_MAX / 1000)
  580. csa->smcp.tm_lim = csa->iocp.tm_lim = 1000 * tm_lim;
  581. else
  582. csa->smcp.tm_lim = csa->iocp.tm_lim = INT_MAX;
  583. }
  584. else if (p("--memlim"))
  585. { int mem_lim;
  586. k++;
  587. if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
  588. { xprintf("No memory limit specified\n");
  589. return 1;
  590. }
  591. if (str2int(argv[k], &mem_lim) || mem_lim < 1)
  592. { xprintf("Invalid memory limit '%s'\n", argv[k]);
  593. return 1;
  594. }
  595. glp_mem_limit(mem_lim);
  596. }
  597. else if (p("--check"))
  598. csa->check = 1;
  599. else if (p("--name"))
  600. { k++;
  601. if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
  602. { xprintf("No problem name specified\n");
  603. return 1;
  604. }
  605. if (csa->new_name != NULL)
  606. { xprintf("Only one problem name allowed\n");
  607. return 1;
  608. }
  609. csa->new_name = argv[k];
  610. }
  611. #if 1 /* 18/I-2018 */
  612. else if (p("--hide"))
  613. csa->hide = 1;
  614. #endif
  615. else if (p("--wmps"))
  616. { k++;
  617. if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
  618. { xprintf("No fixed MPS output file specified\n");
  619. return 1;
  620. }
  621. if (csa->out_mps != NULL)
  622. { xprintf("Only one fixed MPS output file allowed\n");
  623. return 1;
  624. }
  625. csa->out_mps = argv[k];
  626. }
  627. else if (p("--wfreemps"))
  628. { k++;
  629. if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
  630. { xprintf("No free MPS output file specified\n");
  631. return 1;
  632. }
  633. if (csa->out_freemps != NULL)
  634. { xprintf("Only one free MPS output file allowed\n");
  635. return 1;
  636. }
  637. csa->out_freemps = argv[k];
  638. }
  639. else if (p("--wlp") || p("--wcpxlp") || p("--wlpt"))
  640. { k++;
  641. if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
  642. { xprintf("No CPLEX LP output file specified\n");
  643. return 1;
  644. }
  645. if (csa->out_cpxlp != NULL)
  646. { xprintf("Only one CPLEX LP output file allowed\n");
  647. return 1;
  648. }
  649. csa->out_cpxlp = argv[k];
  650. }
  651. else if (p("--wglp"))
  652. { k++;
  653. if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
  654. { xprintf("No GLPK LP/MIP output file specified\n");
  655. return 1;
  656. }
  657. if (csa->out_glp != NULL)
  658. { xprintf("Only one GLPK LP/MIP output file allowed\n");
  659. return 1;
  660. }
  661. csa->out_glp = argv[k];
  662. }
  663. #if 0
  664. else if (p("--wpb"))
  665. { k++;
  666. if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
  667. { xprintf("No problem output file specified\n");
  668. return 1;
  669. }
  670. if (csa->out_pb != NULL)
  671. { xprintf("Only one OPB output file allowed\n");
  672. return 1;
  673. }
  674. csa->out_pb = argv[k];
  675. }
  676. else if (p("--wnpb"))
  677. { k++;
  678. if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
  679. { xprintf("No problem output file specified\n");
  680. return 1;
  681. }
  682. if (csa->out_npb != NULL)
  683. { xprintf("Only one normalized OPB output file allowed\n");
  684. return 1;
  685. }
  686. csa->out_npb = argv[k];
  687. }
  688. #endif
  689. #if 1 /* 06/VIII-2011 */
  690. else if (p("--wcnf"))
  691. { k++;
  692. if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
  693. { xprintf("No problem output file specified\n");
  694. return 1;
  695. }
  696. if (csa->out_cnf != NULL)
  697. { xprintf("Only one output DIMACS CNF-SAT file allowed\n");
  698. return 1;
  699. }
  700. csa->out_cnf = argv[k];
  701. }
  702. #endif
  703. else if (p("--log"))
  704. { k++;
  705. if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
  706. { xprintf("No log file specified\n");
  707. return 1;
  708. }
  709. if (csa->log_file != NULL)
  710. { xprintf("Only one log file allowed\n");
  711. return 1;
  712. }
  713. csa->log_file = argv[k];
  714. }
  715. else if (p("-h") || p("--help"))
  716. { print_help(argv[0]);
  717. return -1;
  718. }
  719. else if (p("-v") || p("--version"))
  720. { print_version(0);
  721. return -1;
  722. }
  723. #if 0 /* 08/III-2014 */
  724. else if (p("--luf"))
  725. csa->bfcp.type = GLP_BF_FT;
  726. else if (p("--cbg"))
  727. csa->bfcp.type = GLP_BF_BG;
  728. else if (p("--cgr"))
  729. csa->bfcp.type = GLP_BF_GR;
  730. #else
  731. else if (p("--luf"))
  732. { csa->bfcp.type &= 0x0F;
  733. csa->bfcp.type |= GLP_BF_LUF;
  734. }
  735. else if (p("--btf"))
  736. { csa->bfcp.type &= 0x0F;
  737. csa->bfcp.type |= GLP_BF_BTF;
  738. }
  739. else if (p("--ft"))
  740. { csa->bfcp.type &= 0xF0;
  741. csa->bfcp.type |= GLP_BF_FT;
  742. }
  743. else if (p("--cbg"))
  744. { csa->bfcp.type &= 0xF0;
  745. csa->bfcp.type |= GLP_BF_BG;
  746. }
  747. else if (p("--cgr"))
  748. { csa->bfcp.type &= 0xF0;
  749. csa->bfcp.type |= GLP_BF_GR;
  750. }
  751. #endif
  752. else if (p("--primal"))
  753. csa->smcp.meth = GLP_PRIMAL;
  754. else if (p("--dual"))
  755. csa->smcp.meth = GLP_DUAL;
  756. else if (p("--std"))
  757. csa->crash = USE_STD_BASIS;
  758. else if (p("--adv"))
  759. csa->crash = USE_ADV_BASIS;
  760. else if (p("--bib"))
  761. csa->crash = USE_CPX_BASIS;
  762. else if (p("--ini"))
  763. { csa->crash = USE_INI_BASIS;
  764. csa->smcp.presolve = GLP_OFF;
  765. k++;
  766. if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
  767. { xprintf("No initial basis file specified\n");
  768. return 1;
  769. }
  770. if (csa->ini_file != NULL)
  771. { xprintf("Only one initial basis file allowed\n");
  772. return 1;
  773. }
  774. csa->ini_file = argv[k];
  775. }
  776. else if (p("--steep"))
  777. csa->smcp.pricing = GLP_PT_PSE;
  778. else if (p("--nosteep"))
  779. csa->smcp.pricing = GLP_PT_STD;
  780. else if (p("--relax"))
  781. csa->smcp.r_test = GLP_RT_HAR;
  782. else if (p("--norelax"))
  783. csa->smcp.r_test = GLP_RT_STD;
  784. #if 1 /* 28/III-2016 */
  785. else if (p("--flip"))
  786. #if 0 /* 23/VI-2017 */
  787. { csa->smcp.meth = GLP_DUAL;
  788. #else
  789. /* now this option is implemented in both primal and dual */
  790. {
  791. #endif
  792. csa->smcp.r_test = GLP_RT_FLIP;
  793. csa->iocp.flip = GLP_ON;
  794. }
  795. #endif
  796. else if (p("--presol"))
  797. csa->smcp.presolve = GLP_ON;
  798. else if (p("--nopresol"))
  799. csa->smcp.presolve = GLP_OFF;
  800. else if (p("--exact"))
  801. csa->exact = 1;
  802. else if (p("--xcheck"))
  803. csa->xcheck = 1;
  804. else if (p("--nord"))
  805. csa->iptcp.ord_alg = GLP_ORD_NONE;
  806. else if (p("--qmd"))
  807. csa->iptcp.ord_alg = GLP_ORD_QMD;
  808. else if (p("--amd"))
  809. csa->iptcp.ord_alg = GLP_ORD_AMD;
  810. else if (p("--symamd"))
  811. csa->iptcp.ord_alg = GLP_ORD_SYMAMD;
  812. else if (p("--nomip"))
  813. csa->nomip = 1;
  814. else if (p("--first"))
  815. csa->iocp.br_tech = GLP_BR_FFV;
  816. else if (p("--last"))
  817. csa->iocp.br_tech = GLP_BR_LFV;
  818. else if (p("--drtom"))
  819. csa->iocp.br_tech = GLP_BR_DTH;
  820. else if (p("--mostf"))
  821. csa->iocp.br_tech = GLP_BR_MFV;
  822. else if (p("--pcost"))
  823. csa->iocp.br_tech = GLP_BR_PCH;
  824. else if (p("--dfs"))
  825. csa->iocp.bt_tech = GLP_BT_DFS;
  826. else if (p("--bfs"))
  827. csa->iocp.bt_tech = GLP_BT_BFS;
  828. else if (p("--bestp"))
  829. csa->iocp.bt_tech = GLP_BT_BPH;
  830. else if (p("--bestb"))
  831. csa->iocp.bt_tech = GLP_BT_BLB;
  832. else if (p("--intopt"))
  833. csa->iocp.presolve = GLP_ON;
  834. else if (p("--nointopt"))
  835. csa->iocp.presolve = GLP_OFF;
  836. else if (p("--binarize"))
  837. csa->iocp.presolve = csa->iocp.binarize = GLP_ON;
  838. else if (p("--fpump"))
  839. csa->iocp.fp_heur = GLP_ON;
  840. #if 1 /* 29/VI-2013 */
  841. else if (p("--proxy"))
  842. { csa->iocp.ps_heur = GLP_ON;
  843. if (argv[k+1] && isdigit((unsigned char)argv[k+1][0]))
  844. { int nnn;
  845. k++;
  846. if (str2int(argv[k], &nnn) || nnn < 1)
  847. { xprintf("Invalid proxy time limit '%s'\n", argv[k]);
  848. return 1;
  849. }
  850. csa->iocp.ps_tm_lim = 1000 * nnn;
  851. }
  852. }
  853. #endif
  854. else if (p("--gomory"))
  855. csa->iocp.gmi_cuts = GLP_ON;
  856. else if (p("--mir"))
  857. csa->iocp.mir_cuts = GLP_ON;
  858. else if (p("--cover"))
  859. csa->iocp.cov_cuts = GLP_ON;
  860. else if (p("--clique"))
  861. csa->iocp.clq_cuts = GLP_ON;
  862. else if (p("--cuts"))
  863. csa->iocp.gmi_cuts = csa->iocp.mir_cuts =
  864. csa->iocp.cov_cuts = csa->iocp.clq_cuts = GLP_ON;
  865. else if (p("--mipgap"))
  866. { double mip_gap;
  867. k++;
  868. if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
  869. { xprintf("No relative gap tolerance specified\n");
  870. return 1;
  871. }
  872. if (str2num(argv[k], &mip_gap) || mip_gap < 0.0)
  873. { xprintf("Invalid relative mip gap tolerance '%s'\n",
  874. argv[k]);
  875. return 1;
  876. }
  877. csa->iocp.mip_gap = mip_gap;
  878. }
  879. #if 1 /* 15/VIII-2011 */
  880. else if (p("--minisat"))
  881. csa->minisat = 1;
  882. else if (p("--objbnd"))
  883. { k++;
  884. if (k == argc || argv[k][0] == '\0' ||
  885. argv[k][0] == '-' && !isdigit((unsigned char)argv[k][1]))
  886. { xprintf("No objective bound specified\n");
  887. return 1;
  888. }
  889. csa->minisat = 1;
  890. csa->use_bnd = 1;
  891. if (str2int(argv[k], &csa->obj_bnd))
  892. { xprintf("Invalid objective bound '%s' (should be integer"
  893. " value)\n", argv[k]);
  894. return 1;
  895. }
  896. }
  897. #endif
  898. #if 1 /* 11/VII-2013 */
  899. else if (p("--use"))
  900. { k++;
  901. if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
  902. { xprintf("No input MIP solution file specified\n");
  903. return 1;
  904. }
  905. if (csa->use_sol != NULL)
  906. { xprintf("Only one input MIP solution file allowed\n");
  907. return 1;
  908. }
  909. csa->use_sol = argv[k];
  910. }
  911. else if (p("--save"))
  912. { k++;
  913. if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
  914. { xprintf("No output MIP solution file specified\n");
  915. return 1;
  916. }
  917. if (csa->iocp.save_sol != NULL)
  918. { xprintf("Only one output MIP solution file allowed\n");
  919. return 1;
  920. }
  921. csa->iocp.save_sol = argv[k];
  922. }
  923. #endif
  924. else if (argv[k][0] == '-' ||
  925. (argv[k][0] == '-' && argv[k][1] == '-'))
  926. { xprintf("Invalid option '%s'; try %s --help\n",
  927. argv[k], argv[0]);
  928. return 1;
  929. }
  930. else
  931. { if (csa->in_file != NULL)
  932. { xprintf("Only one input problem file allowed\n");
  933. return 1;
  934. }
  935. csa->in_file = argv[k];
  936. }
  937. }
  938. #undef p
  939. return 0;
  940. }
  941. typedef struct { double rhs, pi; } v_data;
  942. typedef struct { double low, cap, cost, x; } a_data;
  943. #ifndef __WOE__
  944. int main(int argc, char *argv[])
  945. #else
  946. int __cdecl main(int argc, char *argv[])
  947. #endif
  948. { /* stand-alone LP/MIP solver */
  949. struct csa _csa, *csa = &_csa;
  950. int ret;
  951. #if 0 /* 10/VI-2013 */
  952. glp_long start;
  953. #else
  954. double start;
  955. #endif
  956. /* perform initialization */
  957. csa->prob = glp_create_prob();
  958. glp_get_bfcp(csa->prob, &csa->bfcp);
  959. glp_init_smcp(&csa->smcp);
  960. csa->smcp.presolve = GLP_ON;
  961. glp_init_iptcp(&csa->iptcp);
  962. glp_init_iocp(&csa->iocp);
  963. csa->iocp.presolve = GLP_ON;
  964. csa->tran = NULL;
  965. csa->graph = NULL;
  966. csa->format = FMT_MPS_FILE;
  967. csa->in_file = NULL;
  968. csa->ndf = 0;
  969. csa->out_dpy = NULL;
  970. csa->seed = 1;
  971. csa->solution = SOL_BASIC;
  972. csa->in_res = NULL;
  973. csa->dir = 0;
  974. csa->scale = 1;
  975. csa->out_sol = NULL;
  976. csa->out_res = NULL;
  977. csa->out_ranges = NULL;
  978. csa->check = 0;
  979. csa->new_name = NULL;
  980. #if 1 /* 18/I-2018 */
  981. csa->hide = 0;
  982. #endif
  983. csa->out_mps = NULL;
  984. csa->out_freemps = NULL;
  985. csa->out_cpxlp = NULL;
  986. csa->out_glp = NULL;
  987. #if 0
  988. csa->out_pb = NULL;
  989. csa->out_npb = NULL;
  990. #endif
  991. #if 1 /* 06/VIII-2011 */
  992. csa->out_cnf = NULL;
  993. #endif
  994. csa->log_file = NULL;
  995. csa->crash = USE_ADV_BASIS;
  996. csa->ini_file = NULL;
  997. csa->exact = 0;
  998. csa->xcheck = 0;
  999. csa->nomip = 0;
  1000. #if 1 /* 15/VIII-2011 */
  1001. csa->minisat = 0;
  1002. csa->use_bnd = 0;
  1003. csa->obj_bnd = 0;
  1004. #endif
  1005. #if 1 /* 11/VII-2013 */
  1006. csa->use_sol = NULL;
  1007. #endif
  1008. /* parse command-line parameters */
  1009. ret = parse_cmdline(csa, argc, argv);
  1010. if (ret < 0)
  1011. { ret = EXIT_SUCCESS;
  1012. goto done;
  1013. }
  1014. if (ret > 0)
  1015. { ret = EXIT_FAILURE;
  1016. goto done;
  1017. }
  1018. /*--------------------------------------------------------------*/
  1019. /* remove all output files specified in the command line */
  1020. if (csa->out_dpy != NULL) remove(csa->out_dpy);
  1021. if (csa->out_sol != NULL) remove(csa->out_sol);
  1022. if (csa->out_res != NULL) remove(csa->out_res);
  1023. if (csa->out_ranges != NULL) remove(csa->out_ranges);
  1024. if (csa->out_mps != NULL) remove(csa->out_mps);
  1025. if (csa->out_freemps != NULL) remove(csa->out_freemps);
  1026. if (csa->out_cpxlp != NULL) remove(csa->out_cpxlp);
  1027. if (csa->out_glp != NULL) remove(csa->out_glp);
  1028. #if 0
  1029. if (csa->out_pb != NULL) remove(csa->out_pb);
  1030. if (csa->out_npb != NULL) remove(csa->out_npb);
  1031. #endif
  1032. #if 1 /* 06/VIII-2011 */
  1033. if (csa->out_cnf != NULL) remove(csa->out_cnf);
  1034. #endif
  1035. if (csa->log_file != NULL) remove(csa->log_file);
  1036. /*--------------------------------------------------------------*/
  1037. /* open log file, if required */
  1038. if (csa->log_file != NULL)
  1039. { if (glp_open_tee(csa->log_file))
  1040. { xprintf("Unable to create log file\n");
  1041. ret = EXIT_FAILURE;
  1042. goto done;
  1043. }
  1044. }
  1045. /*--------------------------------------------------------------*/
  1046. /* print version information */
  1047. print_version(1);
  1048. /*--------------------------------------------------------------*/
  1049. /* print parameters specified in the command line */
  1050. if (argc > 1)
  1051. { int k, len = INT_MAX;
  1052. xprintf("Parameter(s) specified in the command line:");
  1053. for (k = 1; k < argc; k++)
  1054. { if (len > 72)
  1055. xprintf("\n"), len = 0;
  1056. xprintf(" %s", argv[k]);
  1057. len += 1 + strlen(argv[k]);
  1058. }
  1059. xprintf("\n");
  1060. }
  1061. /*--------------------------------------------------------------*/
  1062. /* read problem data from the input file */
  1063. if (csa->in_file == NULL)
  1064. { xprintf("No input problem file specified; try %s --help\n",
  1065. argv[0]);
  1066. ret = EXIT_FAILURE;
  1067. goto done;
  1068. }
  1069. if (csa->format == FMT_MPS_DECK)
  1070. { ret = glp_read_mps(csa->prob, GLP_MPS_DECK, NULL,
  1071. csa->in_file);
  1072. if (ret != 0)
  1073. err1: { xprintf("MPS file processing error\n");
  1074. ret = EXIT_FAILURE;
  1075. goto done;
  1076. }
  1077. }
  1078. else if (csa->format == FMT_MPS_FILE)
  1079. { ret = glp_read_mps(csa->prob, GLP_MPS_FILE, NULL,
  1080. csa->in_file);
  1081. if (ret != 0) goto err1;
  1082. }
  1083. else if (csa->format == FMT_LP)
  1084. { ret = glp_read_lp(csa->prob, NULL, csa->in_file);
  1085. if (ret != 0)
  1086. { xprintf("CPLEX LP file processing error\n");
  1087. ret = EXIT_FAILURE;
  1088. goto done;
  1089. }
  1090. }
  1091. else if (csa->format == FMT_GLP)
  1092. { ret = glp_read_prob(csa->prob, 0, csa->in_file);
  1093. if (ret != 0)
  1094. { xprintf("GLPK LP/MIP file processing error\n");
  1095. ret = EXIT_FAILURE;
  1096. goto done;
  1097. }
  1098. }
  1099. else if (csa->format == FMT_MATHPROG)
  1100. { int k;
  1101. /* allocate the translator workspace */
  1102. csa->tran = glp_mpl_alloc_wksp();
  1103. /* set seed value */
  1104. if (csa->seed == 0x80000000)
  1105. #if 0 /* 10/VI-2013 */
  1106. { csa->seed = glp_time().lo;
  1107. #else
  1108. { csa->seed = (int)fmod(glp_time(), 1000000000.0);
  1109. #endif
  1110. xprintf("Seed value %d will be used\n", csa->seed);
  1111. }
  1112. glp_mpl_init_rand(csa->tran, csa->seed);
  1113. /* read model section and optional data section */
  1114. if (glp_mpl_read_model(csa->tran, csa->in_file, csa->ndf > 0))
  1115. err2: { xprintf("MathProg model processing error\n");
  1116. ret = EXIT_FAILURE;
  1117. goto done;
  1118. }
  1119. /* read optional data section(s), if necessary */
  1120. for (k = 1; k <= csa->ndf; k++)
  1121. { if (glp_mpl_read_data(csa->tran, csa->in_data[k]))
  1122. goto err2;
  1123. }
  1124. /* generate the model */
  1125. if (glp_mpl_generate(csa->tran, csa->out_dpy)) goto err2;
  1126. /* build the problem instance from the model */
  1127. glp_mpl_build_prob(csa->tran, csa->prob);
  1128. }
  1129. else if (csa->format == FMT_MIN_COST)
  1130. { csa->graph = glp_create_graph(sizeof(v_data), sizeof(a_data));
  1131. ret = glp_read_mincost(csa->graph, offsetof(v_data, rhs),
  1132. offsetof(a_data, low), offsetof(a_data, cap),
  1133. offsetof(a_data, cost), csa->in_file);
  1134. if (ret != 0)
  1135. { xprintf("DIMACS file processing error\n");
  1136. ret = EXIT_FAILURE;
  1137. goto done;
  1138. }
  1139. glp_mincost_lp(csa->prob, csa->graph, GLP_ON,
  1140. offsetof(v_data, rhs), offsetof(a_data, low),
  1141. offsetof(a_data, cap), offsetof(a_data, cost));
  1142. glp_set_prob_name(csa->prob, csa->in_file);
  1143. }
  1144. else if (csa->format == FMT_MAX_FLOW)
  1145. { int s, t;
  1146. csa->graph = glp_create_graph(sizeof(v_data), sizeof(a_data));
  1147. ret = glp_read_maxflow(csa->graph, &s, &t,
  1148. offsetof(a_data, cap), csa->in_file);
  1149. if (ret != 0)
  1150. { xprintf("DIMACS file processing error\n");
  1151. ret = EXIT_FAILURE;
  1152. goto done;
  1153. }
  1154. glp_maxflow_lp(csa->prob, csa->graph, GLP_ON, s, t,
  1155. offsetof(a_data, cap));
  1156. glp_set_prob_name(csa->prob, csa->in_file);
  1157. }
  1158. #if 1 /* 06/VIII-2011 */
  1159. else if (csa->format == FMT_CNF)
  1160. { ret = glp_read_cnfsat(csa->prob, csa->in_file);
  1161. if (ret != 0)
  1162. { xprintf("DIMACS file processing error\n");
  1163. ret = EXIT_FAILURE;
  1164. goto done;
  1165. }
  1166. glp_set_prob_name(csa->prob, csa->in_file);
  1167. }
  1168. #endif
  1169. else
  1170. xassert(csa != csa);
  1171. /*--------------------------------------------------------------*/
  1172. /* change problem name, if required */
  1173. if (csa->new_name != NULL)
  1174. glp_set_prob_name(csa->prob, csa->new_name);
  1175. /* change optimization direction, if required */
  1176. if (csa->dir != 0)
  1177. glp_set_obj_dir(csa->prob, csa->dir);
  1178. /* sort elements of the constraint matrix */
  1179. glp_sort_matrix(csa->prob);
  1180. #if 1 /* 18/I-2018 */
  1181. /*--------------------------------------------------------------*/
  1182. /* remove all symbolic names from problem object, if required */
  1183. if (csa->hide)
  1184. { int i, j;
  1185. glp_set_obj_name(csa->prob, NULL);
  1186. glp_delete_index(csa->prob);
  1187. for (i = glp_get_num_rows(csa->prob); i >= 1; i--)
  1188. glp_set_row_name(csa->prob, i, NULL);
  1189. for (j = glp_get_num_cols(csa->prob); j >= 1; j--)
  1190. glp_set_col_name(csa->prob, j, NULL);
  1191. }
  1192. #endif
  1193. /*--------------------------------------------------------------*/
  1194. /* write problem data in fixed MPS format, if required */
  1195. if (csa->out_mps != NULL)
  1196. { ret = glp_write_mps(csa->prob, GLP_MPS_DECK, NULL,
  1197. csa->out_mps);
  1198. if (ret != 0)
  1199. { xprintf("Unable to write problem in fixed MPS format\n");
  1200. ret = EXIT_FAILURE;
  1201. goto done;
  1202. }
  1203. }
  1204. /* write problem data in free MPS format, if required */
  1205. if (csa->out_freemps != NULL)
  1206. { ret = glp_write_mps(csa->prob, GLP_MPS_FILE, NULL,
  1207. csa->out_freemps);
  1208. if (ret != 0)
  1209. { xprintf("Unable to write problem in free MPS format\n");
  1210. ret = EXIT_FAILURE;
  1211. goto done;
  1212. }
  1213. }
  1214. /* write problem data in CPLEX LP format, if required */
  1215. if (csa->out_cpxlp != NULL)
  1216. { ret = glp_write_lp(csa->prob, NULL, csa->out_cpxlp);
  1217. if (ret != 0)
  1218. { xprintf("Unable to write problem in CPLEX LP format\n");
  1219. ret = EXIT_FAILURE;
  1220. goto done;
  1221. }
  1222. }
  1223. /* write problem data in GLPK format, if required */
  1224. if (csa->out_glp != NULL)
  1225. { ret = glp_write_prob(csa->prob, 0, csa->out_glp);
  1226. if (ret != 0)
  1227. { xprintf("Unable to write problem in GLPK format\n");
  1228. ret = EXIT_FAILURE;
  1229. goto done;
  1230. }
  1231. }
  1232. #if 0
  1233. /* write problem data in OPB format, if required */
  1234. if (csa->out_pb != NULL)
  1235. { ret = lpx_write_pb(csa->prob, csa->out_pb, 0, 0);
  1236. if (ret != 0)
  1237. { xprintf("Unable to write problem in OPB format\n");
  1238. ret = EXIT_FAILURE;
  1239. goto done;
  1240. }
  1241. }
  1242. /* write problem data in normalized OPB format, if required */
  1243. if (csa->out_npb != NULL)
  1244. { ret = lpx_write_pb(csa->prob, csa->out_npb, 1, 1);
  1245. if (ret != 0)
  1246. { xprintf(
  1247. "Unable to write problem in normalized OPB format\n");
  1248. ret = EXIT_FAILURE;
  1249. goto done;
  1250. }
  1251. }
  1252. #endif
  1253. #if 1 /* 06/VIII-2011 */
  1254. /* write problem data in DIMACS CNF-SAT format, if required */
  1255. if (csa->out_cnf != NULL)
  1256. { ret = glp_write_cnfsat(csa->prob, csa->out_cnf);
  1257. if (ret != 0)
  1258. { xprintf(
  1259. "Unable to write problem in DIMACS CNF-SAT format\n");
  1260. ret = EXIT_FAILURE;
  1261. goto done;
  1262. }
  1263. }
  1264. #endif
  1265. /*--------------------------------------------------------------*/
  1266. /* if only problem data check is required, skip computations */
  1267. if (csa->check)
  1268. {
  1269. #if 1 /* 29/III-2016 */
  1270. /* report problem characteristics */
  1271. int j, cnt = 0;
  1272. xprintf("--- Problem Characteristics ---\n");
  1273. xprintf("Number of rows = %8d\n",
  1274. glp_get_num_rows(csa->prob));
  1275. xprintf("Number of columns = %8d\n",
  1276. glp_get_num_cols(csa->prob));
  1277. xprintf("Number of non-zeros (matrix) = %8d\n",
  1278. glp_get_num_nz(csa->prob));
  1279. for (j = glp_get_num_cols(csa->prob); j >= 1; j--)
  1280. { if (glp_get_obj_coef(csa->prob, j) != 0.0)
  1281. cnt++;
  1282. }
  1283. xprintf("Number of non-zeros (objrow) = %8d\n",
  1284. cnt);
  1285. #endif
  1286. ret = EXIT_SUCCESS;
  1287. goto done;
  1288. }
  1289. /*--------------------------------------------------------------*/
  1290. /* determine the solution type */
  1291. if (!csa->nomip &&
  1292. glp_get_num_int(csa->prob) + glp_get_num_bin(csa->prob) > 0)
  1293. { if (csa->solution == SOL_INTERIOR)
  1294. { xprintf("Interior-point method is not able to solve MIP pro"
  1295. "blem; use --simplex\n");
  1296. ret = EXIT_FAILURE;
  1297. goto done;
  1298. }
  1299. csa->solution = SOL_INTEGER;
  1300. }
  1301. /*--------------------------------------------------------------*/
  1302. /* if solution is provided, read it and skip computations */
  1303. if (csa->in_res != NULL)
  1304. { if (csa->solution == SOL_BASIC)
  1305. ret = glp_read_sol(csa->prob, csa->in_res);
  1306. else if (csa->solution == SOL_INTERIOR)
  1307. ret = glp_read_ipt(csa->prob, csa->in_res);
  1308. else if (csa->solution == SOL_INTEGER)
  1309. ret = glp_read_mip(csa->prob, csa->in_res);
  1310. else
  1311. xassert(csa != csa);
  1312. if (ret != 0)
  1313. { xprintf("Unable to read problem solution\n");
  1314. ret = EXIT_FAILURE;
  1315. goto done;
  1316. }
  1317. goto skip;
  1318. }
  1319. #if 1 /* 11/VII-2013 */
  1320. /*--------------------------------------------------------------*/
  1321. /* if initial MIP solution is provided, read it */
  1322. if (csa->solution == SOL_INTEGER && csa->use_sol != NULL)
  1323. { ret = glp_read_mip(csa->prob, csa->use_sol);
  1324. if (ret != 0)
  1325. { xprintf("Unable to read initial MIP solution\n");
  1326. ret = EXIT_FAILURE;
  1327. goto done;
  1328. }
  1329. csa->iocp.use_sol = GLP_ON;
  1330. }
  1331. #endif
  1332. /*--------------------------------------------------------------*/
  1333. /* scale the problem data, if required */
  1334. if (csa->scale)
  1335. { if (csa->solution == SOL_BASIC && !csa->smcp.presolve ||
  1336. csa->solution == SOL_INTERIOR ||
  1337. csa->solution == SOL_INTEGER && !csa->iocp.presolve)
  1338. glp_scale_prob(csa->prob, GLP_SF_AUTO);
  1339. }
  1340. /*--------------------------------------------------------------*/
  1341. /* construct starting LP basis */
  1342. if (csa->solution == SOL_BASIC && !csa->smcp.presolve ||
  1343. csa->solution == SOL_INTEGER && !csa->iocp.presolve)
  1344. { if (csa->crash == USE_STD_BASIS)
  1345. glp_std_basis(csa->prob);
  1346. else if (csa->crash == USE_ADV_BASIS)
  1347. glp_adv_basis(csa->prob, 0);
  1348. else if (csa->crash == USE_CPX_BASIS)
  1349. glp_cpx_basis(csa->prob);
  1350. else if (csa->crash == USE_INI_BASIS)
  1351. { ret = glp_read_sol(csa->prob, csa->ini_file);
  1352. if (ret != 0)
  1353. { xprintf("Unable to read initial basis\n");
  1354. ret = EXIT_FAILURE;
  1355. goto done;
  1356. }
  1357. }
  1358. else
  1359. xassert(csa != csa);
  1360. }
  1361. /*--------------------------------------------------------------*/
  1362. /* solve the problem */
  1363. start = glp_time();
  1364. if (csa->solution == SOL_BASIC)
  1365. { if (!csa->exact)
  1366. { glp_set_bfcp(csa->prob, &csa->bfcp);
  1367. glp_simplex(csa->prob, &csa->smcp);
  1368. if (csa->xcheck)
  1369. { if (csa->smcp.presolve &&
  1370. glp_get_status(csa->prob) != GLP_OPT)
  1371. xprintf("If you need to check final basis for non-opt"
  1372. "imal solution, use --nopresol\n");
  1373. else
  1374. glp_exact(csa->prob, &csa->smcp);
  1375. }
  1376. if (csa->out_sol != NULL || csa->out_res != NULL)
  1377. { if (csa->smcp.presolve &&
  1378. glp_get_status(csa->prob) != GLP_OPT)
  1379. xprintf("If you need actual output for non-optimal solut"
  1380. "ion, use --nopresol\n");
  1381. }
  1382. }
  1383. else
  1384. glp_exact(csa->prob, &csa->smcp);
  1385. }
  1386. else if (csa->solution == SOL_INTERIOR)
  1387. glp_interior(csa->prob, &csa->iptcp);
  1388. #if 1 /* 15/VIII-2011 */
  1389. else if (csa->solution == SOL_INTEGER && csa->minisat)
  1390. { if (glp_check_cnfsat(csa->prob) == 0)
  1391. glp_minisat1(csa->prob);
  1392. else
  1393. glp_intfeas1(csa->prob, csa->use_bnd, csa->obj_bnd);
  1394. }
  1395. #endif
  1396. else if (csa->solution == SOL_INTEGER)
  1397. { glp_set_bfcp(csa->prob, &csa->bfcp);
  1398. if (!csa->iocp.presolve)
  1399. glp_simplex(csa->prob, &csa->smcp);
  1400. #if 0
  1401. csa->iocp.msg_lev = GLP_MSG_DBG;
  1402. csa->iocp.pp_tech = GLP_PP_NONE;
  1403. #endif
  1404. #ifdef GLP_CB_FUNC /* 05/IV-2016 */
  1405. { extern void GLP_CB_FUNC(glp_tree *, void *);
  1406. csa->iocp.cb_func = GLP_CB_FUNC;
  1407. csa->iocp.cb_info = NULL;
  1408. }
  1409. #endif
  1410. glp_intopt(csa->prob, &csa->iocp);
  1411. }
  1412. else
  1413. xassert(csa != csa);
  1414. /*--------------------------------------------------------------*/
  1415. /* display statistics */
  1416. xprintf("Time used: %.1f secs\n", glp_difftime(glp_time(),
  1417. start));
  1418. #if 0 /* 16/II-2012 */
  1419. { glp_long tpeak;
  1420. char buf[50];
  1421. glp_mem_usage(NULL, NULL, NULL, &tpeak);
  1422. xprintf("Memory used: %.1f Mb (%s bytes)\n",
  1423. xltod(tpeak) / 1048576.0, xltoa(tpeak, buf));
  1424. }
  1425. #else
  1426. { size_t tpeak;
  1427. glp_mem_usage(NULL, NULL, NULL, &tpeak);
  1428. xprintf("Memory used: %.1f Mb (%.0f bytes)\n",
  1429. (double)tpeak / 1048576.0, (double)tpeak);
  1430. }
  1431. #endif
  1432. /*--------------------------------------------------------------*/
  1433. skip: /* postsolve the model, if necessary */
  1434. if (csa->tran != NULL)
  1435. { if (csa->solution == SOL_BASIC)
  1436. { if (!(glp_get_status(csa->prob) == GLP_OPT ||
  1437. glp_get_status(csa->prob) == GLP_FEAS))
  1438. ret = -1;
  1439. else
  1440. ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_SOL);
  1441. }
  1442. else if (csa->solution == SOL_INTERIOR)
  1443. { if (!(glp_ipt_status(csa->prob) == GLP_OPT ||
  1444. glp_ipt_status(csa->prob) == GLP_FEAS))
  1445. ret = -1;
  1446. else
  1447. ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_IPT);
  1448. }
  1449. else if (csa->solution == SOL_INTEGER)
  1450. { if (!(glp_mip_status(csa->prob) == GLP_OPT ||
  1451. glp_mip_status(csa->prob) == GLP_FEAS))
  1452. ret = -1;
  1453. else
  1454. ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_MIP);
  1455. }
  1456. else
  1457. xassert(csa != csa);
  1458. if (ret > 0)
  1459. { xprintf("Model postsolving error\n");
  1460. ret = EXIT_FAILURE;
  1461. goto done;
  1462. }
  1463. }
  1464. /*--------------------------------------------------------------*/
  1465. /* write problem solution in printable format, if required */
  1466. if (csa->out_sol != NULL)
  1467. { if (csa->solution == SOL_BASIC)
  1468. ret = glp_print_sol(csa->prob, csa->out_sol);
  1469. else if (csa->solution == SOL_INTERIOR)
  1470. ret = glp_print_ipt(csa->prob, csa->out_sol);
  1471. else if (csa->solution == SOL_INTEGER)
  1472. ret = glp_print_mip(csa->prob, csa->out_sol);
  1473. else
  1474. xassert(csa != csa);
  1475. if (ret != 0)
  1476. { xprintf("Unable to write problem solution\n");
  1477. ret = EXIT_FAILURE;
  1478. goto done;
  1479. }
  1480. }
  1481. /* write problem solution in printable format, if required */
  1482. if (csa->out_res != NULL)
  1483. { if (csa->solution == SOL_BASIC)
  1484. ret = glp_write_sol(csa->prob, csa->out_res);
  1485. else if (csa->solution == SOL_INTERIOR)
  1486. ret = glp_write_ipt(csa->prob, csa->out_res);
  1487. else if (csa->solution == SOL_INTEGER)
  1488. ret = glp_write_mip(csa->prob, csa->out_res);
  1489. else
  1490. xassert(csa != csa);
  1491. if (ret != 0)
  1492. { xprintf("Unable to write problem solution\n");
  1493. ret = EXIT_FAILURE;
  1494. goto done;
  1495. }
  1496. }
  1497. /* write sensitivity analysis report, if required */
  1498. if (csa->out_ranges != NULL)
  1499. { if (csa->solution == SOL_BASIC)
  1500. { if (glp_get_status(csa->prob) == GLP_OPT)
  1501. { if (glp_bf_exists(csa->prob))
  1502. ranges: { ret = glp_print_ranges(csa->prob, 0, NULL, 0,
  1503. csa->out_ranges);
  1504. if (ret != 0)
  1505. { xprintf("Unable to write sensitivity analysis repo"
  1506. "rt\n");
  1507. ret = EXIT_FAILURE;
  1508. goto done;
  1509. }
  1510. }
  1511. else
  1512. { ret = glp_factorize(csa->prob);
  1513. if (ret == 0) goto ranges;
  1514. xprintf("Cannot produce sensitivity analysis report d"
  1515. "ue to error in basis factorization (glp_factorize"
  1516. " returned %d); try --nopresol\n", ret);
  1517. }
  1518. }
  1519. else
  1520. xprintf("Cannot produce sensitivity analysis report for "
  1521. "non-optimal basic solution\n");
  1522. }
  1523. else
  1524. xprintf("Cannot produce sensitivity analysis report for int"
  1525. "erior-point or MIP solution\n");
  1526. }
  1527. /*--------------------------------------------------------------*/
  1528. /* all seems to be ok */
  1529. ret = EXIT_SUCCESS;
  1530. /*--------------------------------------------------------------*/
  1531. done: /* delete the LP/MIP problem object */
  1532. if (csa->prob != NULL)
  1533. glp_delete_prob(csa->prob);
  1534. /* free the translator workspace, if necessary */
  1535. if (csa->tran != NULL)
  1536. glp_mpl_free_wksp(csa->tran);
  1537. /* delete the network problem object, if necessary */
  1538. if (csa->graph != NULL)
  1539. glp_delete_graph(csa->graph);
  1540. #if 0 /* 23/XI-2015 */
  1541. xassert(gmp_pool_count() == 0);
  1542. gmp_free_mem();
  1543. #endif
  1544. /* close log file, if necessary */
  1545. if (csa->log_file != NULL) glp_close_tee();
  1546. /* check that no memory blocks are still allocated */
  1547. #if 0 /* 16/II-2012 */
  1548. { int count;
  1549. glp_long total;
  1550. glp_mem_usage(&count, NULL, &total, NULL);
  1551. if (count != 0)
  1552. xerror("Error: %d memory block(s) were lost\n", count);
  1553. xassert(count == 0);
  1554. xassert(total.lo == 0 && total.hi == 0);
  1555. }
  1556. #else
  1557. { int count;
  1558. size_t total;
  1559. glp_mem_usage(&count, NULL, &total, NULL);
  1560. if (count != 0)
  1561. xerror("Error: %d memory block(s) were lost\n", count);
  1562. xassert(total == 0);
  1563. }
  1564. #endif
  1565. /* free the GLPK environment */
  1566. glp_free_env();
  1567. /* return to the control program */
  1568. return ret;
  1569. }
  1570. /* eof */