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.

1448 lines
48 KiB

  1. /* glpios06.c (MIR cut generator) */
  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 "env.h"
  24. #include "glpios.h"
  25. #define _MIR_DEBUG 0
  26. #define MAXAGGR 5
  27. /* maximal number of rows which can be aggregated */
  28. struct MIR
  29. { /* MIR cut generator working area */
  30. /*--------------------------------------------------------------*/
  31. /* global information valid for the root subproblem */
  32. int m;
  33. /* number of rows (in the root subproblem) */
  34. int n;
  35. /* number of columns */
  36. char *skip; /* char skip[1+m]; */
  37. /* skip[i], 1 <= i <= m, is a flag that means that row i should
  38. not be used because (1) it is not suitable, or (2) because it
  39. has been used in the aggregated constraint */
  40. char *isint; /* char isint[1+m+n]; */
  41. /* isint[k], 1 <= k <= m+n, is a flag that means that variable
  42. x[k] is integer (otherwise, continuous) */
  43. double *lb; /* double lb[1+m+n]; */
  44. /* lb[k], 1 <= k <= m+n, is lower bound of x[k]; -DBL_MAX means
  45. that x[k] has no lower bound */
  46. int *vlb; /* int vlb[1+m+n]; */
  47. /* vlb[k] = k', 1 <= k <= m+n, is the number of integer variable,
  48. which defines variable lower bound x[k] >= lb[k] * x[k']; zero
  49. means that x[k] has simple lower bound */
  50. double *ub; /* double ub[1+m+n]; */
  51. /* ub[k], 1 <= k <= m+n, is upper bound of x[k]; +DBL_MAX means
  52. that x[k] has no upper bound */
  53. int *vub; /* int vub[1+m+n]; */
  54. /* vub[k] = k', 1 <= k <= m+n, is the number of integer variable,
  55. which defines variable upper bound x[k] <= ub[k] * x[k']; zero
  56. means that x[k] has simple upper bound */
  57. /*--------------------------------------------------------------*/
  58. /* current (fractional) point to be separated */
  59. double *x; /* double x[1+m+n]; */
  60. /* x[k] is current value of auxiliary (1 <= k <= m) or structural
  61. (m+1 <= k <= m+n) variable */
  62. /*--------------------------------------------------------------*/
  63. /* aggregated constraint sum a[k] * x[k] = b, which is a linear
  64. combination of original constraints transformed to equalities
  65. by introducing auxiliary variables */
  66. int agg_cnt;
  67. /* number of rows (original constraints) used to build aggregated
  68. constraint, 1 <= agg_cnt <= MAXAGGR */
  69. int *agg_row; /* int agg_row[1+MAXAGGR]; */
  70. /* agg_row[k], 1 <= k <= agg_cnt, is the row number used to build
  71. aggregated constraint */
  72. IOSVEC *agg_vec; /* IOSVEC agg_vec[1:m+n]; */
  73. /* sparse vector of aggregated constraint coefficients, a[k] */
  74. double agg_rhs;
  75. /* right-hand side of the aggregated constraint, b */
  76. /*--------------------------------------------------------------*/
  77. /* bound substitution flags for modified constraint */
  78. char *subst; /* char subst[1+m+n]; */
  79. /* subst[k], 1 <= k <= m+n, is a bound substitution flag used for
  80. variable x[k]:
  81. '?' - x[k] is missing in modified constraint
  82. 'L' - x[k] = (lower bound) + x'[k]
  83. 'U' - x[k] = (upper bound) - x'[k] */
  84. /*--------------------------------------------------------------*/
  85. /* modified constraint sum a'[k] * x'[k] = b', where x'[k] >= 0,
  86. derived from aggregated constraint by substituting bounds;
  87. note that due to substitution of variable bounds there may be
  88. additional terms in the modified constraint */
  89. IOSVEC *mod_vec; /* IOSVEC mod_vec[1:m+n]; */
  90. /* sparse vector of modified constraint coefficients, a'[k] */
  91. double mod_rhs;
  92. /* right-hand side of the modified constraint, b' */
  93. /*--------------------------------------------------------------*/
  94. /* cutting plane sum alpha[k] * x[k] <= beta */
  95. IOSVEC *cut_vec; /* IOSVEC cut_vec[1:m+n]; */
  96. /* sparse vector of cutting plane coefficients, alpha[k] */
  97. double cut_rhs;
  98. /* right-hand size of the cutting plane, beta */
  99. };
  100. /***********************************************************************
  101. * NAME
  102. *
  103. * ios_mir_init - initialize MIR cut generator
  104. *
  105. * SYNOPSIS
  106. *
  107. * #include "glpios.h"
  108. * void *ios_mir_init(glp_tree *tree);
  109. *
  110. * DESCRIPTION
  111. *
  112. * The routine ios_mir_init initializes the MIR cut generator assuming
  113. * that the current subproblem is the root subproblem.
  114. *
  115. * RETURNS
  116. *
  117. * The routine ios_mir_init returns a pointer to the MIR cut generator
  118. * working area. */
  119. static void set_row_attrib(glp_tree *tree, struct MIR *mir)
  120. { /* set global row attributes */
  121. glp_prob *mip = tree->mip;
  122. int m = mir->m;
  123. int k;
  124. for (k = 1; k <= m; k++)
  125. { GLPROW *row = mip->row[k];
  126. mir->skip[k] = 0;
  127. mir->isint[k] = 0;
  128. switch (row->type)
  129. { case GLP_FR:
  130. mir->lb[k] = -DBL_MAX, mir->ub[k] = +DBL_MAX; break;
  131. case GLP_LO:
  132. mir->lb[k] = row->lb, mir->ub[k] = +DBL_MAX; break;
  133. case GLP_UP:
  134. mir->lb[k] = -DBL_MAX, mir->ub[k] = row->ub; break;
  135. case GLP_DB:
  136. mir->lb[k] = row->lb, mir->ub[k] = row->ub; break;
  137. case GLP_FX:
  138. mir->lb[k] = mir->ub[k] = row->lb; break;
  139. default:
  140. xassert(row != row);
  141. }
  142. mir->vlb[k] = mir->vub[k] = 0;
  143. }
  144. return;
  145. }
  146. static void set_col_attrib(glp_tree *tree, struct MIR *mir)
  147. { /* set global column attributes */
  148. glp_prob *mip = tree->mip;
  149. int m = mir->m;
  150. int n = mir->n;
  151. int k;
  152. for (k = m+1; k <= m+n; k++)
  153. { GLPCOL *col = mip->col[k-m];
  154. switch (col->kind)
  155. { case GLP_CV:
  156. mir->isint[k] = 0; break;
  157. case GLP_IV:
  158. mir->isint[k] = 1; break;
  159. default:
  160. xassert(col != col);
  161. }
  162. switch (col->type)
  163. { case GLP_FR:
  164. mir->lb[k] = -DBL_MAX, mir->ub[k] = +DBL_MAX; break;
  165. case GLP_LO:
  166. mir->lb[k] = col->lb, mir->ub[k] = +DBL_MAX; break;
  167. case GLP_UP:
  168. mir->lb[k] = -DBL_MAX, mir->ub[k] = col->ub; break;
  169. case GLP_DB:
  170. mir->lb[k] = col->lb, mir->ub[k] = col->ub; break;
  171. case GLP_FX:
  172. mir->lb[k] = mir->ub[k] = col->lb; break;
  173. default:
  174. xassert(col != col);
  175. }
  176. mir->vlb[k] = mir->vub[k] = 0;
  177. }
  178. return;
  179. }
  180. static void set_var_bounds(glp_tree *tree, struct MIR *mir)
  181. { /* set variable bounds */
  182. glp_prob *mip = tree->mip;
  183. int m = mir->m;
  184. GLPAIJ *aij;
  185. int i, k1, k2;
  186. double a1, a2;
  187. for (i = 1; i <= m; i++)
  188. { /* we need the row to be '>= 0' or '<= 0' */
  189. if (!(mir->lb[i] == 0.0 && mir->ub[i] == +DBL_MAX ||
  190. mir->lb[i] == -DBL_MAX && mir->ub[i] == 0.0)) continue;
  191. /* take first term */
  192. aij = mip->row[i]->ptr;
  193. if (aij == NULL) continue;
  194. k1 = m + aij->col->j, a1 = aij->val;
  195. /* take second term */
  196. aij = aij->r_next;
  197. if (aij == NULL) continue;
  198. k2 = m + aij->col->j, a2 = aij->val;
  199. /* there must be only two terms */
  200. if (aij->r_next != NULL) continue;
  201. /* interchange terms, if needed */
  202. if (!mir->isint[k1] && mir->isint[k2])
  203. ;
  204. else if (mir->isint[k1] && !mir->isint[k2])
  205. { k2 = k1, a2 = a1;
  206. k1 = m + aij->col->j, a1 = aij->val;
  207. }
  208. else
  209. { /* both terms are either continuous or integer */
  210. continue;
  211. }
  212. /* x[k2] should be double-bounded */
  213. if (mir->lb[k2] == -DBL_MAX || mir->ub[k2] == +DBL_MAX ||
  214. mir->lb[k2] == mir->ub[k2]) continue;
  215. /* change signs, if necessary */
  216. if (mir->ub[i] == 0.0) a1 = - a1, a2 = - a2;
  217. /* now the row has the form a1 * x1 + a2 * x2 >= 0, where x1
  218. is continuous, x2 is integer */
  219. if (a1 > 0.0)
  220. { /* x1 >= - (a2 / a1) * x2 */
  221. if (mir->vlb[k1] == 0)
  222. { /* set variable lower bound for x1 */
  223. mir->lb[k1] = - a2 / a1;
  224. mir->vlb[k1] = k2;
  225. /* the row should not be used */
  226. mir->skip[i] = 1;
  227. }
  228. }
  229. else /* a1 < 0.0 */
  230. { /* x1 <= - (a2 / a1) * x2 */
  231. if (mir->vub[k1] == 0)
  232. { /* set variable upper bound for x1 */
  233. mir->ub[k1] = - a2 / a1;
  234. mir->vub[k1] = k2;
  235. /* the row should not be used */
  236. mir->skip[i] = 1;
  237. }
  238. }
  239. }
  240. return;
  241. }
  242. static void mark_useless_rows(glp_tree *tree, struct MIR *mir)
  243. { /* mark rows which should not be used */
  244. glp_prob *mip = tree->mip;
  245. int m = mir->m;
  246. GLPAIJ *aij;
  247. int i, k, nv;
  248. for (i = 1; i <= m; i++)
  249. { /* free rows should not be used */
  250. if (mir->lb[i] == -DBL_MAX && mir->ub[i] == +DBL_MAX)
  251. { mir->skip[i] = 1;
  252. continue;
  253. }
  254. nv = 0;
  255. for (aij = mip->row[i]->ptr; aij != NULL; aij = aij->r_next)
  256. { k = m + aij->col->j;
  257. /* rows with free variables should not be used */
  258. if (mir->lb[k] == -DBL_MAX && mir->ub[k] == +DBL_MAX)
  259. { mir->skip[i] = 1;
  260. break;
  261. }
  262. /* rows with integer variables having infinite (lower or
  263. upper) bound should not be used */
  264. if (mir->isint[k] && mir->lb[k] == -DBL_MAX ||
  265. mir->isint[k] && mir->ub[k] == +DBL_MAX)
  266. { mir->skip[i] = 1;
  267. break;
  268. }
  269. /* count non-fixed variables */
  270. if (!(mir->vlb[k] == 0 && mir->vub[k] == 0 &&
  271. mir->lb[k] == mir->ub[k])) nv++;
  272. }
  273. /* rows with all variables fixed should not be used */
  274. if (nv == 0)
  275. { mir->skip[i] = 1;
  276. continue;
  277. }
  278. }
  279. return;
  280. }
  281. void *ios_mir_init(glp_tree *tree)
  282. { /* initialize MIR cut generator */
  283. glp_prob *mip = tree->mip;
  284. int m = mip->m;
  285. int n = mip->n;
  286. struct MIR *mir;
  287. #if _MIR_DEBUG
  288. xprintf("ios_mir_init: warning: debug mode enabled\n");
  289. #endif
  290. /* allocate working area */
  291. mir = xmalloc(sizeof(struct MIR));
  292. mir->m = m;
  293. mir->n = n;
  294. mir->skip = xcalloc(1+m, sizeof(char));
  295. mir->isint = xcalloc(1+m+n, sizeof(char));
  296. mir->lb = xcalloc(1+m+n, sizeof(double));
  297. mir->vlb = xcalloc(1+m+n, sizeof(int));
  298. mir->ub = xcalloc(1+m+n, sizeof(double));
  299. mir->vub = xcalloc(1+m+n, sizeof(int));
  300. mir->x = xcalloc(1+m+n, sizeof(double));
  301. mir->agg_row = xcalloc(1+MAXAGGR, sizeof(int));
  302. mir->agg_vec = ios_create_vec(m+n);
  303. mir->subst = xcalloc(1+m+n, sizeof(char));
  304. mir->mod_vec = ios_create_vec(m+n);
  305. mir->cut_vec = ios_create_vec(m+n);
  306. /* set global row attributes */
  307. set_row_attrib(tree, mir);
  308. /* set global column attributes */
  309. set_col_attrib(tree, mir);
  310. /* set variable bounds */
  311. set_var_bounds(tree, mir);
  312. /* mark rows which should not be used */
  313. mark_useless_rows(tree, mir);
  314. return mir;
  315. }
  316. /***********************************************************************
  317. * NAME
  318. *
  319. * ios_mir_gen - generate MIR cuts
  320. *
  321. * SYNOPSIS
  322. *
  323. * #include "glpios.h"
  324. * void ios_mir_gen(glp_tree *tree, void *gen, IOSPOOL *pool);
  325. *
  326. * DESCRIPTION
  327. *
  328. * The routine ios_mir_gen generates MIR cuts for the current point and
  329. * adds them to the cut pool. */
  330. static void get_current_point(glp_tree *tree, struct MIR *mir)
  331. { /* obtain current point */
  332. glp_prob *mip = tree->mip;
  333. int m = mir->m;
  334. int n = mir->n;
  335. int k;
  336. for (k = 1; k <= m; k++)
  337. mir->x[k] = mip->row[k]->prim;
  338. for (k = m+1; k <= m+n; k++)
  339. mir->x[k] = mip->col[k-m]->prim;
  340. return;
  341. }
  342. #if _MIR_DEBUG
  343. static void check_current_point(struct MIR *mir)
  344. { /* check current point */
  345. int m = mir->m;
  346. int n = mir->n;
  347. int k, kk;
  348. double lb, ub, eps;
  349. for (k = 1; k <= m+n; k++)
  350. { /* determine lower bound */
  351. lb = mir->lb[k];
  352. kk = mir->vlb[k];
  353. if (kk != 0)
  354. { xassert(lb != -DBL_MAX);
  355. xassert(!mir->isint[k]);
  356. xassert(mir->isint[kk]);
  357. lb *= mir->x[kk];
  358. }
  359. /* check lower bound */
  360. if (lb != -DBL_MAX)
  361. { eps = 1e-6 * (1.0 + fabs(lb));
  362. xassert(mir->x[k] >= lb - eps);
  363. }
  364. /* determine upper bound */
  365. ub = mir->ub[k];
  366. kk = mir->vub[k];
  367. if (kk != 0)
  368. { xassert(ub != +DBL_MAX);
  369. xassert(!mir->isint[k]);
  370. xassert(mir->isint[kk]);
  371. ub *= mir->x[kk];
  372. }
  373. /* check upper bound */
  374. if (ub != +DBL_MAX)
  375. { eps = 1e-6 * (1.0 + fabs(ub));
  376. xassert(mir->x[k] <= ub + eps);
  377. }
  378. }
  379. return;
  380. }
  381. #endif
  382. static void initial_agg_row(glp_tree *tree, struct MIR *mir, int i)
  383. { /* use original i-th row as initial aggregated constraint */
  384. glp_prob *mip = tree->mip;
  385. int m = mir->m;
  386. GLPAIJ *aij;
  387. xassert(1 <= i && i <= m);
  388. xassert(!mir->skip[i]);
  389. /* mark i-th row in order not to use it in the same aggregated
  390. constraint */
  391. mir->skip[i] = 2;
  392. mir->agg_cnt = 1;
  393. mir->agg_row[1] = i;
  394. /* use x[i] - sum a[i,j] * x[m+j] = 0, where x[i] is auxiliary
  395. variable of row i, x[m+j] are structural variables */
  396. ios_clear_vec(mir->agg_vec);
  397. ios_set_vj(mir->agg_vec, i, 1.0);
  398. for (aij = mip->row[i]->ptr; aij != NULL; aij = aij->r_next)
  399. ios_set_vj(mir->agg_vec, m + aij->col->j, - aij->val);
  400. mir->agg_rhs = 0.0;
  401. #if _MIR_DEBUG
  402. ios_check_vec(mir->agg_vec);
  403. #endif
  404. return;
  405. }
  406. #if _MIR_DEBUG
  407. static void check_agg_row(struct MIR *mir)
  408. { /* check aggregated constraint */
  409. int m = mir->m;
  410. int n = mir->n;
  411. int j, k;
  412. double r, big;
  413. /* compute the residual r = sum a[k] * x[k] - b and determine
  414. big = max(1, |a[k]|, |b|) */
  415. r = 0.0, big = 1.0;
  416. for (j = 1; j <= mir->agg_vec->nnz; j++)
  417. { k = mir->agg_vec->ind[j];
  418. xassert(1 <= k && k <= m+n);
  419. r += mir->agg_vec->val[j] * mir->x[k];
  420. if (big < fabs(mir->agg_vec->val[j]))
  421. big = fabs(mir->agg_vec->val[j]);
  422. }
  423. r -= mir->agg_rhs;
  424. if (big < fabs(mir->agg_rhs))
  425. big = fabs(mir->agg_rhs);
  426. /* the residual must be close to zero */
  427. xassert(fabs(r) <= 1e-6 * big);
  428. return;
  429. }
  430. #endif
  431. static void subst_fixed_vars(struct MIR *mir)
  432. { /* substitute fixed variables into aggregated constraint */
  433. int m = mir->m;
  434. int n = mir->n;
  435. int j, k;
  436. for (j = 1; j <= mir->agg_vec->nnz; j++)
  437. { k = mir->agg_vec->ind[j];
  438. xassert(1 <= k && k <= m+n);
  439. if (mir->vlb[k] == 0 && mir->vub[k] == 0 &&
  440. mir->lb[k] == mir->ub[k])
  441. { /* x[k] is fixed */
  442. mir->agg_rhs -= mir->agg_vec->val[j] * mir->lb[k];
  443. mir->agg_vec->val[j] = 0.0;
  444. }
  445. }
  446. /* remove terms corresponding to fixed variables */
  447. ios_clean_vec(mir->agg_vec, DBL_EPSILON);
  448. #if _MIR_DEBUG
  449. ios_check_vec(mir->agg_vec);
  450. #endif
  451. return;
  452. }
  453. static void bound_subst_heur(struct MIR *mir)
  454. { /* bound substitution heuristic */
  455. int m = mir->m;
  456. int n = mir->n;
  457. int j, k, kk;
  458. double d1, d2;
  459. for (j = 1; j <= mir->agg_vec->nnz; j++)
  460. { k = mir->agg_vec->ind[j];
  461. xassert(1 <= k && k <= m+n);
  462. if (mir->isint[k]) continue; /* skip integer variable */
  463. /* compute distance from x[k] to its lower bound */
  464. kk = mir->vlb[k];
  465. if (kk == 0)
  466. { if (mir->lb[k] == -DBL_MAX)
  467. d1 = DBL_MAX;
  468. else
  469. d1 = mir->x[k] - mir->lb[k];
  470. }
  471. else
  472. { xassert(1 <= kk && kk <= m+n);
  473. xassert(mir->isint[kk]);
  474. xassert(mir->lb[k] != -DBL_MAX);
  475. d1 = mir->x[k] - mir->lb[k] * mir->x[kk];
  476. }
  477. /* compute distance from x[k] to its upper bound */
  478. kk = mir->vub[k];
  479. if (kk == 0)
  480. { if (mir->vub[k] == +DBL_MAX)
  481. d2 = DBL_MAX;
  482. else
  483. d2 = mir->ub[k] - mir->x[k];
  484. }
  485. else
  486. { xassert(1 <= kk && kk <= m+n);
  487. xassert(mir->isint[kk]);
  488. xassert(mir->ub[k] != +DBL_MAX);
  489. d2 = mir->ub[k] * mir->x[kk] - mir->x[k];
  490. }
  491. /* x[k] cannot be free */
  492. xassert(d1 != DBL_MAX || d2 != DBL_MAX);
  493. /* choose the bound which is closer to x[k] */
  494. xassert(mir->subst[k] == '?');
  495. if (d1 <= d2)
  496. mir->subst[k] = 'L';
  497. else
  498. mir->subst[k] = 'U';
  499. }
  500. return;
  501. }
  502. static void build_mod_row(struct MIR *mir)
  503. { /* substitute bounds and build modified constraint */
  504. int m = mir->m;
  505. int n = mir->n;
  506. int j, jj, k, kk;
  507. /* initially modified constraint is aggregated constraint */
  508. ios_copy_vec(mir->mod_vec, mir->agg_vec);
  509. mir->mod_rhs = mir->agg_rhs;
  510. #if _MIR_DEBUG
  511. ios_check_vec(mir->mod_vec);
  512. #endif
  513. /* substitute bounds for continuous variables; note that due to
  514. substitution of variable bounds additional terms may appear in
  515. modified constraint */
  516. for (j = mir->mod_vec->nnz; j >= 1; j--)
  517. { k = mir->mod_vec->ind[j];
  518. xassert(1 <= k && k <= m+n);
  519. if (mir->isint[k]) continue; /* skip integer variable */
  520. if (mir->subst[k] == 'L')
  521. { /* x[k] = (lower bound) + x'[k] */
  522. xassert(mir->lb[k] != -DBL_MAX);
  523. kk = mir->vlb[k];
  524. if (kk == 0)
  525. { /* x[k] = lb[k] + x'[k] */
  526. mir->mod_rhs -= mir->mod_vec->val[j] * mir->lb[k];
  527. }
  528. else
  529. { /* x[k] = lb[k] * x[kk] + x'[k] */
  530. xassert(mir->isint[kk]);
  531. jj = mir->mod_vec->pos[kk];
  532. if (jj == 0)
  533. { ios_set_vj(mir->mod_vec, kk, 1.0);
  534. jj = mir->mod_vec->pos[kk];
  535. mir->mod_vec->val[jj] = 0.0;
  536. }
  537. mir->mod_vec->val[jj] +=
  538. mir->mod_vec->val[j] * mir->lb[k];
  539. }
  540. }
  541. else if (mir->subst[k] == 'U')
  542. { /* x[k] = (upper bound) - x'[k] */
  543. xassert(mir->ub[k] != +DBL_MAX);
  544. kk = mir->vub[k];
  545. if (kk == 0)
  546. { /* x[k] = ub[k] - x'[k] */
  547. mir->mod_rhs -= mir->mod_vec->val[j] * mir->ub[k];
  548. }
  549. else
  550. { /* x[k] = ub[k] * x[kk] - x'[k] */
  551. xassert(mir->isint[kk]);
  552. jj = mir->mod_vec->pos[kk];
  553. if (jj == 0)
  554. { ios_set_vj(mir->mod_vec, kk, 1.0);
  555. jj = mir->mod_vec->pos[kk];
  556. mir->mod_vec->val[jj] = 0.0;
  557. }
  558. mir->mod_vec->val[jj] +=
  559. mir->mod_vec->val[j] * mir->ub[k];
  560. }
  561. mir->mod_vec->val[j] = - mir->mod_vec->val[j];
  562. }
  563. else
  564. xassert(k != k);
  565. }
  566. #if _MIR_DEBUG
  567. ios_check_vec(mir->mod_vec);
  568. #endif
  569. /* substitute bounds for integer variables */
  570. for (j = 1; j <= mir->mod_vec->nnz; j++)
  571. { k = mir->mod_vec->ind[j];
  572. xassert(1 <= k && k <= m+n);
  573. if (!mir->isint[k]) continue; /* skip continuous variable */
  574. xassert(mir->subst[k] == '?');
  575. xassert(mir->vlb[k] == 0 && mir->vub[k] == 0);
  576. xassert(mir->lb[k] != -DBL_MAX && mir->ub[k] != +DBL_MAX);
  577. if (fabs(mir->lb[k]) <= fabs(mir->ub[k]))
  578. { /* x[k] = lb[k] + x'[k] */
  579. mir->subst[k] = 'L';
  580. mir->mod_rhs -= mir->mod_vec->val[j] * mir->lb[k];
  581. }
  582. else
  583. { /* x[k] = ub[k] - x'[k] */
  584. mir->subst[k] = 'U';
  585. mir->mod_rhs -= mir->mod_vec->val[j] * mir->ub[k];
  586. mir->mod_vec->val[j] = - mir->mod_vec->val[j];
  587. }
  588. }
  589. #if _MIR_DEBUG
  590. ios_check_vec(mir->mod_vec);
  591. #endif
  592. return;
  593. }
  594. #if _MIR_DEBUG
  595. static void check_mod_row(struct MIR *mir)
  596. { /* check modified constraint */
  597. int m = mir->m;
  598. int n = mir->n;
  599. int j, k, kk;
  600. double r, big, x;
  601. /* compute the residual r = sum a'[k] * x'[k] - b' and determine
  602. big = max(1, |a[k]|, |b|) */
  603. r = 0.0, big = 1.0;
  604. for (j = 1; j <= mir->mod_vec->nnz; j++)
  605. { k = mir->mod_vec->ind[j];
  606. xassert(1 <= k && k <= m+n);
  607. if (mir->subst[k] == 'L')
  608. { /* x'[k] = x[k] - (lower bound) */
  609. xassert(mir->lb[k] != -DBL_MAX);
  610. kk = mir->vlb[k];
  611. if (kk == 0)
  612. x = mir->x[k] - mir->lb[k];
  613. else
  614. x = mir->x[k] - mir->lb[k] * mir->x[kk];
  615. }
  616. else if (mir->subst[k] == 'U')
  617. { /* x'[k] = (upper bound) - x[k] */
  618. xassert(mir->ub[k] != +DBL_MAX);
  619. kk = mir->vub[k];
  620. if (kk == 0)
  621. x = mir->ub[k] - mir->x[k];
  622. else
  623. x = mir->ub[k] * mir->x[kk] - mir->x[k];
  624. }
  625. else
  626. xassert(k != k);
  627. r += mir->mod_vec->val[j] * x;
  628. if (big < fabs(mir->mod_vec->val[j]))
  629. big = fabs(mir->mod_vec->val[j]);
  630. }
  631. r -= mir->mod_rhs;
  632. if (big < fabs(mir->mod_rhs))
  633. big = fabs(mir->mod_rhs);
  634. /* the residual must be close to zero */
  635. xassert(fabs(r) <= 1e-6 * big);
  636. return;
  637. }
  638. #endif
  639. /***********************************************************************
  640. * mir_ineq - construct MIR inequality
  641. *
  642. * Given the single constraint mixed integer set
  643. *
  644. * |N|
  645. * X = {(x,s) in Z x R : sum a[j] * x[j] <= b + s},
  646. * + + j in N
  647. *
  648. * this routine constructs the mixed integer rounding (MIR) inequality
  649. *
  650. * sum alpha[j] * x[j] <= beta + gamma * s,
  651. * j in N
  652. *
  653. * which is valid for X.
  654. *
  655. * If the MIR inequality has been successfully constructed, the routine
  656. * returns zero. Otherwise, if b is close to nearest integer, there may
  657. * be numeric difficulties due to big coefficients; so in this case the
  658. * routine returns non-zero. */
  659. static int mir_ineq(const int n, const double a[], const double b,
  660. double alpha[], double *beta, double *gamma)
  661. { int j;
  662. double f, t;
  663. if (fabs(b - floor(b + .5)) < 0.01)
  664. return 1;
  665. f = b - floor(b);
  666. for (j = 1; j <= n; j++)
  667. { t = (a[j] - floor(a[j])) - f;
  668. if (t <= 0.0)
  669. alpha[j] = floor(a[j]);
  670. else
  671. alpha[j] = floor(a[j]) + t / (1.0 - f);
  672. }
  673. *beta = floor(b);
  674. *gamma = 1.0 / (1.0 - f);
  675. return 0;
  676. }
  677. /***********************************************************************
  678. * cmir_ineq - construct c-MIR inequality
  679. *
  680. * Given the mixed knapsack set
  681. *
  682. * MK |N|
  683. * X = {(x,s) in Z x R : sum a[j] * x[j] <= b + s,
  684. * + + j in N
  685. *
  686. * x[j] <= u[j]},
  687. *
  688. * a subset C of variables to be complemented, and a divisor delta > 0,
  689. * this routine constructs the complemented MIR (c-MIR) inequality
  690. *
  691. * sum alpha[j] * x[j] <= beta + gamma * s,
  692. * j in N
  693. * MK
  694. * which is valid for X .
  695. *
  696. * If the c-MIR inequality has been successfully constructed, the
  697. * routine returns zero. Otherwise, if there is a risk of numerical
  698. * difficulties due to big coefficients (see comments to the routine
  699. * mir_ineq), the routine cmir_ineq returns non-zero. */
  700. static int cmir_ineq(const int n, const double a[], const double b,
  701. const double u[], const char cset[], const double delta,
  702. double alpha[], double *beta, double *gamma)
  703. { int j;
  704. double *aa, bb;
  705. aa = alpha, bb = b;
  706. for (j = 1; j <= n; j++)
  707. { aa[j] = a[j] / delta;
  708. if (cset[j])
  709. aa[j] = - aa[j], bb -= a[j] * u[j];
  710. }
  711. bb /= delta;
  712. if (mir_ineq(n, aa, bb, alpha, beta, gamma)) return 1;
  713. for (j = 1; j <= n; j++)
  714. { if (cset[j])
  715. alpha[j] = - alpha[j], *beta += alpha[j] * u[j];
  716. }
  717. *gamma /= delta;
  718. return 0;
  719. }
  720. /***********************************************************************
  721. * cmir_sep - c-MIR separation heuristic
  722. *
  723. * Given the mixed knapsack set
  724. *
  725. * MK |N|
  726. * X = {(x,s) in Z x R : sum a[j] * x[j] <= b + s,
  727. * + + j in N
  728. *
  729. * x[j] <= u[j]}
  730. *
  731. * * *
  732. * and a fractional point (x , s ), this routine tries to construct
  733. * c-MIR inequality
  734. *
  735. * sum alpha[j] * x[j] <= beta + gamma * s,
  736. * j in N
  737. * MK
  738. * which is valid for X and has (desirably maximal) violation at the
  739. * fractional point given. This is attained by choosing an appropriate
  740. * set C of variables to be complemented and a divisor delta > 0, which
  741. * together define corresponding c-MIR inequality.
  742. *
  743. * If a violated c-MIR inequality has been successfully constructed,
  744. * the routine returns its violation:
  745. *
  746. * * *
  747. * sum alpha[j] * x [j] - beta - gamma * s ,
  748. * j in N
  749. *
  750. * which is positive. In case of failure the routine returns zero. */
  751. struct vset { int j; double v; };
  752. static int cmir_cmp(const void *p1, const void *p2)
  753. { const struct vset *v1 = p1, *v2 = p2;
  754. if (v1->v < v2->v) return -1;
  755. if (v1->v > v2->v) return +1;
  756. return 0;
  757. }
  758. static double cmir_sep(const int n, const double a[], const double b,
  759. const double u[], const double x[], const double s,
  760. double alpha[], double *beta, double *gamma)
  761. { int fail, j, k, nv, v;
  762. double delta, eps, d_try[1+3], r, r_best;
  763. char *cset;
  764. struct vset *vset;
  765. /* allocate working arrays */
  766. cset = xcalloc(1+n, sizeof(char));
  767. vset = xcalloc(1+n, sizeof(struct vset));
  768. /* choose initial C */
  769. for (j = 1; j <= n; j++)
  770. cset[j] = (char)(x[j] >= 0.5 * u[j]);
  771. /* choose initial delta */
  772. r_best = delta = 0.0;
  773. for (j = 1; j <= n; j++)
  774. { xassert(a[j] != 0.0);
  775. /* if x[j] is close to its bounds, skip it */
  776. eps = 1e-9 * (1.0 + fabs(u[j]));
  777. if (x[j] < eps || x[j] > u[j] - eps) continue;
  778. /* try delta = |a[j]| to construct c-MIR inequality */
  779. fail = cmir_ineq(n, a, b, u, cset, fabs(a[j]), alpha, beta,
  780. gamma);
  781. if (fail) continue;
  782. /* compute violation */
  783. r = - (*beta) - (*gamma) * s;
  784. for (k = 1; k <= n; k++) r += alpha[k] * x[k];
  785. if (r_best < r) r_best = r, delta = fabs(a[j]);
  786. }
  787. if (r_best < 0.001) r_best = 0.0;
  788. if (r_best == 0.0) goto done;
  789. xassert(delta > 0.0);
  790. /* try to increase violation by dividing delta by 2, 4, and 8,
  791. respectively */
  792. d_try[1] = delta / 2.0;
  793. d_try[2] = delta / 4.0;
  794. d_try[3] = delta / 8.0;
  795. for (j = 1; j <= 3; j++)
  796. { /* construct c-MIR inequality */
  797. fail = cmir_ineq(n, a, b, u, cset, d_try[j], alpha, beta,
  798. gamma);
  799. if (fail) continue;
  800. /* compute violation */
  801. r = - (*beta) - (*gamma) * s;
  802. for (k = 1; k <= n; k++) r += alpha[k] * x[k];
  803. if (r_best < r) r_best = r, delta = d_try[j];
  804. }
  805. /* build subset of variables lying strictly between their bounds
  806. and order it by nondecreasing values of |x[j] - u[j]/2| */
  807. nv = 0;
  808. for (j = 1; j <= n; j++)
  809. { /* if x[j] is close to its bounds, skip it */
  810. eps = 1e-9 * (1.0 + fabs(u[j]));
  811. if (x[j] < eps || x[j] > u[j] - eps) continue;
  812. /* add x[j] to the subset */
  813. nv++;
  814. vset[nv].j = j;
  815. vset[nv].v = fabs(x[j] - 0.5 * u[j]);
  816. }
  817. qsort(&vset[1], nv, sizeof(struct vset), cmir_cmp);
  818. /* try to increase violation by successively complementing each
  819. variable in the subset */
  820. for (v = 1; v <= nv; v++)
  821. { j = vset[v].j;
  822. /* replace x[j] by its complement or vice versa */
  823. cset[j] = (char)!cset[j];
  824. /* construct c-MIR inequality */
  825. fail = cmir_ineq(n, a, b, u, cset, delta, alpha, beta, gamma);
  826. /* restore the variable */
  827. cset[j] = (char)!cset[j];
  828. /* do not replace the variable in case of failure */
  829. if (fail) continue;
  830. /* compute violation */
  831. r = - (*beta) - (*gamma) * s;
  832. for (k = 1; k <= n; k++) r += alpha[k] * x[k];
  833. if (r_best < r) r_best = r, cset[j] = (char)!cset[j];
  834. }
  835. /* construct the best c-MIR inequality chosen */
  836. fail = cmir_ineq(n, a, b, u, cset, delta, alpha, beta, gamma);
  837. xassert(!fail);
  838. done: /* free working arrays */
  839. xfree(cset);
  840. xfree(vset);
  841. /* return to the calling routine */
  842. return r_best;
  843. }
  844. static double generate(struct MIR *mir)
  845. { /* try to generate violated c-MIR cut for modified constraint */
  846. int m = mir->m;
  847. int n = mir->n;
  848. int j, k, kk, nint;
  849. double s, *u, *x, *alpha, r_best = 0.0, b, beta, gamma;
  850. ios_copy_vec(mir->cut_vec, mir->mod_vec);
  851. mir->cut_rhs = mir->mod_rhs;
  852. /* remove small terms, which can appear due to substitution of
  853. variable bounds */
  854. ios_clean_vec(mir->cut_vec, DBL_EPSILON);
  855. #if _MIR_DEBUG
  856. ios_check_vec(mir->cut_vec);
  857. #endif
  858. /* remove positive continuous terms to obtain MK relaxation */
  859. for (j = 1; j <= mir->cut_vec->nnz; j++)
  860. { k = mir->cut_vec->ind[j];
  861. xassert(1 <= k && k <= m+n);
  862. if (!mir->isint[k] && mir->cut_vec->val[j] > 0.0)
  863. mir->cut_vec->val[j] = 0.0;
  864. }
  865. ios_clean_vec(mir->cut_vec, 0.0);
  866. #if _MIR_DEBUG
  867. ios_check_vec(mir->cut_vec);
  868. #endif
  869. /* move integer terms to the beginning of the sparse vector and
  870. determine the number of integer variables */
  871. nint = 0;
  872. for (j = 1; j <= mir->cut_vec->nnz; j++)
  873. { k = mir->cut_vec->ind[j];
  874. xassert(1 <= k && k <= m+n);
  875. if (mir->isint[k])
  876. { double temp;
  877. nint++;
  878. /* interchange elements [nint] and [j] */
  879. kk = mir->cut_vec->ind[nint];
  880. mir->cut_vec->pos[k] = nint;
  881. mir->cut_vec->pos[kk] = j;
  882. mir->cut_vec->ind[nint] = k;
  883. mir->cut_vec->ind[j] = kk;
  884. temp = mir->cut_vec->val[nint];
  885. mir->cut_vec->val[nint] = mir->cut_vec->val[j];
  886. mir->cut_vec->val[j] = temp;
  887. }
  888. }
  889. #if _MIR_DEBUG
  890. ios_check_vec(mir->cut_vec);
  891. #endif
  892. /* if there is no integer variable, nothing to generate */
  893. if (nint == 0) goto done;
  894. /* allocate working arrays */
  895. u = xcalloc(1+nint, sizeof(double));
  896. x = xcalloc(1+nint, sizeof(double));
  897. alpha = xcalloc(1+nint, sizeof(double));
  898. /* determine u and x */
  899. for (j = 1; j <= nint; j++)
  900. { k = mir->cut_vec->ind[j];
  901. xassert(m+1 <= k && k <= m+n);
  902. xassert(mir->isint[k]);
  903. u[j] = mir->ub[k] - mir->lb[k];
  904. xassert(u[j] >= 1.0);
  905. if (mir->subst[k] == 'L')
  906. x[j] = mir->x[k] - mir->lb[k];
  907. else if (mir->subst[k] == 'U')
  908. x[j] = mir->ub[k] - mir->x[k];
  909. else
  910. xassert(k != k);
  911. xassert(x[j] >= -0.001);
  912. if (x[j] < 0.0) x[j] = 0.0;
  913. }
  914. /* compute s = - sum of continuous terms */
  915. s = 0.0;
  916. for (j = nint+1; j <= mir->cut_vec->nnz; j++)
  917. { double x;
  918. k = mir->cut_vec->ind[j];
  919. xassert(1 <= k && k <= m+n);
  920. /* must be continuous */
  921. xassert(!mir->isint[k]);
  922. if (mir->subst[k] == 'L')
  923. { xassert(mir->lb[k] != -DBL_MAX);
  924. kk = mir->vlb[k];
  925. if (kk == 0)
  926. x = mir->x[k] - mir->lb[k];
  927. else
  928. x = mir->x[k] - mir->lb[k] * mir->x[kk];
  929. }
  930. else if (mir->subst[k] == 'U')
  931. { xassert(mir->ub[k] != +DBL_MAX);
  932. kk = mir->vub[k];
  933. if (kk == 0)
  934. x = mir->ub[k] - mir->x[k];
  935. else
  936. x = mir->ub[k] * mir->x[kk] - mir->x[k];
  937. }
  938. else
  939. xassert(k != k);
  940. xassert(x >= -0.001);
  941. if (x < 0.0) x = 0.0;
  942. s -= mir->cut_vec->val[j] * x;
  943. }
  944. xassert(s >= 0.0);
  945. /* apply heuristic to obtain most violated c-MIR inequality */
  946. b = mir->cut_rhs;
  947. r_best = cmir_sep(nint, mir->cut_vec->val, b, u, x, s, alpha,
  948. &beta, &gamma);
  949. if (r_best == 0.0) goto skip;
  950. xassert(r_best > 0.0);
  951. /* convert to raw cut */
  952. /* sum alpha[j] * x[j] <= beta + gamma * s */
  953. for (j = 1; j <= nint; j++)
  954. mir->cut_vec->val[j] = alpha[j];
  955. for (j = nint+1; j <= mir->cut_vec->nnz; j++)
  956. { k = mir->cut_vec->ind[j];
  957. if (k <= m+n) mir->cut_vec->val[j] *= gamma;
  958. }
  959. mir->cut_rhs = beta;
  960. #if _MIR_DEBUG
  961. ios_check_vec(mir->cut_vec);
  962. #endif
  963. skip: /* free working arrays */
  964. xfree(u);
  965. xfree(x);
  966. xfree(alpha);
  967. done: return r_best;
  968. }
  969. #if _MIR_DEBUG
  970. static void check_raw_cut(struct MIR *mir, double r_best)
  971. { /* check raw cut before back bound substitution */
  972. int m = mir->m;
  973. int n = mir->n;
  974. int j, k, kk;
  975. double r, big, x;
  976. /* compute the residual r = sum a[k] * x[k] - b and determine
  977. big = max(1, |a[k]|, |b|) */
  978. r = 0.0, big = 1.0;
  979. for (j = 1; j <= mir->cut_vec->nnz; j++)
  980. { k = mir->cut_vec->ind[j];
  981. xassert(1 <= k && k <= m+n);
  982. if (mir->subst[k] == 'L')
  983. { xassert(mir->lb[k] != -DBL_MAX);
  984. kk = mir->vlb[k];
  985. if (kk == 0)
  986. x = mir->x[k] - mir->lb[k];
  987. else
  988. x = mir->x[k] - mir->lb[k] * mir->x[kk];
  989. }
  990. else if (mir->subst[k] == 'U')
  991. { xassert(mir->ub[k] != +DBL_MAX);
  992. kk = mir->vub[k];
  993. if (kk == 0)
  994. x = mir->ub[k] - mir->x[k];
  995. else
  996. x = mir->ub[k] * mir->x[kk] - mir->x[k];
  997. }
  998. else
  999. xassert(k != k);
  1000. r += mir->cut_vec->val[j] * x;
  1001. if (big < fabs(mir->cut_vec->val[j]))
  1002. big = fabs(mir->cut_vec->val[j]);
  1003. }
  1004. r -= mir->cut_rhs;
  1005. if (big < fabs(mir->cut_rhs))
  1006. big = fabs(mir->cut_rhs);
  1007. /* the residual must be close to r_best */
  1008. xassert(fabs(r - r_best) <= 1e-6 * big);
  1009. return;
  1010. }
  1011. #endif
  1012. static void back_subst(struct MIR *mir)
  1013. { /* back substitution of original bounds */
  1014. int m = mir->m;
  1015. int n = mir->n;
  1016. int j, jj, k, kk;
  1017. /* at first, restore bounds of integer variables (because on
  1018. restoring variable bounds of continuous variables we need
  1019. original, not shifted, bounds of integer variables) */
  1020. for (j = 1; j <= mir->cut_vec->nnz; j++)
  1021. { k = mir->cut_vec->ind[j];
  1022. xassert(1 <= k && k <= m+n);
  1023. if (!mir->isint[k]) continue; /* skip continuous */
  1024. if (mir->subst[k] == 'L')
  1025. { /* x'[k] = x[k] - lb[k] */
  1026. xassert(mir->lb[k] != -DBL_MAX);
  1027. xassert(mir->vlb[k] == 0);
  1028. mir->cut_rhs += mir->cut_vec->val[j] * mir->lb[k];
  1029. }
  1030. else if (mir->subst[k] == 'U')
  1031. { /* x'[k] = ub[k] - x[k] */
  1032. xassert(mir->ub[k] != +DBL_MAX);
  1033. xassert(mir->vub[k] == 0);
  1034. mir->cut_rhs -= mir->cut_vec->val[j] * mir->ub[k];
  1035. mir->cut_vec->val[j] = - mir->cut_vec->val[j];
  1036. }
  1037. else
  1038. xassert(k != k);
  1039. }
  1040. /* now restore bounds of continuous variables */
  1041. for (j = 1; j <= mir->cut_vec->nnz; j++)
  1042. { k = mir->cut_vec->ind[j];
  1043. xassert(1 <= k && k <= m+n);
  1044. if (mir->isint[k]) continue; /* skip integer */
  1045. if (mir->subst[k] == 'L')
  1046. { /* x'[k] = x[k] - (lower bound) */
  1047. xassert(mir->lb[k] != -DBL_MAX);
  1048. kk = mir->vlb[k];
  1049. if (kk == 0)
  1050. { /* x'[k] = x[k] - lb[k] */
  1051. mir->cut_rhs += mir->cut_vec->val[j] * mir->lb[k];
  1052. }
  1053. else
  1054. { /* x'[k] = x[k] - lb[k] * x[kk] */
  1055. jj = mir->cut_vec->pos[kk];
  1056. #if 0
  1057. xassert(jj != 0);
  1058. #else
  1059. if (jj == 0)
  1060. { ios_set_vj(mir->cut_vec, kk, 1.0);
  1061. jj = mir->cut_vec->pos[kk];
  1062. xassert(jj != 0);
  1063. mir->cut_vec->val[jj] = 0.0;
  1064. }
  1065. #endif
  1066. mir->cut_vec->val[jj] -= mir->cut_vec->val[j] *
  1067. mir->lb[k];
  1068. }
  1069. }
  1070. else if (mir->subst[k] == 'U')
  1071. { /* x'[k] = (upper bound) - x[k] */
  1072. xassert(mir->ub[k] != +DBL_MAX);
  1073. kk = mir->vub[k];
  1074. if (kk == 0)
  1075. { /* x'[k] = ub[k] - x[k] */
  1076. mir->cut_rhs -= mir->cut_vec->val[j] * mir->ub[k];
  1077. }
  1078. else
  1079. { /* x'[k] = ub[k] * x[kk] - x[k] */
  1080. jj = mir->cut_vec->pos[kk];
  1081. if (jj == 0)
  1082. { ios_set_vj(mir->cut_vec, kk, 1.0);
  1083. jj = mir->cut_vec->pos[kk];
  1084. xassert(jj != 0);
  1085. mir->cut_vec->val[jj] = 0.0;
  1086. }
  1087. mir->cut_vec->val[jj] += mir->cut_vec->val[j] *
  1088. mir->ub[k];
  1089. }
  1090. mir->cut_vec->val[j] = - mir->cut_vec->val[j];
  1091. }
  1092. else
  1093. xassert(k != k);
  1094. }
  1095. #if _MIR_DEBUG
  1096. ios_check_vec(mir->cut_vec);
  1097. #endif
  1098. return;
  1099. }
  1100. #if _MIR_DEBUG
  1101. static void check_cut_row(struct MIR *mir, double r_best)
  1102. { /* check the cut after back bound substitution or elimination of
  1103. auxiliary variables */
  1104. int m = mir->m;
  1105. int n = mir->n;
  1106. int j, k;
  1107. double r, big;
  1108. /* compute the residual r = sum a[k] * x[k] - b and determine
  1109. big = max(1, |a[k]|, |b|) */
  1110. r = 0.0, big = 1.0;
  1111. for (j = 1; j <= mir->cut_vec->nnz; j++)
  1112. { k = mir->cut_vec->ind[j];
  1113. xassert(1 <= k && k <= m+n);
  1114. r += mir->cut_vec->val[j] * mir->x[k];
  1115. if (big < fabs(mir->cut_vec->val[j]))
  1116. big = fabs(mir->cut_vec->val[j]);
  1117. }
  1118. r -= mir->cut_rhs;
  1119. if (big < fabs(mir->cut_rhs))
  1120. big = fabs(mir->cut_rhs);
  1121. /* the residual must be close to r_best */
  1122. xassert(fabs(r - r_best) <= 1e-6 * big);
  1123. return;
  1124. }
  1125. #endif
  1126. static void subst_aux_vars(glp_tree *tree, struct MIR *mir)
  1127. { /* final substitution to eliminate auxiliary variables */
  1128. glp_prob *mip = tree->mip;
  1129. int m = mir->m;
  1130. int n = mir->n;
  1131. GLPAIJ *aij;
  1132. int j, k, kk, jj;
  1133. for (j = mir->cut_vec->nnz; j >= 1; j--)
  1134. { k = mir->cut_vec->ind[j];
  1135. xassert(1 <= k && k <= m+n);
  1136. if (k > m) continue; /* skip structurals */
  1137. for (aij = mip->row[k]->ptr; aij != NULL; aij = aij->r_next)
  1138. { kk = m + aij->col->j; /* structural */
  1139. jj = mir->cut_vec->pos[kk];
  1140. if (jj == 0)
  1141. { ios_set_vj(mir->cut_vec, kk, 1.0);
  1142. jj = mir->cut_vec->pos[kk];
  1143. mir->cut_vec->val[jj] = 0.0;
  1144. }
  1145. mir->cut_vec->val[jj] += mir->cut_vec->val[j] * aij->val;
  1146. }
  1147. mir->cut_vec->val[j] = 0.0;
  1148. }
  1149. ios_clean_vec(mir->cut_vec, 0.0);
  1150. return;
  1151. }
  1152. static void add_cut(glp_tree *tree, struct MIR *mir)
  1153. { /* add constructed cut inequality to the cut pool */
  1154. int m = mir->m;
  1155. int n = mir->n;
  1156. int j, k, len;
  1157. int *ind = xcalloc(1+n, sizeof(int));
  1158. double *val = xcalloc(1+n, sizeof(double));
  1159. len = 0;
  1160. for (j = mir->cut_vec->nnz; j >= 1; j--)
  1161. { k = mir->cut_vec->ind[j];
  1162. xassert(m+1 <= k && k <= m+n);
  1163. len++, ind[len] = k - m, val[len] = mir->cut_vec->val[j];
  1164. }
  1165. #if 0
  1166. ios_add_cut_row(tree, pool, GLP_RF_MIR, len, ind, val, GLP_UP,
  1167. mir->cut_rhs);
  1168. #else
  1169. glp_ios_add_row(tree, NULL, GLP_RF_MIR, 0, len, ind, val, GLP_UP,
  1170. mir->cut_rhs);
  1171. #endif
  1172. xfree(ind);
  1173. xfree(val);
  1174. return;
  1175. }
  1176. static int aggregate_row(glp_tree *tree, struct MIR *mir)
  1177. { /* try to aggregate another row */
  1178. glp_prob *mip = tree->mip;
  1179. int m = mir->m;
  1180. int n = mir->n;
  1181. GLPAIJ *aij;
  1182. IOSVEC *v;
  1183. int ii, j, jj, k, kk, kappa = 0, ret = 0;
  1184. double d1, d2, d, d_max = 0.0;
  1185. /* choose appropriate structural variable in the aggregated row
  1186. to be substituted */
  1187. for (j = 1; j <= mir->agg_vec->nnz; j++)
  1188. { k = mir->agg_vec->ind[j];
  1189. xassert(1 <= k && k <= m+n);
  1190. if (k <= m) continue; /* skip auxiliary var */
  1191. if (mir->isint[k]) continue; /* skip integer var */
  1192. if (fabs(mir->agg_vec->val[j]) < 0.001) continue;
  1193. /* compute distance from x[k] to its lower bound */
  1194. kk = mir->vlb[k];
  1195. if (kk == 0)
  1196. { if (mir->lb[k] == -DBL_MAX)
  1197. d1 = DBL_MAX;
  1198. else
  1199. d1 = mir->x[k] - mir->lb[k];
  1200. }
  1201. else
  1202. { xassert(1 <= kk && kk <= m+n);
  1203. xassert(mir->isint[kk]);
  1204. xassert(mir->lb[k] != -DBL_MAX);
  1205. d1 = mir->x[k] - mir->lb[k] * mir->x[kk];
  1206. }
  1207. /* compute distance from x[k] to its upper bound */
  1208. kk = mir->vub[k];
  1209. if (kk == 0)
  1210. { if (mir->vub[k] == +DBL_MAX)
  1211. d2 = DBL_MAX;
  1212. else
  1213. d2 = mir->ub[k] - mir->x[k];
  1214. }
  1215. else
  1216. { xassert(1 <= kk && kk <= m+n);
  1217. xassert(mir->isint[kk]);
  1218. xassert(mir->ub[k] != +DBL_MAX);
  1219. d2 = mir->ub[k] * mir->x[kk] - mir->x[k];
  1220. }
  1221. /* x[k] cannot be free */
  1222. xassert(d1 != DBL_MAX || d2 != DBL_MAX);
  1223. /* d = min(d1, d2) */
  1224. d = (d1 <= d2 ? d1 : d2);
  1225. xassert(d != DBL_MAX);
  1226. /* should not be close to corresponding bound */
  1227. if (d < 0.001) continue;
  1228. if (d_max < d) d_max = d, kappa = k;
  1229. }
  1230. if (kappa == 0)
  1231. { /* nothing chosen */
  1232. ret = 1;
  1233. goto done;
  1234. }
  1235. /* x[kappa] has been chosen */
  1236. xassert(m+1 <= kappa && kappa <= m+n);
  1237. xassert(!mir->isint[kappa]);
  1238. /* find another row, which have not been used yet, to eliminate
  1239. x[kappa] from the aggregated row */
  1240. for (ii = 1; ii <= m; ii++)
  1241. { if (mir->skip[ii]) continue;
  1242. for (aij = mip->row[ii]->ptr; aij != NULL; aij = aij->r_next)
  1243. if (aij->col->j == kappa - m) break;
  1244. if (aij != NULL && fabs(aij->val) >= 0.001) break;
  1245. }
  1246. if (ii > m)
  1247. { /* nothing found */
  1248. ret = 2;
  1249. goto done;
  1250. }
  1251. /* row ii has been found; include it in the aggregated list */
  1252. mir->agg_cnt++;
  1253. xassert(mir->agg_cnt <= MAXAGGR);
  1254. mir->agg_row[mir->agg_cnt] = ii;
  1255. mir->skip[ii] = 2;
  1256. /* v := new row */
  1257. v = ios_create_vec(m+n);
  1258. ios_set_vj(v, ii, 1.0);
  1259. for (aij = mip->row[ii]->ptr; aij != NULL; aij = aij->r_next)
  1260. ios_set_vj(v, m + aij->col->j, - aij->val);
  1261. #if _MIR_DEBUG
  1262. ios_check_vec(v);
  1263. #endif
  1264. /* perform gaussian elimination to remove x[kappa] */
  1265. j = mir->agg_vec->pos[kappa];
  1266. xassert(j != 0);
  1267. jj = v->pos[kappa];
  1268. xassert(jj != 0);
  1269. ios_linear_comb(mir->agg_vec,
  1270. - mir->agg_vec->val[j] / v->val[jj], v);
  1271. ios_delete_vec(v);
  1272. ios_set_vj(mir->agg_vec, kappa, 0.0);
  1273. #if _MIR_DEBUG
  1274. ios_check_vec(mir->agg_vec);
  1275. #endif
  1276. done: return ret;
  1277. }
  1278. void ios_mir_gen(glp_tree *tree, void *gen)
  1279. { /* main routine to generate MIR cuts */
  1280. glp_prob *mip = tree->mip;
  1281. struct MIR *mir = gen;
  1282. int m = mir->m;
  1283. int n = mir->n;
  1284. int i;
  1285. double r_best;
  1286. xassert(mip->m >= m);
  1287. xassert(mip->n == n);
  1288. /* obtain current point */
  1289. get_current_point(tree, mir);
  1290. #if _MIR_DEBUG
  1291. /* check current point */
  1292. check_current_point(mir);
  1293. #endif
  1294. /* reset bound substitution flags */
  1295. memset(&mir->subst[1], '?', m+n);
  1296. /* try to generate a set of violated MIR cuts */
  1297. for (i = 1; i <= m; i++)
  1298. { if (mir->skip[i]) continue;
  1299. /* use original i-th row as initial aggregated constraint */
  1300. initial_agg_row(tree, mir, i);
  1301. loop: ;
  1302. #if _MIR_DEBUG
  1303. /* check aggregated row */
  1304. check_agg_row(mir);
  1305. #endif
  1306. /* substitute fixed variables into aggregated constraint */
  1307. subst_fixed_vars(mir);
  1308. #if _MIR_DEBUG
  1309. /* check aggregated row */
  1310. check_agg_row(mir);
  1311. #endif
  1312. #if _MIR_DEBUG
  1313. /* check bound substitution flags */
  1314. { int k;
  1315. for (k = 1; k <= m+n; k++)
  1316. xassert(mir->subst[k] == '?');
  1317. }
  1318. #endif
  1319. /* apply bound substitution heuristic */
  1320. bound_subst_heur(mir);
  1321. /* substitute bounds and build modified constraint */
  1322. build_mod_row(mir);
  1323. #if _MIR_DEBUG
  1324. /* check modified row */
  1325. check_mod_row(mir);
  1326. #endif
  1327. /* try to generate violated c-MIR cut for modified row */
  1328. r_best = generate(mir);
  1329. if (r_best > 0.0)
  1330. { /* success */
  1331. #if _MIR_DEBUG
  1332. /* check raw cut before back bound substitution */
  1333. check_raw_cut(mir, r_best);
  1334. #endif
  1335. /* back substitution of original bounds */
  1336. back_subst(mir);
  1337. #if _MIR_DEBUG
  1338. /* check the cut after back bound substitution */
  1339. check_cut_row(mir, r_best);
  1340. #endif
  1341. /* final substitution to eliminate auxiliary variables */
  1342. subst_aux_vars(tree, mir);
  1343. #if _MIR_DEBUG
  1344. /* check the cut after elimination of auxiliaries */
  1345. check_cut_row(mir, r_best);
  1346. #endif
  1347. /* add constructed cut inequality to the cut pool */
  1348. add_cut(tree, mir);
  1349. }
  1350. /* reset bound substitution flags */
  1351. { int j, k;
  1352. for (j = 1; j <= mir->mod_vec->nnz; j++)
  1353. { k = mir->mod_vec->ind[j];
  1354. xassert(1 <= k && k <= m+n);
  1355. xassert(mir->subst[k] != '?');
  1356. mir->subst[k] = '?';
  1357. }
  1358. }
  1359. if (r_best == 0.0)
  1360. { /* failure */
  1361. if (mir->agg_cnt < MAXAGGR)
  1362. { /* try to aggregate another row */
  1363. if (aggregate_row(tree, mir) == 0) goto loop;
  1364. }
  1365. }
  1366. /* unmark rows used in the aggregated constraint */
  1367. { int k, ii;
  1368. for (k = 1; k <= mir->agg_cnt; k++)
  1369. { ii = mir->agg_row[k];
  1370. xassert(1 <= ii && ii <= m);
  1371. xassert(mir->skip[ii] == 2);
  1372. mir->skip[ii] = 0;
  1373. }
  1374. }
  1375. }
  1376. return;
  1377. }
  1378. /***********************************************************************
  1379. * NAME
  1380. *
  1381. * ios_mir_term - terminate MIR cut generator
  1382. *
  1383. * SYNOPSIS
  1384. *
  1385. * #include "glpios.h"
  1386. * void ios_mir_term(void *gen);
  1387. *
  1388. * DESCRIPTION
  1389. *
  1390. * The routine ios_mir_term deletes the MIR cut generator working area
  1391. * freeing all the memory allocated to it. */
  1392. void ios_mir_term(void *gen)
  1393. { struct MIR *mir = gen;
  1394. xfree(mir->skip);
  1395. xfree(mir->isint);
  1396. xfree(mir->lb);
  1397. xfree(mir->vlb);
  1398. xfree(mir->ub);
  1399. xfree(mir->vub);
  1400. xfree(mir->x);
  1401. xfree(mir->agg_row);
  1402. ios_delete_vec(mir->agg_vec);
  1403. xfree(mir->subst);
  1404. ios_delete_vec(mir->mod_vec);
  1405. ios_delete_vec(mir->cut_vec);
  1406. xfree(mir);
  1407. return;
  1408. }
  1409. /* eof */