glpios06.c 48 KB

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