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.

551 lines
18 KiB

  1. /* glpios07.c (mixed cover 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. /*----------------------------------------------------------------------
  26. -- COVER INEQUALITIES
  27. --
  28. -- Consider the set of feasible solutions to 0-1 knapsack problem:
  29. --
  30. -- sum a[j]*x[j] <= b, (1)
  31. -- j in J
  32. --
  33. -- x[j] is binary, (2)
  34. --
  35. -- where, wlog, we assume that a[j] > 0 (since 0-1 variables can be
  36. -- complemented) and a[j] <= b (since a[j] > b implies x[j] = 0).
  37. --
  38. -- A set C within J is called a cover if
  39. --
  40. -- sum a[j] > b. (3)
  41. -- j in C
  42. --
  43. -- For any cover C the inequality
  44. --
  45. -- sum x[j] <= |C| - 1 (4)
  46. -- j in C
  47. --
  48. -- is called a cover inequality and is valid for (1)-(2).
  49. --
  50. -- MIXED COVER INEQUALITIES
  51. --
  52. -- Consider the set of feasible solutions to mixed knapsack problem:
  53. --
  54. -- sum a[j]*x[j] + y <= b, (5)
  55. -- j in J
  56. --
  57. -- x[j] is binary, (6)
  58. --
  59. -- 0 <= y <= u is continuous, (7)
  60. --
  61. -- where again we assume that a[j] > 0.
  62. --
  63. -- Let C within J be some set. From (1)-(4) it follows that
  64. --
  65. -- sum a[j] > b - y (8)
  66. -- j in C
  67. --
  68. -- implies
  69. --
  70. -- sum x[j] <= |C| - 1. (9)
  71. -- j in C
  72. --
  73. -- Thus, we need to modify the inequality (9) in such a way that it be
  74. -- a constraint only if the condition (8) is satisfied.
  75. --
  76. -- Consider the following inequality:
  77. --
  78. -- sum x[j] <= |C| - t. (10)
  79. -- j in C
  80. --
  81. -- If 0 < t <= 1, then (10) is equivalent to (9), because all x[j] are
  82. -- binary variables. On the other hand, if t <= 0, (10) being satisfied
  83. -- for any values of x[j] is not a constraint.
  84. --
  85. -- Let
  86. --
  87. -- t' = sum a[j] + y - b. (11)
  88. -- j in C
  89. --
  90. -- It is understood that the condition t' > 0 is equivalent to (8).
  91. -- Besides, from (6)-(7) it follows that t' has an implied upper bound:
  92. --
  93. -- t'max = sum a[j] + u - b. (12)
  94. -- j in C
  95. --
  96. -- This allows to express the parameter t having desired properties:
  97. --
  98. -- t = t' / t'max. (13)
  99. --
  100. -- In fact, t <= 1 by definition, and t > 0 being equivalent to t' > 0
  101. -- is equivalent to (8).
  102. --
  103. -- Thus, the inequality (10), where t is given by formula (13) is valid
  104. -- for (5)-(7).
  105. --
  106. -- Note that if u = 0, then y = 0, so t = 1, and the conditions (8) and
  107. -- (10) is transformed to the conditions (3) and (4).
  108. --
  109. -- GENERATING MIXED COVER CUTS
  110. --
  111. -- To generate a mixed cover cut in the form (10) we need to find such
  112. -- set C which satisfies to the inequality (8) and for which, in turn,
  113. -- the inequality (10) is violated in the current point.
  114. --
  115. -- Substituting t from (13) to (10) gives:
  116. --
  117. -- 1
  118. -- sum x[j] <= |C| - ----- (sum a[j] + y - b), (14)
  119. -- j in C t'max j in C
  120. --
  121. -- and finally we have the cut inequality in the standard form:
  122. --
  123. -- sum x[j] + alfa * y <= beta, (15)
  124. -- j in C
  125. --
  126. -- where:
  127. --
  128. -- alfa = 1 / t'max, (16)
  129. --
  130. -- beta = |C| - alfa * (sum a[j] - b). (17)
  131. -- j in C */
  132. #if 1
  133. #define MAXTRY 1000
  134. #else
  135. #define MAXTRY 10000
  136. #endif
  137. static int cover2(int n, double a[], double b, double u, double x[],
  138. double y, int cov[], double *_alfa, double *_beta)
  139. { /* try to generate mixed cover cut using two-element cover */
  140. int i, j, try = 0, ret = 0;
  141. double eps, alfa, beta, temp, rmax = 0.001;
  142. eps = 0.001 * (1.0 + fabs(b));
  143. for (i = 0+1; i <= n; i++)
  144. for (j = i+1; j <= n; j++)
  145. { /* C = {i, j} */
  146. try++;
  147. if (try > MAXTRY) goto done;
  148. /* check if condition (8) is satisfied */
  149. if (a[i] + a[j] + y > b + eps)
  150. { /* compute parameters for inequality (15) */
  151. temp = a[i] + a[j] - b;
  152. alfa = 1.0 / (temp + u);
  153. beta = 2.0 - alfa * temp;
  154. /* compute violation of inequality (15) */
  155. temp = x[i] + x[j] + alfa * y - beta;
  156. /* choose C providing maximum violation */
  157. if (rmax < temp)
  158. { rmax = temp;
  159. cov[1] = i;
  160. cov[2] = j;
  161. *_alfa = alfa;
  162. *_beta = beta;
  163. ret = 1;
  164. }
  165. }
  166. }
  167. done: return ret;
  168. }
  169. static int cover3(int n, double a[], double b, double u, double x[],
  170. double y, int cov[], double *_alfa, double *_beta)
  171. { /* try to generate mixed cover cut using three-element cover */
  172. int i, j, k, try = 0, ret = 0;
  173. double eps, alfa, beta, temp, rmax = 0.001;
  174. eps = 0.001 * (1.0 + fabs(b));
  175. for (i = 0+1; i <= n; i++)
  176. for (j = i+1; j <= n; j++)
  177. for (k = j+1; k <= n; k++)
  178. { /* C = {i, j, k} */
  179. try++;
  180. if (try > MAXTRY) goto done;
  181. /* check if condition (8) is satisfied */
  182. if (a[i] + a[j] + a[k] + y > b + eps)
  183. { /* compute parameters for inequality (15) */
  184. temp = a[i] + a[j] + a[k] - b;
  185. alfa = 1.0 / (temp + u);
  186. beta = 3.0 - alfa * temp;
  187. /* compute violation of inequality (15) */
  188. temp = x[i] + x[j] + x[k] + alfa * y - beta;
  189. /* choose C providing maximum violation */
  190. if (rmax < temp)
  191. { rmax = temp;
  192. cov[1] = i;
  193. cov[2] = j;
  194. cov[3] = k;
  195. *_alfa = alfa;
  196. *_beta = beta;
  197. ret = 1;
  198. }
  199. }
  200. }
  201. done: return ret;
  202. }
  203. static int cover4(int n, double a[], double b, double u, double x[],
  204. double y, int cov[], double *_alfa, double *_beta)
  205. { /* try to generate mixed cover cut using four-element cover */
  206. int i, j, k, l, try = 0, ret = 0;
  207. double eps, alfa, beta, temp, rmax = 0.001;
  208. eps = 0.001 * (1.0 + fabs(b));
  209. for (i = 0+1; i <= n; i++)
  210. for (j = i+1; j <= n; j++)
  211. for (k = j+1; k <= n; k++)
  212. for (l = k+1; l <= n; l++)
  213. { /* C = {i, j, k, l} */
  214. try++;
  215. if (try > MAXTRY) goto done;
  216. /* check if condition (8) is satisfied */
  217. if (a[i] + a[j] + a[k] + a[l] + y > b + eps)
  218. { /* compute parameters for inequality (15) */
  219. temp = a[i] + a[j] + a[k] + a[l] - b;
  220. alfa = 1.0 / (temp + u);
  221. beta = 4.0 - alfa * temp;
  222. /* compute violation of inequality (15) */
  223. temp = x[i] + x[j] + x[k] + x[l] + alfa * y - beta;
  224. /* choose C providing maximum violation */
  225. if (rmax < temp)
  226. { rmax = temp;
  227. cov[1] = i;
  228. cov[2] = j;
  229. cov[3] = k;
  230. cov[4] = l;
  231. *_alfa = alfa;
  232. *_beta = beta;
  233. ret = 1;
  234. }
  235. }
  236. }
  237. done: return ret;
  238. }
  239. static int cover(int n, double a[], double b, double u, double x[],
  240. double y, int cov[], double *alfa, double *beta)
  241. { /* try to generate mixed cover cut;
  242. input (see (5)):
  243. n is the number of binary variables;
  244. a[1:n] are coefficients at binary variables;
  245. b is the right-hand side;
  246. u is upper bound of continuous variable;
  247. x[1:n] are values of binary variables at current point;
  248. y is value of continuous variable at current point;
  249. output (see (15), (16), (17)):
  250. cov[1:r] are indices of binary variables included in cover C,
  251. where r is the set cardinality returned on exit;
  252. alfa coefficient at continuous variable;
  253. beta is the right-hand side; */
  254. int j;
  255. /* perform some sanity checks */
  256. xassert(n >= 2);
  257. for (j = 1; j <= n; j++) xassert(a[j] > 0.0);
  258. #if 1 /* ??? */
  259. xassert(b > -1e-5);
  260. #else
  261. xassert(b > 0.0);
  262. #endif
  263. xassert(u >= 0.0);
  264. for (j = 1; j <= n; j++) xassert(0.0 <= x[j] && x[j] <= 1.0);
  265. xassert(0.0 <= y && y <= u);
  266. /* try to generate mixed cover cut */
  267. if (cover2(n, a, b, u, x, y, cov, alfa, beta)) return 2;
  268. if (cover3(n, a, b, u, x, y, cov, alfa, beta)) return 3;
  269. if (cover4(n, a, b, u, x, y, cov, alfa, beta)) return 4;
  270. return 0;
  271. }
  272. /*----------------------------------------------------------------------
  273. -- lpx_cover_cut - generate mixed cover cut.
  274. --
  275. -- SYNOPSIS
  276. --
  277. -- int lpx_cover_cut(LPX *lp, int len, int ind[], double val[],
  278. -- double work[]);
  279. --
  280. -- DESCRIPTION
  281. --
  282. -- The routine lpx_cover_cut generates a mixed cover cut for a given
  283. -- row of the MIP problem.
  284. --
  285. -- The given row of the MIP problem should be explicitly specified in
  286. -- the form:
  287. --
  288. -- sum{j in J} a[j]*x[j] <= b. (1)
  289. --
  290. -- On entry indices (ordinal numbers) of structural variables, which
  291. -- have non-zero constraint coefficients, should be placed in locations
  292. -- ind[1], ..., ind[len], and corresponding constraint coefficients
  293. -- should be placed in locations val[1], ..., val[len]. The right-hand
  294. -- side b should be stored in location val[0].
  295. --
  296. -- The working array work should have at least nb locations, where nb
  297. -- is the number of binary variables in (1).
  298. --
  299. -- The routine generates a mixed cover cut in the same form as (1) and
  300. -- stores the cut coefficients and right-hand side in the same way as
  301. -- just described above.
  302. --
  303. -- RETURNS
  304. --
  305. -- If the cutting plane has been successfully generated, the routine
  306. -- returns 1 <= len' <= n, which is the number of non-zero coefficients
  307. -- in the inequality constraint. Otherwise, the routine returns zero. */
  308. static int lpx_cover_cut(glp_prob *lp, int len, int ind[],
  309. double val[], double work[])
  310. { int cov[1+4], j, k, nb, newlen, r;
  311. double f_min, f_max, alfa, beta, u, *x = work, y;
  312. /* substitute and remove fixed variables */
  313. newlen = 0;
  314. for (k = 1; k <= len; k++)
  315. { j = ind[k];
  316. if (glp_get_col_type(lp, j) == GLP_FX)
  317. val[0] -= val[k] * glp_get_col_lb(lp, j);
  318. else
  319. { newlen++;
  320. ind[newlen] = ind[k];
  321. val[newlen] = val[k];
  322. }
  323. }
  324. len = newlen;
  325. /* move binary variables to the beginning of the list so that
  326. elements 1, 2, ..., nb correspond to binary variables, and
  327. elements nb+1, nb+2, ..., len correspond to rest variables */
  328. nb = 0;
  329. for (k = 1; k <= len; k++)
  330. { j = ind[k];
  331. if (glp_get_col_kind(lp, j) == GLP_BV)
  332. { /* binary variable */
  333. int ind_k;
  334. double val_k;
  335. nb++;
  336. ind_k = ind[nb], val_k = val[nb];
  337. ind[nb] = ind[k], val[nb] = val[k];
  338. ind[k] = ind_k, val[k] = val_k;
  339. }
  340. }
  341. /* now the specified row has the form:
  342. sum a[j]*x[j] + sum a[j]*y[j] <= b,
  343. where x[j] are binary variables, y[j] are rest variables */
  344. /* at least two binary variables are needed */
  345. if (nb < 2) return 0;
  346. /* compute implied lower and upper bounds for sum a[j]*y[j] */
  347. f_min = f_max = 0.0;
  348. for (k = nb+1; k <= len; k++)
  349. { j = ind[k];
  350. /* both bounds must be finite */
  351. if (glp_get_col_type(lp, j) != GLP_DB) return 0;
  352. if (val[k] > 0.0)
  353. { f_min += val[k] * glp_get_col_lb(lp, j);
  354. f_max += val[k] * glp_get_col_ub(lp, j);
  355. }
  356. else
  357. { f_min += val[k] * glp_get_col_ub(lp, j);
  358. f_max += val[k] * glp_get_col_lb(lp, j);
  359. }
  360. }
  361. /* sum a[j]*x[j] + sum a[j]*y[j] <= b ===>
  362. sum a[j]*x[j] + (sum a[j]*y[j] - f_min) <= b - f_min ===>
  363. sum a[j]*x[j] + y <= b - f_min,
  364. where y = sum a[j]*y[j] - f_min;
  365. note that 0 <= y <= u, u = f_max - f_min */
  366. /* determine upper bound of y */
  367. u = f_max - f_min;
  368. /* determine value of y at the current point */
  369. y = 0.0;
  370. for (k = nb+1; k <= len; k++)
  371. { j = ind[k];
  372. y += val[k] * glp_get_col_prim(lp, j);
  373. }
  374. y -= f_min;
  375. if (y < 0.0) y = 0.0;
  376. if (y > u) y = u;
  377. /* modify the right-hand side b */
  378. val[0] -= f_min;
  379. /* now the transformed row has the form:
  380. sum a[j]*x[j] + y <= b, where 0 <= y <= u */
  381. /* determine values of x[j] at the current point */
  382. for (k = 1; k <= nb; k++)
  383. { j = ind[k];
  384. x[k] = glp_get_col_prim(lp, j);
  385. if (x[k] < 0.0) x[k] = 0.0;
  386. if (x[k] > 1.0) x[k] = 1.0;
  387. }
  388. /* if a[j] < 0, replace x[j] by its complement 1 - x'[j] */
  389. for (k = 1; k <= nb; k++)
  390. { if (val[k] < 0.0)
  391. { ind[k] = - ind[k];
  392. val[k] = - val[k];
  393. val[0] += val[k];
  394. x[k] = 1.0 - x[k];
  395. }
  396. }
  397. /* try to generate a mixed cover cut for the transformed row */
  398. r = cover(nb, val, val[0], u, x, y, cov, &alfa, &beta);
  399. if (r == 0) return 0;
  400. xassert(2 <= r && r <= 4);
  401. /* now the cut is in the form:
  402. sum{j in C} x[j] + alfa * y <= beta */
  403. /* store the right-hand side beta */
  404. ind[0] = 0, val[0] = beta;
  405. /* restore the original ordinal numbers of x[j] */
  406. for (j = 1; j <= r; j++) cov[j] = ind[cov[j]];
  407. /* store cut coefficients at binary variables complementing back
  408. the variables having negative row coefficients */
  409. xassert(r <= nb);
  410. for (k = 1; k <= r; k++)
  411. { if (cov[k] > 0)
  412. { ind[k] = +cov[k];
  413. val[k] = +1.0;
  414. }
  415. else
  416. { ind[k] = -cov[k];
  417. val[k] = -1.0;
  418. val[0] -= 1.0;
  419. }
  420. }
  421. /* substitute y = sum a[j]*y[j] - f_min */
  422. for (k = nb+1; k <= len; k++)
  423. { r++;
  424. ind[r] = ind[k];
  425. val[r] = alfa * val[k];
  426. }
  427. val[0] += alfa * f_min;
  428. xassert(r <= len);
  429. len = r;
  430. return len;
  431. }
  432. /*----------------------------------------------------------------------
  433. -- lpx_eval_row - compute explictily specified row.
  434. --
  435. -- SYNOPSIS
  436. --
  437. -- double lpx_eval_row(LPX *lp, int len, int ind[], double val[]);
  438. --
  439. -- DESCRIPTION
  440. --
  441. -- The routine lpx_eval_row computes the primal value of an explicitly
  442. -- specified row using current values of structural variables.
  443. --
  444. -- The explicitly specified row may be thought as a linear form:
  445. --
  446. -- y = a[1]*x[m+1] + a[2]*x[m+2] + ... + a[n]*x[m+n],
  447. --
  448. -- where y is an auxiliary variable for this row, a[j] are coefficients
  449. -- of the linear form, x[m+j] are structural variables.
  450. --
  451. -- On entry column indices and numerical values of non-zero elements of
  452. -- the row should be stored in locations ind[1], ..., ind[len] and
  453. -- val[1], ..., val[len], where len is the number of non-zero elements.
  454. -- The array ind and val are not changed on exit.
  455. --
  456. -- RETURNS
  457. --
  458. -- The routine returns a computed value of y, the auxiliary variable of
  459. -- the specified row. */
  460. static double lpx_eval_row(glp_prob *lp, int len, int ind[],
  461. double val[])
  462. { int n = glp_get_num_cols(lp);
  463. int j, k;
  464. double sum = 0.0;
  465. if (len < 0)
  466. xerror("lpx_eval_row: len = %d; invalid row length\n", len);
  467. for (k = 1; k <= len; k++)
  468. { j = ind[k];
  469. if (!(1 <= j && j <= n))
  470. xerror("lpx_eval_row: j = %d; column number out of range\n",
  471. j);
  472. sum += val[k] * glp_get_col_prim(lp, j);
  473. }
  474. return sum;
  475. }
  476. /***********************************************************************
  477. * NAME
  478. *
  479. * ios_cov_gen - generate mixed cover cuts
  480. *
  481. * SYNOPSIS
  482. *
  483. * #include "glpios.h"
  484. * void ios_cov_gen(glp_tree *tree);
  485. *
  486. * DESCRIPTION
  487. *
  488. * The routine ios_cov_gen generates mixed cover cuts for the current
  489. * point and adds them to the cut pool. */
  490. void ios_cov_gen(glp_tree *tree)
  491. { glp_prob *prob = tree->mip;
  492. int m = glp_get_num_rows(prob);
  493. int n = glp_get_num_cols(prob);
  494. int i, k, type, kase, len, *ind;
  495. double r, *val, *work;
  496. xassert(glp_get_status(prob) == GLP_OPT);
  497. /* allocate working arrays */
  498. ind = xcalloc(1+n, sizeof(int));
  499. val = xcalloc(1+n, sizeof(double));
  500. work = xcalloc(1+n, sizeof(double));
  501. /* look through all rows */
  502. for (i = 1; i <= m; i++)
  503. for (kase = 1; kase <= 2; kase++)
  504. { type = glp_get_row_type(prob, i);
  505. if (kase == 1)
  506. { /* consider rows of '<=' type */
  507. if (!(type == GLP_UP || type == GLP_DB)) continue;
  508. len = glp_get_mat_row(prob, i, ind, val);
  509. val[0] = glp_get_row_ub(prob, i);
  510. }
  511. else
  512. { /* consider rows of '>=' type */
  513. if (!(type == GLP_LO || type == GLP_DB)) continue;
  514. len = glp_get_mat_row(prob, i, ind, val);
  515. for (k = 1; k <= len; k++) val[k] = - val[k];
  516. val[0] = - glp_get_row_lb(prob, i);
  517. }
  518. /* generate mixed cover cut:
  519. sum{j in J} a[j] * x[j] <= b */
  520. len = lpx_cover_cut(prob, len, ind, val, work);
  521. if (len == 0) continue;
  522. /* at the current point the cut inequality is violated, i.e.
  523. sum{j in J} a[j] * x[j] - b > 0 */
  524. r = lpx_eval_row(prob, len, ind, val) - val[0];
  525. if (r < 1e-3) continue;
  526. /* add the cut to the cut pool */
  527. glp_ios_add_row(tree, NULL, GLP_RF_COV, 0, len, ind, val,
  528. GLP_UP, val[0]);
  529. }
  530. /* free working arrays */
  531. xfree(ind);
  532. xfree(val);
  533. xfree(work);
  534. return;
  535. }
  536. /* eof */