glpios10.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. /* glpios10.c (feasibility pump heuristic) */
  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 "glprng.h"
  25. /***********************************************************************
  26. * NAME
  27. *
  28. * ios_feas_pump - feasibility pump heuristic
  29. *
  30. * SYNOPSIS
  31. *
  32. * #include "glpios.h"
  33. * void ios_feas_pump(glp_tree *T);
  34. *
  35. * DESCRIPTION
  36. *
  37. * The routine ios_feas_pump is a simple implementation of the Feasi-
  38. * bility Pump heuristic.
  39. *
  40. * REFERENCES
  41. *
  42. * M.Fischetti, F.Glover, and A.Lodi. "The feasibility pump." Math.
  43. * Program., Ser. A 104, pp. 91-104 (2005). */
  44. struct VAR
  45. { /* binary variable */
  46. int j;
  47. /* ordinal number */
  48. int x;
  49. /* value in the rounded solution (0 or 1) */
  50. double d;
  51. /* sorting key */
  52. };
  53. static int fcmp(const void *x, const void *y)
  54. { /* comparison routine */
  55. const struct VAR *vx = x, *vy = y;
  56. if (vx->d > vy->d)
  57. return -1;
  58. else if (vx->d < vy->d)
  59. return +1;
  60. else
  61. return 0;
  62. }
  63. void ios_feas_pump(glp_tree *T)
  64. { glp_prob *P = T->mip;
  65. int n = P->n;
  66. glp_prob *lp = NULL;
  67. struct VAR *var = NULL;
  68. RNG *rand = NULL;
  69. GLPCOL *col;
  70. glp_smcp parm;
  71. int j, k, new_x, nfail, npass, nv, ret, stalling;
  72. double dist, tol;
  73. xassert(glp_get_status(P) == GLP_OPT);
  74. /* this heuristic is applied only once on the root level */
  75. if (!(T->curr->level == 0 && T->curr->solved == 1)) goto done;
  76. /* determine number of binary variables */
  77. nv = 0;
  78. for (j = 1; j <= n; j++)
  79. { col = P->col[j];
  80. /* if x[j] is continuous, skip it */
  81. if (col->kind == GLP_CV) continue;
  82. /* if x[j] is fixed, skip it */
  83. if (col->type == GLP_FX) continue;
  84. /* x[j] is non-fixed integer */
  85. xassert(col->kind == GLP_IV);
  86. if (col->type == GLP_DB && col->lb == 0.0 && col->ub == 1.0)
  87. { /* x[j] is binary */
  88. nv++;
  89. }
  90. else
  91. { /* x[j] is general integer */
  92. if (T->parm->msg_lev >= GLP_MSG_ALL)
  93. xprintf("FPUMP heuristic cannot be applied due to genera"
  94. "l integer variables\n");
  95. goto done;
  96. }
  97. }
  98. /* there must be at least one binary variable */
  99. if (nv == 0) goto done;
  100. if (T->parm->msg_lev >= GLP_MSG_ALL)
  101. xprintf("Applying FPUMP heuristic...\n");
  102. /* build the list of binary variables */
  103. var = xcalloc(1+nv, sizeof(struct VAR));
  104. k = 0;
  105. for (j = 1; j <= n; j++)
  106. { col = P->col[j];
  107. if (col->kind == GLP_IV && col->type == GLP_DB)
  108. var[++k].j = j;
  109. }
  110. xassert(k == nv);
  111. /* create working problem object */
  112. lp = glp_create_prob();
  113. more: /* copy the original problem object to keep it intact */
  114. glp_copy_prob(lp, P, GLP_OFF);
  115. /* we are interested to find an integer feasible solution, which
  116. is better than the best known one */
  117. if (P->mip_stat == GLP_FEAS)
  118. { int *ind;
  119. double *val, bnd;
  120. /* add a row and make it identical to the objective row */
  121. glp_add_rows(lp, 1);
  122. ind = xcalloc(1+n, sizeof(int));
  123. val = xcalloc(1+n, sizeof(double));
  124. for (j = 1; j <= n; j++)
  125. { ind[j] = j;
  126. val[j] = P->col[j]->coef;
  127. }
  128. glp_set_mat_row(lp, lp->m, n, ind, val);
  129. xfree(ind);
  130. xfree(val);
  131. /* introduce upper (minimization) or lower (maximization)
  132. bound to the original objective function; note that this
  133. additional constraint is not violated at the optimal point
  134. to LP relaxation */
  135. #if 0 /* modified by xypron <xypron.glpk@gmx.de> */
  136. if (P->dir == GLP_MIN)
  137. { bnd = P->mip_obj - 0.10 * (1.0 + fabs(P->mip_obj));
  138. if (bnd < P->obj_val) bnd = P->obj_val;
  139. glp_set_row_bnds(lp, lp->m, GLP_UP, 0.0, bnd - P->c0);
  140. }
  141. else if (P->dir == GLP_MAX)
  142. { bnd = P->mip_obj + 0.10 * (1.0 + fabs(P->mip_obj));
  143. if (bnd > P->obj_val) bnd = P->obj_val;
  144. glp_set_row_bnds(lp, lp->m, GLP_LO, bnd - P->c0, 0.0);
  145. }
  146. else
  147. xassert(P != P);
  148. #else
  149. bnd = 0.1 * P->obj_val + 0.9 * P->mip_obj;
  150. /* xprintf("bnd = %f\n", bnd); */
  151. if (P->dir == GLP_MIN)
  152. glp_set_row_bnds(lp, lp->m, GLP_UP, 0.0, bnd - P->c0);
  153. else if (P->dir == GLP_MAX)
  154. glp_set_row_bnds(lp, lp->m, GLP_LO, bnd - P->c0, 0.0);
  155. else
  156. xassert(P != P);
  157. #endif
  158. }
  159. /* reset pass count */
  160. npass = 0;
  161. /* invalidate the rounded point */
  162. for (k = 1; k <= nv; k++)
  163. var[k].x = -1;
  164. pass: /* next pass starts here */
  165. npass++;
  166. if (T->parm->msg_lev >= GLP_MSG_ALL)
  167. xprintf("Pass %d\n", npass);
  168. /* initialize minimal distance between the basic point and the
  169. rounded one obtained during this pass */
  170. dist = DBL_MAX;
  171. /* reset failure count (the number of succeeded iterations failed
  172. to improve the distance) */
  173. nfail = 0;
  174. /* if it is not the first pass, perturb the last rounded point
  175. rather than construct it from the basic solution */
  176. if (npass > 1)
  177. { double rho, temp;
  178. if (rand == NULL)
  179. rand = rng_create_rand();
  180. for (k = 1; k <= nv; k++)
  181. { j = var[k].j;
  182. col = lp->col[j];
  183. rho = rng_uniform(rand, -0.3, 0.7);
  184. if (rho < 0.0) rho = 0.0;
  185. temp = fabs((double)var[k].x - col->prim);
  186. if (temp + rho > 0.5) var[k].x = 1 - var[k].x;
  187. }
  188. goto skip;
  189. }
  190. loop: /* innermost loop begins here */
  191. /* round basic solution (which is assumed primal feasible) */
  192. stalling = 1;
  193. for (k = 1; k <= nv; k++)
  194. { col = lp->col[var[k].j];
  195. if (col->prim < 0.5)
  196. { /* rounded value is 0 */
  197. new_x = 0;
  198. }
  199. else
  200. { /* rounded value is 1 */
  201. new_x = 1;
  202. }
  203. if (var[k].x != new_x)
  204. { stalling = 0;
  205. var[k].x = new_x;
  206. }
  207. }
  208. /* if the rounded point has not changed (stalling), choose and
  209. flip some its entries heuristically */
  210. if (stalling)
  211. { /* compute d[j] = |x[j] - round(x[j])| */
  212. for (k = 1; k <= nv; k++)
  213. { col = lp->col[var[k].j];
  214. var[k].d = fabs(col->prim - (double)var[k].x);
  215. }
  216. /* sort the list of binary variables by descending d[j] */
  217. qsort(&var[1], nv, sizeof(struct VAR), fcmp);
  218. /* choose and flip some rounded components */
  219. for (k = 1; k <= nv; k++)
  220. { if (k >= 5 && var[k].d < 0.35 || k >= 10) break;
  221. var[k].x = 1 - var[k].x;
  222. }
  223. }
  224. skip: /* check if the time limit has been exhausted */
  225. if (T->parm->tm_lim < INT_MAX &&
  226. (double)(T->parm->tm_lim - 1) <=
  227. 1000.0 * xdifftime(xtime(), T->tm_beg)) goto done;
  228. /* build the objective, which is the distance between the current
  229. (basic) point and the rounded one */
  230. lp->dir = GLP_MIN;
  231. lp->c0 = 0.0;
  232. for (j = 1; j <= n; j++)
  233. lp->col[j]->coef = 0.0;
  234. for (k = 1; k <= nv; k++)
  235. { j = var[k].j;
  236. if (var[k].x == 0)
  237. lp->col[j]->coef = +1.0;
  238. else
  239. { lp->col[j]->coef = -1.0;
  240. lp->c0 += 1.0;
  241. }
  242. }
  243. /* minimize the distance with the simplex method */
  244. glp_init_smcp(&parm);
  245. if (T->parm->msg_lev <= GLP_MSG_ERR)
  246. parm.msg_lev = T->parm->msg_lev;
  247. else if (T->parm->msg_lev <= GLP_MSG_ALL)
  248. { parm.msg_lev = GLP_MSG_ON;
  249. parm.out_dly = 10000;
  250. }
  251. ret = glp_simplex(lp, &parm);
  252. if (ret != 0)
  253. { if (T->parm->msg_lev >= GLP_MSG_ERR)
  254. xprintf("Warning: glp_simplex returned %d\n", ret);
  255. goto done;
  256. }
  257. ret = glp_get_status(lp);
  258. if (ret != GLP_OPT)
  259. { if (T->parm->msg_lev >= GLP_MSG_ERR)
  260. xprintf("Warning: glp_get_status returned %d\n", ret);
  261. goto done;
  262. }
  263. if (T->parm->msg_lev >= GLP_MSG_DBG)
  264. xprintf("delta = %g\n", lp->obj_val);
  265. /* check if the basic solution is integer feasible; note that it
  266. may be so even if the minimial distance is positive */
  267. tol = 0.3 * T->parm->tol_int;
  268. for (k = 1; k <= nv; k++)
  269. { col = lp->col[var[k].j];
  270. if (tol < col->prim && col->prim < 1.0 - tol) break;
  271. }
  272. if (k > nv)
  273. { /* okay; the basic solution seems to be integer feasible */
  274. double *x = xcalloc(1+n, sizeof(double));
  275. for (j = 1; j <= n; j++)
  276. { x[j] = lp->col[j]->prim;
  277. if (P->col[j]->kind == GLP_IV) x[j] = floor(x[j] + 0.5);
  278. }
  279. #if 1 /* modified by xypron <xypron.glpk@gmx.de> */
  280. /* reset direction and right-hand side of objective */
  281. lp->c0 = P->c0;
  282. lp->dir = P->dir;
  283. /* fix integer variables */
  284. for (k = 1; k <= nv; k++)
  285. { lp->col[var[k].j]->lb = x[var[k].j];
  286. lp->col[var[k].j]->ub = x[var[k].j];
  287. lp->col[var[k].j]->type = GLP_FX;
  288. }
  289. /* copy original objective function */
  290. for (j = 1; j <= n; j++)
  291. lp->col[j]->coef = P->col[j]->coef;
  292. /* solve original LP and copy result */
  293. ret = glp_simplex(lp, &parm);
  294. if (ret != 0)
  295. { if (T->parm->msg_lev >= GLP_MSG_ERR)
  296. xprintf("Warning: glp_simplex returned %d\n", ret);
  297. goto done;
  298. }
  299. ret = glp_get_status(lp);
  300. if (ret != GLP_OPT)
  301. { if (T->parm->msg_lev >= GLP_MSG_ERR)
  302. xprintf("Warning: glp_get_status returned %d\n", ret);
  303. goto done;
  304. }
  305. for (j = 1; j <= n; j++)
  306. if (P->col[j]->kind != GLP_IV) x[j] = lp->col[j]->prim;
  307. #endif
  308. ret = glp_ios_heur_sol(T, x);
  309. xfree(x);
  310. if (ret == 0)
  311. { /* the integer solution is accepted */
  312. if (ios_is_hopeful(T, T->curr->bound))
  313. { /* it is reasonable to apply the heuristic once again */
  314. goto more;
  315. }
  316. else
  317. { /* the best known integer feasible solution just found
  318. is close to optimal solution to LP relaxation */
  319. goto done;
  320. }
  321. }
  322. }
  323. /* the basic solution is fractional */
  324. if (dist == DBL_MAX ||
  325. lp->obj_val <= dist - 1e-6 * (1.0 + dist))
  326. { /* the distance is reducing */
  327. nfail = 0, dist = lp->obj_val;
  328. }
  329. else
  330. { /* improving the distance failed */
  331. nfail++;
  332. }
  333. if (nfail < 3) goto loop;
  334. if (npass < 5) goto pass;
  335. done: /* delete working objects */
  336. if (lp != NULL) glp_delete_prob(lp);
  337. if (var != NULL) xfree(var);
  338. if (rand != NULL) rng_delete_rand(rand);
  339. return;
  340. }
  341. /* eof */