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.

1462 lines
53 KiB

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