glpapi09.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742
  1. /* glpapi09.c (mixed integer programming routines) */
  2. /***********************************************************************
  3. * This code is part of GLPK (GNU Linear Programming Kit).
  4. *
  5. * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
  6. * 2009, 2010 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 "glpios.h"
  24. #include "glpnpp.h"
  25. /***********************************************************************
  26. * NAME
  27. *
  28. * glp_set_col_kind - set (change) column kind
  29. *
  30. * SYNOPSIS
  31. *
  32. * void glp_set_col_kind(glp_prob *mip, int j, int kind);
  33. *
  34. * DESCRIPTION
  35. *
  36. * The routine glp_set_col_kind sets (changes) the kind of j-th column
  37. * (structural variable) as specified by the parameter kind:
  38. *
  39. * GLP_CV - continuous variable;
  40. * GLP_IV - integer variable;
  41. * GLP_BV - binary variable. */
  42. void glp_set_col_kind(glp_prob *mip, int j, int kind)
  43. { GLPCOL *col;
  44. if (!(1 <= j && j <= mip->n))
  45. xerror("glp_set_col_kind: j = %d; column number out of range\n"
  46. , j);
  47. col = mip->col[j];
  48. switch (kind)
  49. { case GLP_CV:
  50. col->kind = GLP_CV;
  51. break;
  52. case GLP_IV:
  53. col->kind = GLP_IV;
  54. break;
  55. case GLP_BV:
  56. col->kind = GLP_IV;
  57. if (!(col->type == GLP_DB && col->lb == 0.0 && col->ub ==
  58. 1.0)) glp_set_col_bnds(mip, j, GLP_DB, 0.0, 1.0);
  59. break;
  60. default:
  61. xerror("glp_set_col_kind: j = %d; kind = %d; invalid column"
  62. " kind\n", j, kind);
  63. }
  64. return;
  65. }
  66. /***********************************************************************
  67. * NAME
  68. *
  69. * glp_get_col_kind - retrieve column kind
  70. *
  71. * SYNOPSIS
  72. *
  73. * int glp_get_col_kind(glp_prob *mip, int j);
  74. *
  75. * RETURNS
  76. *
  77. * The routine glp_get_col_kind returns the kind of j-th column, i.e.
  78. * the kind of corresponding structural variable, as follows:
  79. *
  80. * GLP_CV - continuous variable;
  81. * GLP_IV - integer variable;
  82. * GLP_BV - binary variable */
  83. int glp_get_col_kind(glp_prob *mip, int j)
  84. { GLPCOL *col;
  85. int kind;
  86. if (!(1 <= j && j <= mip->n))
  87. xerror("glp_get_col_kind: j = %d; column number out of range\n"
  88. , j);
  89. col = mip->col[j];
  90. kind = col->kind;
  91. switch (kind)
  92. { case GLP_CV:
  93. break;
  94. case GLP_IV:
  95. if (col->type == GLP_DB && col->lb == 0.0 && col->ub == 1.0)
  96. kind = GLP_BV;
  97. break;
  98. default:
  99. xassert(kind != kind);
  100. }
  101. return kind;
  102. }
  103. /***********************************************************************
  104. * NAME
  105. *
  106. * glp_get_num_int - retrieve number of integer columns
  107. *
  108. * SYNOPSIS
  109. *
  110. * int glp_get_num_int(glp_prob *mip);
  111. *
  112. * RETURNS
  113. *
  114. * The routine glp_get_num_int returns the current number of columns,
  115. * which are marked as integer. */
  116. int glp_get_num_int(glp_prob *mip)
  117. { GLPCOL *col;
  118. int j, count = 0;
  119. for (j = 1; j <= mip->n; j++)
  120. { col = mip->col[j];
  121. if (col->kind == GLP_IV) count++;
  122. }
  123. return count;
  124. }
  125. /***********************************************************************
  126. * NAME
  127. *
  128. * glp_get_num_bin - retrieve number of binary columns
  129. *
  130. * SYNOPSIS
  131. *
  132. * int glp_get_num_bin(glp_prob *mip);
  133. *
  134. * RETURNS
  135. *
  136. * The routine glp_get_num_bin returns the current number of columns,
  137. * which are marked as binary. */
  138. int glp_get_num_bin(glp_prob *mip)
  139. { GLPCOL *col;
  140. int j, count = 0;
  141. for (j = 1; j <= mip->n; j++)
  142. { col = mip->col[j];
  143. if (col->kind == GLP_IV && col->type == GLP_DB && col->lb ==
  144. 0.0 && col->ub == 1.0) count++;
  145. }
  146. return count;
  147. }
  148. /***********************************************************************
  149. * NAME
  150. *
  151. * glp_intopt - solve MIP problem with the branch-and-bound method
  152. *
  153. * SYNOPSIS
  154. *
  155. * int glp_intopt(glp_prob *P, const glp_iocp *parm);
  156. *
  157. * DESCRIPTION
  158. *
  159. * The routine glp_intopt is a driver to the MIP solver based on the
  160. * branch-and-bound method.
  161. *
  162. * On entry the problem object should contain optimal solution to LP
  163. * relaxation (which can be obtained with the routine glp_simplex).
  164. *
  165. * The MIP solver has a set of control parameters. Values of the control
  166. * parameters can be passed in a structure glp_iocp, which the parameter
  167. * parm points to.
  168. *
  169. * The parameter parm can be specified as NULL, in which case the MIP
  170. * solver uses default settings.
  171. *
  172. * RETURNS
  173. *
  174. * 0 The MIP problem instance has been successfully solved. This code
  175. * does not necessarily mean that the solver has found optimal
  176. * solution. It only means that the solution process was successful.
  177. *
  178. * GLP_EBOUND
  179. * Unable to start the search, because some double-bounded variables
  180. * have incorrect bounds or some integer variables have non-integer
  181. * (fractional) bounds.
  182. *
  183. * GLP_EROOT
  184. * Unable to start the search, because optimal basis for initial LP
  185. * relaxation is not provided.
  186. *
  187. * GLP_EFAIL
  188. * The search was prematurely terminated due to the solver failure.
  189. *
  190. * GLP_EMIPGAP
  191. * The search was prematurely terminated, because the relative mip
  192. * gap tolerance has been reached.
  193. *
  194. * GLP_ETMLIM
  195. * The search was prematurely terminated, because the time limit has
  196. * been exceeded.
  197. *
  198. * GLP_ENOPFS
  199. * The MIP problem instance has no primal feasible solution (only if
  200. * the MIP presolver is used).
  201. *
  202. * GLP_ENODFS
  203. * LP relaxation of the MIP problem instance has no dual feasible
  204. * solution (only if the MIP presolver is used).
  205. *
  206. * GLP_ESTOP
  207. * The search was prematurely terminated by application. */
  208. static int solve_mip(glp_prob *P, const glp_iocp *parm)
  209. { /* solve MIP directly without using the preprocessor */
  210. glp_tree *T;
  211. int ret;
  212. /* optimal basis to LP relaxation must be provided */
  213. if (glp_get_status(P) != GLP_OPT)
  214. { if (parm->msg_lev >= GLP_MSG_ERR)
  215. xprintf("glp_intopt: optimal basis to initial LP relaxation"
  216. " not provided\n");
  217. ret = GLP_EROOT;
  218. goto done;
  219. }
  220. /* it seems all is ok */
  221. if (parm->msg_lev >= GLP_MSG_ALL)
  222. xprintf("Integer optimization begins...\n");
  223. /* create the branch-and-bound tree */
  224. T = ios_create_tree(P, parm);
  225. /* solve the problem instance */
  226. ret = ios_driver(T);
  227. /* delete the branch-and-bound tree */
  228. ios_delete_tree(T);
  229. /* analyze exit code reported by the mip driver */
  230. if (ret == 0)
  231. { if (P->mip_stat == GLP_FEAS)
  232. { if (parm->msg_lev >= GLP_MSG_ALL)
  233. xprintf("INTEGER OPTIMAL SOLUTION FOUND\n");
  234. P->mip_stat = GLP_OPT;
  235. }
  236. else
  237. { if (parm->msg_lev >= GLP_MSG_ALL)
  238. xprintf("PROBLEM HAS NO INTEGER FEASIBLE SOLUTION\n");
  239. P->mip_stat = GLP_NOFEAS;
  240. }
  241. }
  242. else if (ret == GLP_EMIPGAP)
  243. { if (parm->msg_lev >= GLP_MSG_ALL)
  244. xprintf("RELATIVE MIP GAP TOLERANCE REACHED; SEARCH TERMINA"
  245. "TED\n");
  246. }
  247. else if (ret == GLP_ETMLIM)
  248. { if (parm->msg_lev >= GLP_MSG_ALL)
  249. xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n");
  250. }
  251. else if (ret == GLP_EFAIL)
  252. { if (parm->msg_lev >= GLP_MSG_ERR)
  253. xprintf("glp_intopt: cannot solve current LP relaxation\n");
  254. }
  255. else if (ret == GLP_ESTOP)
  256. { if (parm->msg_lev >= GLP_MSG_ALL)
  257. xprintf("SEARCH TERMINATED BY APPLICATION\n");
  258. }
  259. else
  260. xassert(ret != ret);
  261. done: return ret;
  262. }
  263. static int preprocess_and_solve_mip(glp_prob *P, const glp_iocp *parm)
  264. { /* solve MIP using the preprocessor */
  265. ENV *env = get_env_ptr();
  266. int term_out = env->term_out;
  267. NPP *npp;
  268. glp_prob *mip = NULL;
  269. glp_bfcp bfcp;
  270. glp_smcp smcp;
  271. int ret;
  272. if (parm->msg_lev >= GLP_MSG_ALL)
  273. xprintf("Preprocessing...\n");
  274. /* create preprocessor workspace */
  275. npp = npp_create_wksp();
  276. /* load original problem into the preprocessor workspace */
  277. npp_load_prob(npp, P, GLP_OFF, GLP_MIP, GLP_OFF);
  278. /* process MIP prior to applying the branch-and-bound method */
  279. if (!term_out || parm->msg_lev < GLP_MSG_ALL)
  280. env->term_out = GLP_OFF;
  281. else
  282. env->term_out = GLP_ON;
  283. ret = npp_integer(npp, parm);
  284. env->term_out = term_out;
  285. if (ret == 0)
  286. ;
  287. else if (ret == GLP_ENOPFS)
  288. { if (parm->msg_lev >= GLP_MSG_ALL)
  289. xprintf("PROBLEM HAS NO PRIMAL FEASIBLE SOLUTION\n");
  290. }
  291. else if (ret == GLP_ENODFS)
  292. { if (parm->msg_lev >= GLP_MSG_ALL)
  293. xprintf("LP RELAXATION HAS NO DUAL FEASIBLE SOLUTION\n");
  294. }
  295. else
  296. xassert(ret != ret);
  297. if (ret != 0) goto done;
  298. /* build transformed MIP */
  299. mip = glp_create_prob();
  300. npp_build_prob(npp, mip);
  301. /* if the transformed MIP is empty, it has empty solution, which
  302. is optimal */
  303. if (mip->m == 0 && mip->n == 0)
  304. { mip->mip_stat = GLP_OPT;
  305. mip->mip_obj = mip->c0;
  306. if (parm->msg_lev >= GLP_MSG_ALL)
  307. { xprintf("Objective value = %17.9e\n", mip->mip_obj);
  308. xprintf("INTEGER OPTIMAL SOLUTION FOUND BY MIP PREPROCESSOR"
  309. "\n");
  310. }
  311. goto post;
  312. }
  313. /* display some statistics */
  314. if (parm->msg_lev >= GLP_MSG_ALL)
  315. { int ni = glp_get_num_int(mip);
  316. int nb = glp_get_num_bin(mip);
  317. char s[50];
  318. xprintf("%d row%s, %d column%s, %d non-zero%s\n",
  319. mip->m, mip->m == 1 ? "" : "s", mip->n, mip->n == 1 ? "" :
  320. "s", mip->nnz, mip->nnz == 1 ? "" : "s");
  321. if (nb == 0)
  322. strcpy(s, "none of");
  323. else if (ni == 1 && nb == 1)
  324. strcpy(s, "");
  325. else if (nb == 1)
  326. strcpy(s, "one of");
  327. else if (nb == ni)
  328. strcpy(s, "all of");
  329. else
  330. sprintf(s, "%d of", nb);
  331. xprintf("%d integer variable%s, %s which %s binary\n",
  332. ni, ni == 1 ? "" : "s", s, nb == 1 ? "is" : "are");
  333. }
  334. /* inherit basis factorization control parameters */
  335. glp_get_bfcp(P, &bfcp);
  336. glp_set_bfcp(mip, &bfcp);
  337. /* scale the transformed problem */
  338. if (!term_out || parm->msg_lev < GLP_MSG_ALL)
  339. env->term_out = GLP_OFF;
  340. else
  341. env->term_out = GLP_ON;
  342. glp_scale_prob(mip,
  343. GLP_SF_GM | GLP_SF_EQ | GLP_SF_2N | GLP_SF_SKIP);
  344. env->term_out = term_out;
  345. /* build advanced initial basis */
  346. if (!term_out || parm->msg_lev < GLP_MSG_ALL)
  347. env->term_out = GLP_OFF;
  348. else
  349. env->term_out = GLP_ON;
  350. glp_adv_basis(mip, 0);
  351. env->term_out = term_out;
  352. /* solve initial LP relaxation */
  353. if (parm->msg_lev >= GLP_MSG_ALL)
  354. xprintf("Solving LP relaxation...\n");
  355. glp_init_smcp(&smcp);
  356. smcp.msg_lev = parm->msg_lev;
  357. mip->it_cnt = P->it_cnt;
  358. ret = glp_simplex(mip, &smcp);
  359. P->it_cnt = mip->it_cnt;
  360. if (ret != 0)
  361. { if (parm->msg_lev >= GLP_MSG_ERR)
  362. xprintf("glp_intopt: cannot solve LP relaxation\n");
  363. ret = GLP_EFAIL;
  364. goto done;
  365. }
  366. /* check status of the basic solution */
  367. ret = glp_get_status(mip);
  368. if (ret == GLP_OPT)
  369. ret = 0;
  370. else if (ret == GLP_NOFEAS)
  371. ret = GLP_ENOPFS;
  372. else if (ret == GLP_UNBND)
  373. ret = GLP_ENODFS;
  374. else
  375. xassert(ret != ret);
  376. if (ret != 0) goto done;
  377. /* solve the transformed MIP */
  378. mip->it_cnt = P->it_cnt;
  379. ret = solve_mip(mip, parm);
  380. P->it_cnt = mip->it_cnt;
  381. /* only integer feasible solution can be postprocessed */
  382. if (!(mip->mip_stat == GLP_OPT || mip->mip_stat == GLP_FEAS))
  383. { P->mip_stat = mip->mip_stat;
  384. goto done;
  385. }
  386. /* postprocess solution from the transformed MIP */
  387. post: npp_postprocess(npp, mip);
  388. /* the transformed MIP is no longer needed */
  389. glp_delete_prob(mip), mip = NULL;
  390. /* store solution to the original problem */
  391. npp_unload_sol(npp, P);
  392. done: /* delete the transformed MIP, if it exists */
  393. if (mip != NULL) glp_delete_prob(mip);
  394. /* delete preprocessor workspace */
  395. npp_delete_wksp(npp);
  396. return ret;
  397. }
  398. #ifndef HAVE_ALIEN_SOLVER /* 28/V-2010 */
  399. int _glp_intopt1(glp_prob *P, const glp_iocp *parm)
  400. { xassert(P == P);
  401. xassert(parm == parm);
  402. xprintf("glp_intopt: no alien solver is available\n");
  403. return GLP_EFAIL;
  404. }
  405. #endif
  406. int glp_intopt(glp_prob *P, const glp_iocp *parm)
  407. { /* solve MIP problem with the branch-and-bound method */
  408. glp_iocp _parm;
  409. int i, j, ret;
  410. /* check problem object */
  411. if (P == NULL || P->magic != GLP_PROB_MAGIC)
  412. xerror("glp_intopt: P = %p; invalid problem object\n", P);
  413. if (P->tree != NULL)
  414. xerror("glp_intopt: operation not allowed\n");
  415. /* check control parameters */
  416. if (parm == NULL)
  417. parm = &_parm, glp_init_iocp((glp_iocp *)parm);
  418. if (!(parm->msg_lev == GLP_MSG_OFF ||
  419. parm->msg_lev == GLP_MSG_ERR ||
  420. parm->msg_lev == GLP_MSG_ON ||
  421. parm->msg_lev == GLP_MSG_ALL ||
  422. parm->msg_lev == GLP_MSG_DBG))
  423. xerror("glp_intopt: msg_lev = %d; invalid parameter\n",
  424. parm->msg_lev);
  425. if (!(parm->br_tech == GLP_BR_FFV ||
  426. parm->br_tech == GLP_BR_LFV ||
  427. parm->br_tech == GLP_BR_MFV ||
  428. parm->br_tech == GLP_BR_DTH ||
  429. parm->br_tech == GLP_BR_PCH))
  430. xerror("glp_intopt: br_tech = %d; invalid parameter\n",
  431. parm->br_tech);
  432. if (!(parm->bt_tech == GLP_BT_DFS ||
  433. parm->bt_tech == GLP_BT_BFS ||
  434. parm->bt_tech == GLP_BT_BLB ||
  435. parm->bt_tech == GLP_BT_BPH))
  436. xerror("glp_intopt: bt_tech = %d; invalid parameter\n",
  437. parm->bt_tech);
  438. if (!(0.0 < parm->tol_int && parm->tol_int < 1.0))
  439. xerror("glp_intopt: tol_int = %g; invalid parameter\n",
  440. parm->tol_int);
  441. if (!(0.0 < parm->tol_obj && parm->tol_obj < 1.0))
  442. xerror("glp_intopt: tol_obj = %g; invalid parameter\n",
  443. parm->tol_obj);
  444. if (parm->tm_lim < 0)
  445. xerror("glp_intopt: tm_lim = %d; invalid parameter\n",
  446. parm->tm_lim);
  447. if (parm->out_frq < 0)
  448. xerror("glp_intopt: out_frq = %d; invalid parameter\n",
  449. parm->out_frq);
  450. if (parm->out_dly < 0)
  451. xerror("glp_intopt: out_dly = %d; invalid parameter\n",
  452. parm->out_dly);
  453. if (!(0 <= parm->cb_size && parm->cb_size <= 256))
  454. xerror("glp_intopt: cb_size = %d; invalid parameter\n",
  455. parm->cb_size);
  456. if (!(parm->pp_tech == GLP_PP_NONE ||
  457. parm->pp_tech == GLP_PP_ROOT ||
  458. parm->pp_tech == GLP_PP_ALL))
  459. xerror("glp_intopt: pp_tech = %d; invalid parameter\n",
  460. parm->pp_tech);
  461. if (parm->mip_gap < 0.0)
  462. xerror("glp_intopt: mip_gap = %g; invalid parameter\n",
  463. parm->mip_gap);
  464. if (!(parm->mir_cuts == GLP_ON || parm->mir_cuts == GLP_OFF))
  465. xerror("glp_intopt: mir_cuts = %d; invalid parameter\n",
  466. parm->mir_cuts);
  467. if (!(parm->gmi_cuts == GLP_ON || parm->gmi_cuts == GLP_OFF))
  468. xerror("glp_intopt: gmi_cuts = %d; invalid parameter\n",
  469. parm->gmi_cuts);
  470. if (!(parm->cov_cuts == GLP_ON || parm->cov_cuts == GLP_OFF))
  471. xerror("glp_intopt: cov_cuts = %d; invalid parameter\n",
  472. parm->cov_cuts);
  473. if (!(parm->clq_cuts == GLP_ON || parm->clq_cuts == GLP_OFF))
  474. xerror("glp_intopt: clq_cuts = %d; invalid parameter\n",
  475. parm->clq_cuts);
  476. if (!(parm->presolve == GLP_ON || parm->presolve == GLP_OFF))
  477. xerror("glp_intopt: presolve = %d; invalid parameter\n",
  478. parm->presolve);
  479. if (!(parm->binarize == GLP_ON || parm->binarize == GLP_OFF))
  480. xerror("glp_intopt: binarize = %d; invalid parameter\n",
  481. parm->binarize);
  482. if (!(parm->fp_heur == GLP_ON || parm->fp_heur == GLP_OFF))
  483. xerror("glp_intopt: fp_heur = %d; invalid parameter\n",
  484. parm->fp_heur);
  485. #if 1 /* 28/V-2010 */
  486. if (!(parm->alien == GLP_ON || parm->alien == GLP_OFF))
  487. xerror("glp_intopt: alien = %d; invalid parameter\n",
  488. parm->alien);
  489. #endif
  490. /* integer solution is currently undefined */
  491. P->mip_stat = GLP_UNDEF;
  492. P->mip_obj = 0.0;
  493. /* check bounds of double-bounded variables */
  494. for (i = 1; i <= P->m; i++)
  495. { GLPROW *row = P->row[i];
  496. if (row->type == GLP_DB && row->lb >= row->ub)
  497. { if (parm->msg_lev >= GLP_MSG_ERR)
  498. xprintf("glp_intopt: row %d: lb = %g, ub = %g; incorrect"
  499. " bounds\n", i, row->lb, row->ub);
  500. ret = GLP_EBOUND;
  501. goto done;
  502. }
  503. }
  504. for (j = 1; j <= P->n; j++)
  505. { GLPCOL *col = P->col[j];
  506. if (col->type == GLP_DB && col->lb >= col->ub)
  507. { if (parm->msg_lev >= GLP_MSG_ERR)
  508. xprintf("glp_intopt: column %d: lb = %g, ub = %g; incorr"
  509. "ect bounds\n", j, col->lb, col->ub);
  510. ret = GLP_EBOUND;
  511. goto done;
  512. }
  513. }
  514. /* bounds of all integer variables must be integral */
  515. for (j = 1; j <= P->n; j++)
  516. { GLPCOL *col = P->col[j];
  517. if (col->kind != GLP_IV) continue;
  518. if (col->type == GLP_LO || col->type == GLP_DB)
  519. { if (col->lb != floor(col->lb))
  520. { if (parm->msg_lev >= GLP_MSG_ERR)
  521. xprintf("glp_intopt: integer column %d has non-intege"
  522. "r lower bound %g\n", j, col->lb);
  523. ret = GLP_EBOUND;
  524. goto done;
  525. }
  526. }
  527. if (col->type == GLP_UP || col->type == GLP_DB)
  528. { if (col->ub != floor(col->ub))
  529. { if (parm->msg_lev >= GLP_MSG_ERR)
  530. xprintf("glp_intopt: integer column %d has non-intege"
  531. "r upper bound %g\n", j, col->ub);
  532. ret = GLP_EBOUND;
  533. goto done;
  534. }
  535. }
  536. if (col->type == GLP_FX)
  537. { if (col->lb != floor(col->lb))
  538. { if (parm->msg_lev >= GLP_MSG_ERR)
  539. xprintf("glp_intopt: integer column %d has non-intege"
  540. "r fixed value %g\n", j, col->lb);
  541. ret = GLP_EBOUND;
  542. goto done;
  543. }
  544. }
  545. }
  546. /* solve MIP problem */
  547. if (parm->msg_lev >= GLP_MSG_ALL)
  548. { int ni = glp_get_num_int(P);
  549. int nb = glp_get_num_bin(P);
  550. char s[50];
  551. xprintf("GLPK Integer Optimizer, v%s\n", glp_version());
  552. xprintf("%d row%s, %d column%s, %d non-zero%s\n",
  553. P->m, P->m == 1 ? "" : "s", P->n, P->n == 1 ? "" : "s",
  554. P->nnz, P->nnz == 1 ? "" : "s");
  555. if (nb == 0)
  556. strcpy(s, "none of");
  557. else if (ni == 1 && nb == 1)
  558. strcpy(s, "");
  559. else if (nb == 1)
  560. strcpy(s, "one of");
  561. else if (nb == ni)
  562. strcpy(s, "all of");
  563. else
  564. sprintf(s, "%d of", nb);
  565. xprintf("%d integer variable%s, %s which %s binary\n",
  566. ni, ni == 1 ? "" : "s", s, nb == 1 ? "is" : "are");
  567. }
  568. #if 1 /* 28/V-2010 */
  569. if (parm->alien)
  570. { /* use alien integer optimizer */
  571. ret = _glp_intopt1(P, parm);
  572. goto done;
  573. }
  574. #endif
  575. if (!parm->presolve)
  576. ret = solve_mip(P, parm);
  577. else
  578. ret = preprocess_and_solve_mip(P, parm);
  579. done: /* return to the application program */
  580. return ret;
  581. }
  582. /***********************************************************************
  583. * NAME
  584. *
  585. * glp_init_iocp - initialize integer optimizer control parameters
  586. *
  587. * SYNOPSIS
  588. *
  589. * void glp_init_iocp(glp_iocp *parm);
  590. *
  591. * DESCRIPTION
  592. *
  593. * The routine glp_init_iocp initializes control parameters, which are
  594. * used by the integer optimizer, with default values.
  595. *
  596. * Default values of the control parameters are stored in a glp_iocp
  597. * structure, which the parameter parm points to. */
  598. void glp_init_iocp(glp_iocp *parm)
  599. { parm->msg_lev = GLP_MSG_ALL;
  600. parm->br_tech = GLP_BR_DTH;
  601. parm->bt_tech = GLP_BT_BLB;
  602. parm->tol_int = 1e-5;
  603. parm->tol_obj = 1e-7;
  604. parm->tm_lim = INT_MAX;
  605. parm->out_frq = 5000;
  606. parm->out_dly = 10000;
  607. parm->cb_func = NULL;
  608. parm->cb_info = NULL;
  609. parm->cb_size = 0;
  610. parm->pp_tech = GLP_PP_ALL;
  611. parm->mip_gap = 0.0;
  612. parm->mir_cuts = GLP_OFF;
  613. parm->gmi_cuts = GLP_OFF;
  614. parm->cov_cuts = GLP_OFF;
  615. parm->clq_cuts = GLP_OFF;
  616. parm->presolve = GLP_OFF;
  617. parm->binarize = GLP_OFF;
  618. parm->fp_heur = GLP_OFF;
  619. #if 1 /* 28/V-2010 */
  620. parm->alien = GLP_OFF;
  621. #endif
  622. return;
  623. }
  624. /***********************************************************************
  625. * NAME
  626. *
  627. * glp_mip_status - retrieve status of MIP solution
  628. *
  629. * SYNOPSIS
  630. *
  631. * int glp_mip_status(glp_prob *mip);
  632. *
  633. * RETURNS
  634. *
  635. * The routine lpx_mip_status reports the status of MIP solution found
  636. * by the branch-and-bound solver as follows:
  637. *
  638. * GLP_UNDEF - MIP solution is undefined;
  639. * GLP_OPT - MIP solution is integer optimal;
  640. * GLP_FEAS - MIP solution is integer feasible but its optimality
  641. * (or non-optimality) has not been proven, perhaps due to
  642. * premature termination of the search;
  643. * GLP_NOFEAS - problem has no integer feasible solution (proven by the
  644. * solver). */
  645. int glp_mip_status(glp_prob *mip)
  646. { int mip_stat = mip->mip_stat;
  647. return mip_stat;
  648. }
  649. /***********************************************************************
  650. * NAME
  651. *
  652. * glp_mip_obj_val - retrieve objective value (MIP solution)
  653. *
  654. * SYNOPSIS
  655. *
  656. * double glp_mip_obj_val(glp_prob *mip);
  657. *
  658. * RETURNS
  659. *
  660. * The routine glp_mip_obj_val returns value of the objective function
  661. * for MIP solution. */
  662. double glp_mip_obj_val(glp_prob *mip)
  663. { /*struct LPXCPS *cps = mip->cps;*/
  664. double z;
  665. z = mip->mip_obj;
  666. /*if (cps->round && fabs(z) < 1e-9) z = 0.0;*/
  667. return z;
  668. }
  669. /***********************************************************************
  670. * NAME
  671. *
  672. * glp_mip_row_val - retrieve row value (MIP solution)
  673. *
  674. * SYNOPSIS
  675. *
  676. * double glp_mip_row_val(glp_prob *mip, int i);
  677. *
  678. * RETURNS
  679. *
  680. * The routine glp_mip_row_val returns value of the auxiliary variable
  681. * associated with i-th row. */
  682. double glp_mip_row_val(glp_prob *mip, int i)
  683. { /*struct LPXCPS *cps = mip->cps;*/
  684. double mipx;
  685. if (!(1 <= i && i <= mip->m))
  686. xerror("glp_mip_row_val: i = %d; row number out of range\n", i)
  687. ;
  688. mipx = mip->row[i]->mipx;
  689. /*if (cps->round && fabs(mipx) < 1e-9) mipx = 0.0;*/
  690. return mipx;
  691. }
  692. /***********************************************************************
  693. * NAME
  694. *
  695. * glp_mip_col_val - retrieve column value (MIP solution)
  696. *
  697. * SYNOPSIS
  698. *
  699. * double glp_mip_col_val(glp_prob *mip, int j);
  700. *
  701. * RETURNS
  702. *
  703. * The routine glp_mip_col_val returns value of the structural variable
  704. * associated with j-th column. */
  705. double glp_mip_col_val(glp_prob *mip, int j)
  706. { /*struct LPXCPS *cps = mip->cps;*/
  707. double mipx;
  708. if (!(1 <= j && j <= mip->n))
  709. xerror("glp_mip_col_val: j = %d; column number out of range\n",
  710. j);
  711. mipx = mip->col[j]->mipx;
  712. /*if (cps->round && fabs(mipx) < 1e-9) mipx = 0.0;*/
  713. return mipx;
  714. }
  715. /* eof */