glpapi19.c 45 KB

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