1 /* glpios08.c (clique cut generator) */
3 /***********************************************************************
4 * This code is part of GLPK (GNU Linear Programming Kit).
6 * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
7 * 2009, 2010 Andrew Makhorin, Department for Applied Informatics,
8 * Moscow Aviation Institute, Moscow, Russia. All rights reserved.
9 * E-mail: <mao@gnu.org>.
11 * GLPK is free software: you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
16 * GLPK is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
19 * License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with GLPK. If not, see <http://www.gnu.org/licenses/>.
23 ***********************************************************************/
27 static double get_row_lb(LPX *lp, int i)
28 { /* this routine returns lower bound of row i or -DBL_MAX if the
29 row has no lower bound */
31 switch (lpx_get_row_type(lp, i))
39 lb = lpx_get_row_lb(lp, i);
47 static double get_row_ub(LPX *lp, int i)
48 { /* this routine returns upper bound of row i or +DBL_MAX if the
49 row has no upper bound */
51 switch (lpx_get_row_type(lp, i))
59 ub = lpx_get_row_ub(lp, i);
67 static double get_col_lb(LPX *lp, int j)
68 { /* this routine returns lower bound of column j or -DBL_MAX if
69 the column has no lower bound */
71 switch (lpx_get_col_type(lp, j))
79 lb = lpx_get_col_lb(lp, j);
87 static double get_col_ub(LPX *lp, int j)
88 { /* this routine returns upper bound of column j or +DBL_MAX if
89 the column has no upper bound */
91 switch (lpx_get_col_type(lp, j))
99 ub = lpx_get_col_ub(lp, j);
107 static int is_binary(LPX *lp, int j)
108 { /* this routine checks if variable x[j] is binary */
110 lpx_get_col_kind(lp, j) == LPX_IV &&
111 lpx_get_col_type(lp, j) == LPX_DB &&
112 lpx_get_col_lb(lp, j) == 0.0 && lpx_get_col_ub(lp, j) == 1.0;
115 static double eval_lf_min(LPX *lp, int len, int ind[], double val[])
116 { /* this routine computes the minimum of a specified linear form
123 min = sum a[j]*lb[j] + sum a[j]*ub[j],
126 where J+ = {j: a[j] > 0}, J- = {j: a[j] < 0}, lb[j] and ub[j]
127 are lower and upper bound of variable x[j], resp. */
131 for (t = 1; t <= len; t++)
134 { lb = get_col_lb(lp, j);
141 else if (val[t] < 0.0)
142 { ub = get_col_ub(lp, j);
155 static double eval_lf_max(LPX *lp, int len, int ind[], double val[])
156 { /* this routine computes the maximum of a specified linear form
163 max = sum a[j]*ub[j] + sum a[j]*lb[j],
166 where J+ = {j: a[j] > 0}, J- = {j: a[j] < 0}, lb[j] and ub[j]
167 are lower and upper bound of variable x[j], resp. */
171 for (t = 1; t <= len; t++)
174 { ub = get_col_ub(lp, j);
181 else if (val[t] < 0.0)
182 { lb = get_col_lb(lp, j);
195 /*----------------------------------------------------------------------
196 -- probing - determine logical relation between binary variables.
198 -- This routine tentatively sets a binary variable to 0 and then to 1
199 -- and examines whether another binary variable is caused to be fixed.
201 -- The examination is based only on one row (constraint), which is the
204 -- L <= sum a[j]*x[j] <= U. (1)
207 -- Let x[p] be a probing variable, x[q] be an examined variable. Then
208 -- (1) can be written as:
210 -- L <= sum a[j]*x[j] + a[p]*x[p] + a[q]*x[q] <= U, (2)
213 -- where J' = {j: j != p and j != q}.
217 -- L' = L - a[p]*x[p], (3)
219 -- U' = U - a[p]*x[p], (4)
221 -- where x[p] is assumed to be fixed at 0 or 1. So (2) can be rewritten
224 -- L' <= sum a[j]*x[j] + a[q]*x[q] <= U', (5)
227 -- from where we have:
229 -- L' - sum a[j]*x[j] <= a[q]*x[q] <= U' - sum a[j]*x[j]. (6)
234 -- min a[q]*x[q] = L' - MAX, (7)
236 -- max a[q]*x[q] = U' - MIN, (8)
240 -- MIN = min sum a[j]*x[j], (9)
243 -- MAX = max sum a[j]*x[j]. (10)
246 -- Formulae (7) and (8) allows determining implied lower and upper
249 -- Parameters len, val, L and U specify the constraint (1).
251 -- Parameters lf_min and lf_max specify implied lower and upper bounds
252 -- of the linear form (1). It is assumed that these bounds are computed
253 -- with the routines eval_lf_min and eval_lf_max (see above).
255 -- Parameter p specifies the probing variable x[p], which is set to 0
256 -- (if set is 0) or to 1 (if set is 1).
258 -- Parameter q specifies the examined variable x[q].
260 -- On exit the routine returns one of the following codes:
262 -- 0 - there is no logical relation between x[p] and x[q];
263 -- 1 - x[q] can take only on value 0;
264 -- 2 - x[q] can take only on value 1. */
266 static int probing(int len, double val[], double L, double U,
267 double lf_min, double lf_max, int p, int set, int q)
269 xassert(1 <= p && p < q && q <= len);
271 if (L != -DBL_MAX && set) L -= val[p];
273 if (U != +DBL_MAX && set) U -= val[p];
274 /* compute MIN (9) */
275 if (lf_min != -DBL_MAX)
276 { if (val[p] < 0.0) lf_min -= val[p];
277 if (val[q] < 0.0) lf_min -= val[q];
279 /* compute MAX (10) */
280 if (lf_max != +DBL_MAX)
281 { if (val[p] > 0.0) lf_max -= val[p];
282 if (val[q] > 0.0) lf_max -= val[q];
284 /* compute implied lower bound of x[q]; see (7), (8) */
286 { if (L == -DBL_MAX || lf_max == +DBL_MAX)
289 temp = (L - lf_max) / val[q];
292 { if (U == +DBL_MAX || lf_min == -DBL_MAX)
295 temp = (U - lf_min) / val[q];
297 if (temp > 0.001) return 2;
298 /* compute implied upper bound of x[q]; see (7), (8) */
300 { if (U == +DBL_MAX || lf_min == -DBL_MAX)
303 temp = (U - lf_min) / val[q];
306 { if (L == -DBL_MAX || lf_max == +DBL_MAX)
309 temp = (L - lf_max) / val[q];
311 if (temp < 0.999) return 1;
312 /* there is no logical relation between x[p] and x[q] */
317 { /* conflict graph; it represents logical relations between binary
318 variables and has a vertex for each binary variable and its
319 complement, and an edge between two vertices when at most one
320 of the variables represented by the vertices can equal one in
321 an optimal solution */
323 /* number of variables */
325 /* number of binary variables represented in the graph (note that
326 not all binary variables can be represented); vertices which
327 correspond to binary variables have numbers 1, ..., nb while
328 vertices which correspond to complements of binary variables
329 have numbers nb+1, ..., nb+nb */
331 /* number of edges in the graph */
332 int *vert; /* int vert[1+n]; */
333 /* if x[j] is a binary variable represented in the graph, vert[j]
334 is the vertex number corresponding to x[j]; otherwise vert[j]
336 int *orig; /* int list[1:nb]; */
337 /* if vert[j] = k > 0, then orig[k] = j */
339 /* adjacency matrix of the graph having 2*nb rows and columns;
340 only strict lower triangle is stored in dense packed form */
343 /*----------------------------------------------------------------------
344 -- lpx_create_cog - create the conflict graph.
348 -- #include "glplpx.h"
349 -- void *lpx_create_cog(LPX *lp);
353 -- The routine lpx_create_cog creates the conflict graph for a given
358 -- If the graph has been created, the routine returns a pointer to it.
359 -- Otherwise the routine returns NULL. */
362 #define MAX_ROW_LEN 500
364 static void lpx_add_cog_edge(void *_cog, int i, int j);
366 static void *lpx_create_cog(LPX *lp)
367 { struct COG *cog = NULL;
368 int m, n, nb, i, j, p, q, len, *ind, *vert, *orig;
369 double L, U, lf_min, lf_max, *val;
370 xprintf("Creating the conflict graph...\n");
371 m = lpx_get_num_rows(lp);
372 n = lpx_get_num_cols(lp);
373 /* determine which binary variables should be included in the
376 vert = xcalloc(1+n, sizeof(int));
377 for (j = 1; j <= n; j++) vert[j] = 0;
378 orig = xcalloc(1+n, sizeof(int));
379 ind = xcalloc(1+n, sizeof(int));
380 val = xcalloc(1+n, sizeof(double));
381 for (i = 1; i <= m; i++)
382 { L = get_row_lb(lp, i);
383 U = get_row_ub(lp, i);
384 if (L == -DBL_MAX && U == +DBL_MAX) continue;
385 len = lpx_get_mat_row(lp, i, ind, val);
386 if (len > MAX_ROW_LEN) continue;
387 lf_min = eval_lf_min(lp, len, ind, val);
388 lf_max = eval_lf_max(lp, len, ind, val);
389 for (p = 1; p <= len; p++)
390 { if (!is_binary(lp, ind[p])) continue;
391 for (q = p+1; q <= len; q++)
392 { if (!is_binary(lp, ind[q])) continue;
393 if (probing(len, val, L, U, lf_min, lf_max, p, 0, q) ||
394 probing(len, val, L, U, lf_min, lf_max, p, 1, q))
395 { /* there is a logical relation */
396 /* include the first variable in the graph */
398 if (vert[j] == 0) nb++, vert[j] = nb, orig[nb] = j;
399 /* incude the second variable in the graph */
401 if (vert[j] == 0) nb++, vert[j] = nb, orig[nb] = j;
406 /* if the graph is either empty or has too many vertices, do not
408 if (nb == 0 || nb > MAX_NB)
409 { xprintf("The conflict graph is either empty or too big\n");
414 /* create the conflict graph */
415 cog = xmalloc(sizeof(struct COG));
421 len = nb + nb; /* number of vertices */
422 len = (len * (len - 1)) / 2; /* number of entries in triangle */
423 len = (len + (CHAR_BIT - 1)) / CHAR_BIT; /* bytes needed */
424 cog->a = xmalloc(len);
425 memset(cog->a, 0, len);
426 for (j = 1; j <= nb; j++)
427 { /* add edge between variable and its complement */
428 lpx_add_cog_edge(cog, +orig[j], -orig[j]);
430 for (i = 1; i <= m; i++)
431 { L = get_row_lb(lp, i);
432 U = get_row_ub(lp, i);
433 if (L == -DBL_MAX && U == +DBL_MAX) continue;
434 len = lpx_get_mat_row(lp, i, ind, val);
435 if (len > MAX_ROW_LEN) continue;
436 lf_min = eval_lf_min(lp, len, ind, val);
437 lf_max = eval_lf_max(lp, len, ind, val);
438 for (p = 1; p <= len; p++)
439 { if (!is_binary(lp, ind[p])) continue;
440 for (q = p+1; q <= len; q++)
441 { if (!is_binary(lp, ind[q])) continue;
442 /* set x[p] to 0 and examine x[q] */
443 switch (probing(len, val, L, U, lf_min, lf_max, p, 0, q))
445 /* no logical relation */
448 /* x[p] = 0 implies x[q] = 0 */
449 lpx_add_cog_edge(cog, -ind[p], +ind[q]);
452 /* x[p] = 0 implies x[q] = 1 */
453 lpx_add_cog_edge(cog, -ind[p], -ind[q]);
458 /* set x[p] to 1 and examine x[q] */
459 switch (probing(len, val, L, U, lf_min, lf_max, p, 1, q))
461 /* no logical relation */
464 /* x[p] = 1 implies x[q] = 0 */
465 lpx_add_cog_edge(cog, +ind[p], +ind[q]);
468 /* x[p] = 1 implies x[q] = 1 */
469 lpx_add_cog_edge(cog, +ind[p], -ind[q]);
477 xprintf("The conflict graph has 2*%d vertices and %d edges\n",
484 /*----------------------------------------------------------------------
485 -- lpx_add_cog_edge - add edge to the conflict graph.
489 -- #include "glplpx.h"
490 -- void lpx_add_cog_edge(void *cog, int i, int j);
494 -- The routine lpx_add_cog_edge adds an edge to the conflict graph.
495 -- The edge connects x[i] (if i > 0) or its complement (if i < 0) and
496 -- x[j] (if j > 0) or its complement (if j < 0), where i and j are
497 -- original ordinal numbers of corresponding variables. */
499 static void lpx_add_cog_edge(void *_cog, int i, int j)
500 { struct COG *cog = _cog;
503 /* determine indices of corresponding vertices */
505 { xassert(1 <= i && i <= cog->n);
511 xassert(1 <= i && i <= cog->n);
517 { xassert(1 <= j && j <= cog->n);
523 xassert(1 <= j && j <= cog->n);
528 /* only lower triangle is stored, so we need i > j */
529 if (i < j) k = i, i = j, j = k;
530 k = ((i - 1) * (i - 2)) / 2 + (j - 1);
531 cog->a[k / CHAR_BIT] |=
532 (unsigned char)(1 << ((CHAR_BIT - 1) - k % CHAR_BIT));
537 /*----------------------------------------------------------------------
538 -- MAXIMUM WEIGHT CLIQUE
540 -- Two subroutines sub() and wclique() below are intended to find a
541 -- maximum weight clique in a given undirected graph. These subroutines
542 -- are slightly modified version of the program WCLIQUE developed by
543 -- Patric Ostergard <http://www.tcs.hut.fi/~pat/wclique.html> and based
544 -- on ideas from the article "P. R. J. Ostergard, A new algorithm for
545 -- the maximum-weight clique problem, submitted for publication", which
546 -- in turn is a generalization of the algorithm for unweighted graphs
547 -- presented in "P. R. J. Ostergard, A fast algorithm for the maximum
548 -- clique problem, submitted for publication".
550 -- USED WITH PERMISSION OF THE AUTHOR OF THE ORIGINAL CODE. */
553 { /* dynamic storage area */
555 /* number of vertices */
556 int *wt; /* int wt[0:n-1]; */
559 /* adjacency matrix (packed lower triangle without main diag.) */
561 /* weight of best clique */
563 /* number of vertices in best clique */
564 int *rec; /* int rec[0:n-1]; */
565 /* best clique so far */
566 int *clique; /* int clique[0:n-1]; */
567 /* table for pruning */
568 int *set; /* int set[0:n-1]; */
575 #define record (dsa->record)
576 #define rec_level (dsa->rec_level)
577 #define rec (dsa->rec)
578 #define clique (dsa->clique)
579 #define set (dsa->set)
582 static int is_edge(struct dsa *dsa, int i, int j)
583 { /* if there is arc (i,j), the routine returns true; otherwise
584 false; 0 <= i, j < n */
586 xassert(0 <= i && i < n);
587 xassert(0 <= j && j < n);
588 if (i == j) return 0;
589 if (i < j) k = i, i = j, j = k;
590 k = (i * (i - 1)) / 2 + j;
591 return a[k / CHAR_BIT] &
592 (unsigned char)(1 << ((CHAR_BIT - 1) - k % CHAR_BIT));
595 #define is_edge(dsa, i, j) ((i) == (j) ? 0 : \
596 (i) > (j) ? is_edge1(i, j) : is_edge1(j, i))
597 #define is_edge1(i, j) is_edge2(((i) * ((i) - 1)) / 2 + (j))
598 #define is_edge2(k) (a[(k) / CHAR_BIT] & \
599 (unsigned char)(1 << ((CHAR_BIT - 1) - (k) % CHAR_BIT)))
602 static void sub(struct dsa *dsa, int ct, int table[], int level,
603 int weight, int l_weight)
604 { int i, j, k, curr_weight, left_weight, *p1, *p2, *newtable;
605 newtable = xcalloc(n, sizeof(int));
607 { /* 0 or 1 elements left; include these */
609 { set[level++] = table[0];
615 for (i = 0; i < level; i++) rec[i] = set[i];
619 for (i = ct; i >= 0; i--)
620 { if ((level == 0) && (i < ct)) goto done;
622 if ((level > 0) && (clique[k] <= (record - weight)))
623 goto done; /* prune */
625 curr_weight = weight + wt[k];
627 if (l_weight <= (record - curr_weight))
628 goto done; /* prune */
632 while (p2 < table + i)
634 if (is_edge(dsa, j, k))
636 left_weight += wt[j];
639 if (left_weight <= (record - curr_weight)) continue;
640 sub(dsa, p1 - newtable - 1, newtable, level + 1, curr_weight,
643 done: xfree(newtable);
647 static int wclique(int _n, int w[], unsigned char _a[], int sol[])
648 { struct dsa _dsa, *dsa = &_dsa;
649 int i, j, p, max_wt, max_nwt, wth, *used, *nwt, *pos;
657 clique = xcalloc(n, sizeof(int));
658 set = xcalloc(n, sizeof(int));
659 used = xcalloc(n, sizeof(int));
660 nwt = xcalloc(n, sizeof(int));
661 pos = xcalloc(n, sizeof(int));
665 for (i = 0; i < n; i++)
667 for (j = 0; j < n; j++)
668 if (is_edge(dsa, i, j)) nwt[i] += wt[j];
670 for (i = 0; i < n; i++)
672 for (i = n-1; i >= 0; i--)
675 for (j = 0; j < n; j++)
676 { if ((!used[j]) && ((wt[j] > max_wt) || (wt[j] == max_wt
677 && nwt[j] > max_nwt)))
685 for (j = 0; j < n; j++)
686 if ((!used[j]) && (j != p) && (is_edge(dsa, p, j)))
691 for (i = 0; i < n; i++)
693 sub(dsa, i, pos, 0, 0, wth);
694 clique[pos[i]] = record;
696 if (utime() >= timer + 5.0)
698 if (xdifftime(xtime(), timer) >= 5.0 - 0.001)
700 { /* print current record and reset timer */
701 xprintf("level = %d (%d); best = %d\n", i+1, n, record);
714 /* return the solution found */
715 for (i = 1; i <= rec_level; i++) sol[i]++;
728 /*----------------------------------------------------------------------
729 -- lpx_clique_cut - generate cluque cut.
733 -- #include "glplpx.h"
734 -- int lpx_clique_cut(LPX *lp, void *cog, int ind[], double val[]);
738 -- The routine lpx_clique_cut generates a clique cut using the conflict
739 -- graph specified by the parameter cog.
741 -- If a violated clique cut has been found, it has the following form:
743 -- sum{j in J} a[j]*x[j] <= b.
745 -- Variable indices j in J are stored in elements ind[1], ..., ind[len]
746 -- while corresponding constraint coefficients are stored in elements
747 -- val[1], ..., val[len], where len is returned on exit. The right-hand
748 -- side b is stored in element val[0].
752 -- If the cutting plane has been successfully generated, the routine
753 -- returns 1 <= len <= n, which is the number of non-zero coefficients
754 -- in the inequality constraint. Otherwise, the routine returns zero. */
756 static int lpx_clique_cut(LPX *lp, void *_cog, int ind[], double val[])
757 { struct COG *cog = _cog;
758 int n = lpx_get_num_cols(lp);
759 int j, t, v, card, temp, len = 0, *w, *sol;
760 double x, sum, b, *vec;
761 /* allocate working arrays */
762 w = xcalloc(1 + 2 * cog->nb, sizeof(int));
763 sol = xcalloc(1 + 2 * cog->nb, sizeof(int));
764 vec = xcalloc(1+n, sizeof(double));
765 /* assign weights to vertices of the conflict graph */
766 for (t = 1; t <= cog->nb; t++)
768 x = lpx_get_col_prim(lp, j);
769 temp = (int)(100.0 * x + 0.5);
770 if (temp < 0) temp = 0;
771 if (temp > 100) temp = 100;
773 w[cog->nb + t] = 100 - temp;
775 /* find a clique of maximum weight */
776 card = wclique(2 * cog->nb, w, cog->a, sol);
777 /* compute the clique weight for unscaled values */
779 for ( t = 1; t <= card; t++)
781 xassert(1 <= v && v <= 2 * cog->nb);
783 { /* vertex v corresponds to binary variable x[j] */
785 x = lpx_get_col_prim(lp, j);
789 { /* vertex v corresponds to the complement of x[j] */
790 j = cog->orig[v - cog->nb];
791 x = lpx_get_col_prim(lp, j);
795 /* if the sum of binary variables and their complements in the
796 clique greater than 1, the clique cut is violated */
798 { /* construct the inquality */
799 for (j = 1; j <= n; j++) vec[j] = 0;
801 for (t = 1; t <= card; t++)
804 { /* vertex v corresponds to binary variable x[j] */
806 xassert(1 <= j && j <= n);
810 { /* vertex v corresponds to the complement of x[j] */
811 j = cog->orig[v - cog->nb];
812 xassert(1 <= j && j <= n);
818 for (j = 1; j <= n; j++)
821 ind[len] = j, val[len] = vec[j];
824 ind[0] = 0, val[0] = b;
826 /* free working arrays */
830 /* return to the calling program */
834 /*----------------------------------------------------------------------
835 -- lpx_delete_cog - delete the conflict graph.
839 -- #include "glplpx.h"
840 -- void lpx_delete_cog(void *cog);
844 -- The routine lpx_delete_cog deletes the conflict graph, which the
845 -- parameter cog points to, freeing all the memory allocated to this
848 static void lpx_delete_cog(void *_cog)
849 { struct COG *cog = _cog;
856 /**********************************************************************/
858 void *ios_clq_init(glp_tree *tree)
859 { /* initialize clique cut generator */
860 glp_prob *mip = tree->mip;
861 xassert(mip != NULL);
862 return lpx_create_cog(mip);
865 /***********************************************************************
868 * ios_clq_gen - generate clique cuts
872 * #include "glpios.h"
873 * void ios_clq_gen(glp_tree *tree, void *gen);
877 * The routine ios_clq_gen generates clique cuts for the current point
878 * and adds them to the clique pool. */
880 void ios_clq_gen(glp_tree *tree, void *gen)
881 { int n = lpx_get_num_cols(tree->mip);
884 xassert(gen != NULL);
885 ind = xcalloc(1+n, sizeof(int));
886 val = xcalloc(1+n, sizeof(double));
887 len = lpx_clique_cut(tree->mip, gen, ind, val);
889 { /* xprintf("len = %d\n", len); */
890 glp_ios_add_row(tree, NULL, GLP_RF_CLQ, 0, len, ind, val,
898 /**********************************************************************/
900 void ios_clq_term(void *gen)
901 { /* terminate clique cut generator */
902 xassert(gen != NULL);