lemon-project-template-glpk
comparison deps/glpk/src/glpios08.c @ 9:33de93886c88
Import GLPK 4.47
author | Alpar Juttner <alpar@cs.elte.hu> |
---|---|
date | Sun, 06 Nov 2011 20:59:10 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:407f0ca41f8a |
---|---|
1 /* glpios08.c (clique cut generator) */ | |
2 | |
3 /*********************************************************************** | |
4 * This code is part of GLPK (GNU Linear Programming Kit). | |
5 * | |
6 * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, | |
7 * 2009, 2010, 2011 Andrew Makhorin, Department for Applied Informatics, | |
8 * Moscow Aviation Institute, Moscow, Russia. All rights reserved. | |
9 * E-mail: <mao@gnu.org>. | |
10 * | |
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. | |
15 * | |
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. | |
20 * | |
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 ***********************************************************************/ | |
24 | |
25 #include "glpios.h" | |
26 | |
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 */ | |
30 double lb; | |
31 switch (lpx_get_row_type(lp, i)) | |
32 { case LPX_FR: | |
33 case LPX_UP: | |
34 lb = -DBL_MAX; | |
35 break; | |
36 case LPX_LO: | |
37 case LPX_DB: | |
38 case LPX_FX: | |
39 lb = lpx_get_row_lb(lp, i); | |
40 break; | |
41 default: | |
42 xassert(lp != lp); | |
43 } | |
44 return lb; | |
45 } | |
46 | |
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 */ | |
50 double ub; | |
51 switch (lpx_get_row_type(lp, i)) | |
52 { case LPX_FR: | |
53 case LPX_LO: | |
54 ub = +DBL_MAX; | |
55 break; | |
56 case LPX_UP: | |
57 case LPX_DB: | |
58 case LPX_FX: | |
59 ub = lpx_get_row_ub(lp, i); | |
60 break; | |
61 default: | |
62 xassert(lp != lp); | |
63 } | |
64 return ub; | |
65 } | |
66 | |
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 */ | |
70 double lb; | |
71 switch (lpx_get_col_type(lp, j)) | |
72 { case LPX_FR: | |
73 case LPX_UP: | |
74 lb = -DBL_MAX; | |
75 break; | |
76 case LPX_LO: | |
77 case LPX_DB: | |
78 case LPX_FX: | |
79 lb = lpx_get_col_lb(lp, j); | |
80 break; | |
81 default: | |
82 xassert(lp != lp); | |
83 } | |
84 return lb; | |
85 } | |
86 | |
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 */ | |
90 double ub; | |
91 switch (lpx_get_col_type(lp, j)) | |
92 { case LPX_FR: | |
93 case LPX_LO: | |
94 ub = +DBL_MAX; | |
95 break; | |
96 case LPX_UP: | |
97 case LPX_DB: | |
98 case LPX_FX: | |
99 ub = lpx_get_col_ub(lp, j); | |
100 break; | |
101 default: | |
102 xassert(lp != lp); | |
103 } | |
104 return ub; | |
105 } | |
106 | |
107 static int is_binary(LPX *lp, int j) | |
108 { /* this routine checks if variable x[j] is binary */ | |
109 return | |
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; | |
113 } | |
114 | |
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 | |
117 | |
118 sum a[j]*x[j] | |
119 j | |
120 | |
121 using the formula: | |
122 | |
123 min = sum a[j]*lb[j] + sum a[j]*ub[j], | |
124 j in J+ j in J- | |
125 | |
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. */ | |
128 int j, t; | |
129 double lb, ub, sum; | |
130 sum = 0.0; | |
131 for (t = 1; t <= len; t++) | |
132 { j = ind[t]; | |
133 if (val[t] > 0.0) | |
134 { lb = get_col_lb(lp, j); | |
135 if (lb == -DBL_MAX) | |
136 { sum = -DBL_MAX; | |
137 break; | |
138 } | |
139 sum += val[t] * lb; | |
140 } | |
141 else if (val[t] < 0.0) | |
142 { ub = get_col_ub(lp, j); | |
143 if (ub == +DBL_MAX) | |
144 { sum = -DBL_MAX; | |
145 break; | |
146 } | |
147 sum += val[t] * ub; | |
148 } | |
149 else | |
150 xassert(val != val); | |
151 } | |
152 return sum; | |
153 } | |
154 | |
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 | |
157 | |
158 sum a[j]*x[j] | |
159 j | |
160 | |
161 using the formula: | |
162 | |
163 max = sum a[j]*ub[j] + sum a[j]*lb[j], | |
164 j in J+ j in J- | |
165 | |
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. */ | |
168 int j, t; | |
169 double lb, ub, sum; | |
170 sum = 0.0; | |
171 for (t = 1; t <= len; t++) | |
172 { j = ind[t]; | |
173 if (val[t] > 0.0) | |
174 { ub = get_col_ub(lp, j); | |
175 if (ub == +DBL_MAX) | |
176 { sum = +DBL_MAX; | |
177 break; | |
178 } | |
179 sum += val[t] * ub; | |
180 } | |
181 else if (val[t] < 0.0) | |
182 { lb = get_col_lb(lp, j); | |
183 if (lb == -DBL_MAX) | |
184 { sum = +DBL_MAX; | |
185 break; | |
186 } | |
187 sum += val[t] * lb; | |
188 } | |
189 else | |
190 xassert(val != val); | |
191 } | |
192 return sum; | |
193 } | |
194 | |
195 /*---------------------------------------------------------------------- | |
196 -- probing - determine logical relation between binary variables. | |
197 -- | |
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. | |
200 -- | |
201 -- The examination is based only on one row (constraint), which is the | |
202 -- following: | |
203 -- | |
204 -- L <= sum a[j]*x[j] <= U. (1) | |
205 -- j | |
206 -- | |
207 -- Let x[p] be a probing variable, x[q] be an examined variable. Then | |
208 -- (1) can be written as: | |
209 -- | |
210 -- L <= sum a[j]*x[j] + a[p]*x[p] + a[q]*x[q] <= U, (2) | |
211 -- j in J' | |
212 -- | |
213 -- where J' = {j: j != p and j != q}. | |
214 -- | |
215 -- Let | |
216 -- | |
217 -- L' = L - a[p]*x[p], (3) | |
218 -- | |
219 -- U' = U - a[p]*x[p], (4) | |
220 -- | |
221 -- where x[p] is assumed to be fixed at 0 or 1. So (2) can be rewritten | |
222 -- as follows: | |
223 -- | |
224 -- L' <= sum a[j]*x[j] + a[q]*x[q] <= U', (5) | |
225 -- j in J' | |
226 -- | |
227 -- from where we have: | |
228 -- | |
229 -- L' - sum a[j]*x[j] <= a[q]*x[q] <= U' - sum a[j]*x[j]. (6) | |
230 -- j in J' j in J' | |
231 -- | |
232 -- Thus, | |
233 -- | |
234 -- min a[q]*x[q] = L' - MAX, (7) | |
235 -- | |
236 -- max a[q]*x[q] = U' - MIN, (8) | |
237 -- | |
238 -- where | |
239 -- | |
240 -- MIN = min sum a[j]*x[j], (9) | |
241 -- j in J' | |
242 -- | |
243 -- MAX = max sum a[j]*x[j]. (10) | |
244 -- j in J' | |
245 -- | |
246 -- Formulae (7) and (8) allows determining implied lower and upper | |
247 -- bounds of x[q]. | |
248 -- | |
249 -- Parameters len, val, L and U specify the constraint (1). | |
250 -- | |
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). | |
254 -- | |
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). | |
257 -- | |
258 -- Parameter q specifies the examined variable x[q]. | |
259 -- | |
260 -- On exit the routine returns one of the following codes: | |
261 -- | |
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. */ | |
265 | |
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) | |
268 { double temp; | |
269 xassert(1 <= p && p < q && q <= len); | |
270 /* compute L' (3) */ | |
271 if (L != -DBL_MAX && set) L -= val[p]; | |
272 /* compute U' (4) */ | |
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]; | |
278 } | |
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]; | |
283 } | |
284 /* compute implied lower bound of x[q]; see (7), (8) */ | |
285 if (val[q] > 0.0) | |
286 { if (L == -DBL_MAX || lf_max == +DBL_MAX) | |
287 temp = -DBL_MAX; | |
288 else | |
289 temp = (L - lf_max) / val[q]; | |
290 } | |
291 else | |
292 { if (U == +DBL_MAX || lf_min == -DBL_MAX) | |
293 temp = -DBL_MAX; | |
294 else | |
295 temp = (U - lf_min) / val[q]; | |
296 } | |
297 if (temp > 0.001) return 2; | |
298 /* compute implied upper bound of x[q]; see (7), (8) */ | |
299 if (val[q] > 0.0) | |
300 { if (U == +DBL_MAX || lf_min == -DBL_MAX) | |
301 temp = +DBL_MAX; | |
302 else | |
303 temp = (U - lf_min) / val[q]; | |
304 } | |
305 else | |
306 { if (L == -DBL_MAX || lf_max == +DBL_MAX) | |
307 temp = +DBL_MAX; | |
308 else | |
309 temp = (L - lf_max) / val[q]; | |
310 } | |
311 if (temp < 0.999) return 1; | |
312 /* there is no logical relation between x[p] and x[q] */ | |
313 return 0; | |
314 } | |
315 | |
316 struct COG | |
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 */ | |
322 int n; | |
323 /* number of variables */ | |
324 int nb; | |
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 */ | |
330 int ne; | |
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] | |
335 is zero */ | |
336 int *orig; /* int list[1:nb]; */ | |
337 /* if vert[j] = k > 0, then orig[k] = j */ | |
338 unsigned char *a; | |
339 /* adjacency matrix of the graph having 2*nb rows and columns; | |
340 only strict lower triangle is stored in dense packed form */ | |
341 }; | |
342 | |
343 /*---------------------------------------------------------------------- | |
344 -- lpx_create_cog - create the conflict graph. | |
345 -- | |
346 -- SYNOPSIS | |
347 -- | |
348 -- #include "glplpx.h" | |
349 -- void *lpx_create_cog(LPX *lp); | |
350 -- | |
351 -- DESCRIPTION | |
352 -- | |
353 -- The routine lpx_create_cog creates the conflict graph for a given | |
354 -- problem instance. | |
355 -- | |
356 -- RETURNS | |
357 -- | |
358 -- If the graph has been created, the routine returns a pointer to it. | |
359 -- Otherwise the routine returns NULL. */ | |
360 | |
361 #define MAX_NB 4000 | |
362 #define MAX_ROW_LEN 500 | |
363 | |
364 static void lpx_add_cog_edge(void *_cog, int i, int j); | |
365 | |
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 | |
374 conflict graph */ | |
375 nb = 0; | |
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 */ | |
397 j = ind[p]; | |
398 if (vert[j] == 0) nb++, vert[j] = nb, orig[nb] = j; | |
399 /* incude the second variable in the graph */ | |
400 j = ind[q]; | |
401 if (vert[j] == 0) nb++, vert[j] = nb, orig[nb] = j; | |
402 } | |
403 } | |
404 } | |
405 } | |
406 /* if the graph is either empty or has too many vertices, do not | |
407 create it */ | |
408 if (nb == 0 || nb > MAX_NB) | |
409 { xprintf("The conflict graph is either empty or too big\n"); | |
410 xfree(vert); | |
411 xfree(orig); | |
412 goto done; | |
413 } | |
414 /* create the conflict graph */ | |
415 cog = xmalloc(sizeof(struct COG)); | |
416 cog->n = n; | |
417 cog->nb = nb; | |
418 cog->ne = 0; | |
419 cog->vert = vert; | |
420 cog->orig = orig; | |
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]); | |
429 } | |
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)) | |
444 { case 0: | |
445 /* no logical relation */ | |
446 break; | |
447 case 1: | |
448 /* x[p] = 0 implies x[q] = 0 */ | |
449 lpx_add_cog_edge(cog, -ind[p], +ind[q]); | |
450 break; | |
451 case 2: | |
452 /* x[p] = 0 implies x[q] = 1 */ | |
453 lpx_add_cog_edge(cog, -ind[p], -ind[q]); | |
454 break; | |
455 default: | |
456 xassert(lp != lp); | |
457 } | |
458 /* set x[p] to 1 and examine x[q] */ | |
459 switch (probing(len, val, L, U, lf_min, lf_max, p, 1, q)) | |
460 { case 0: | |
461 /* no logical relation */ | |
462 break; | |
463 case 1: | |
464 /* x[p] = 1 implies x[q] = 0 */ | |
465 lpx_add_cog_edge(cog, +ind[p], +ind[q]); | |
466 break; | |
467 case 2: | |
468 /* x[p] = 1 implies x[q] = 1 */ | |
469 lpx_add_cog_edge(cog, +ind[p], -ind[q]); | |
470 break; | |
471 default: | |
472 xassert(lp != lp); | |
473 } | |
474 } | |
475 } | |
476 } | |
477 xprintf("The conflict graph has 2*%d vertices and %d edges\n", | |
478 cog->nb, cog->ne); | |
479 done: xfree(ind); | |
480 xfree(val); | |
481 return cog; | |
482 } | |
483 | |
484 /*---------------------------------------------------------------------- | |
485 -- lpx_add_cog_edge - add edge to the conflict graph. | |
486 -- | |
487 -- SYNOPSIS | |
488 -- | |
489 -- #include "glplpx.h" | |
490 -- void lpx_add_cog_edge(void *cog, int i, int j); | |
491 -- | |
492 -- DESCRIPTION | |
493 -- | |
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. */ | |
498 | |
499 static void lpx_add_cog_edge(void *_cog, int i, int j) | |
500 { struct COG *cog = _cog; | |
501 int k; | |
502 xassert(i != j); | |
503 /* determine indices of corresponding vertices */ | |
504 if (i > 0) | |
505 { xassert(1 <= i && i <= cog->n); | |
506 i = cog->vert[i]; | |
507 xassert(i != 0); | |
508 } | |
509 else | |
510 { i = -i; | |
511 xassert(1 <= i && i <= cog->n); | |
512 i = cog->vert[i]; | |
513 xassert(i != 0); | |
514 i += cog->nb; | |
515 } | |
516 if (j > 0) | |
517 { xassert(1 <= j && j <= cog->n); | |
518 j = cog->vert[j]; | |
519 xassert(j != 0); | |
520 } | |
521 else | |
522 { j = -j; | |
523 xassert(1 <= j && j <= cog->n); | |
524 j = cog->vert[j]; | |
525 xassert(j != 0); | |
526 j += cog->nb; | |
527 } | |
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)); | |
533 cog->ne++; | |
534 return; | |
535 } | |
536 | |
537 /*---------------------------------------------------------------------- | |
538 -- MAXIMUM WEIGHT CLIQUE | |
539 -- | |
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". | |
549 -- | |
550 -- USED WITH PERMISSION OF THE AUTHOR OF THE ORIGINAL CODE. */ | |
551 | |
552 struct dsa | |
553 { /* dynamic storage area */ | |
554 int n; | |
555 /* number of vertices */ | |
556 int *wt; /* int wt[0:n-1]; */ | |
557 /* weights */ | |
558 unsigned char *a; | |
559 /* adjacency matrix (packed lower triangle without main diag.) */ | |
560 int record; | |
561 /* weight of best clique */ | |
562 int rec_level; | |
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]; */ | |
569 /* current clique */ | |
570 }; | |
571 | |
572 #define n (dsa->n) | |
573 #define wt (dsa->wt) | |
574 #define a (dsa->a) | |
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) | |
580 | |
581 #if 0 | |
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 */ | |
585 int k; | |
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)); | |
593 } | |
594 #else | |
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))) | |
600 #endif | |
601 | |
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)); | |
606 if (ct <= 0) | |
607 { /* 0 or 1 elements left; include these */ | |
608 if (ct == 0) | |
609 { set[level++] = table[0]; | |
610 weight += l_weight; | |
611 } | |
612 if (weight > record) | |
613 { record = weight; | |
614 rec_level = level; | |
615 for (i = 0; i < level; i++) rec[i] = set[i]; | |
616 } | |
617 goto done; | |
618 } | |
619 for (i = ct; i >= 0; i--) | |
620 { if ((level == 0) && (i < ct)) goto done; | |
621 k = table[i]; | |
622 if ((level > 0) && (clique[k] <= (record - weight))) | |
623 goto done; /* prune */ | |
624 set[level] = k; | |
625 curr_weight = weight + wt[k]; | |
626 l_weight -= wt[k]; | |
627 if (l_weight <= (record - curr_weight)) | |
628 goto done; /* prune */ | |
629 p1 = newtable; | |
630 p2 = table; | |
631 left_weight = 0; | |
632 while (p2 < table + i) | |
633 { j = *p2++; | |
634 if (is_edge(dsa, j, k)) | |
635 { *p1++ = j; | |
636 left_weight += wt[j]; | |
637 } | |
638 } | |
639 if (left_weight <= (record - curr_weight)) continue; | |
640 sub(dsa, p1 - newtable - 1, newtable, level + 1, curr_weight, | |
641 left_weight); | |
642 } | |
643 done: xfree(newtable); | |
644 return; | |
645 } | |
646 | |
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; | |
650 glp_long timer; | |
651 n = _n; | |
652 wt = &w[1]; | |
653 a = _a; | |
654 record = 0; | |
655 rec_level = 0; | |
656 rec = &sol[1]; | |
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)); | |
662 /* start timer */ | |
663 timer = xtime(); | |
664 /* order vertices */ | |
665 for (i = 0; i < n; i++) | |
666 { nwt[i] = 0; | |
667 for (j = 0; j < n; j++) | |
668 if (is_edge(dsa, i, j)) nwt[i] += wt[j]; | |
669 } | |
670 for (i = 0; i < n; i++) | |
671 used[i] = 0; | |
672 for (i = n-1; i >= 0; i--) | |
673 { max_wt = -1; | |
674 max_nwt = -1; | |
675 for (j = 0; j < n; j++) | |
676 { if ((!used[j]) && ((wt[j] > max_wt) || (wt[j] == max_wt | |
677 && nwt[j] > max_nwt))) | |
678 { max_wt = wt[j]; | |
679 max_nwt = nwt[j]; | |
680 p = j; | |
681 } | |
682 } | |
683 pos[i] = p; | |
684 used[p] = 1; | |
685 for (j = 0; j < n; j++) | |
686 if ((!used[j]) && (j != p) && (is_edge(dsa, p, j))) | |
687 nwt[j] -= wt[p]; | |
688 } | |
689 /* main routine */ | |
690 wth = 0; | |
691 for (i = 0; i < n; i++) | |
692 { wth += wt[pos[i]]; | |
693 sub(dsa, i, pos, 0, 0, wth); | |
694 clique[pos[i]] = record; | |
695 #if 0 | |
696 if (utime() >= timer + 5.0) | |
697 #else | |
698 if (xdifftime(xtime(), timer) >= 5.0 - 0.001) | |
699 #endif | |
700 { /* print current record and reset timer */ | |
701 xprintf("level = %d (%d); best = %d\n", i+1, n, record); | |
702 #if 0 | |
703 timer = utime(); | |
704 #else | |
705 timer = xtime(); | |
706 #endif | |
707 } | |
708 } | |
709 xfree(clique); | |
710 xfree(set); | |
711 xfree(used); | |
712 xfree(nwt); | |
713 xfree(pos); | |
714 /* return the solution found */ | |
715 for (i = 1; i <= rec_level; i++) sol[i]++; | |
716 return rec_level; | |
717 } | |
718 | |
719 #undef n | |
720 #undef wt | |
721 #undef a | |
722 #undef record | |
723 #undef rec_level | |
724 #undef rec | |
725 #undef clique | |
726 #undef set | |
727 | |
728 /*---------------------------------------------------------------------- | |
729 -- lpx_clique_cut - generate cluque cut. | |
730 -- | |
731 -- SYNOPSIS | |
732 -- | |
733 -- #include "glplpx.h" | |
734 -- int lpx_clique_cut(LPX *lp, void *cog, int ind[], double val[]); | |
735 -- | |
736 -- DESCRIPTION | |
737 -- | |
738 -- The routine lpx_clique_cut generates a clique cut using the conflict | |
739 -- graph specified by the parameter cog. | |
740 -- | |
741 -- If a violated clique cut has been found, it has the following form: | |
742 -- | |
743 -- sum{j in J} a[j]*x[j] <= b. | |
744 -- | |
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]. | |
749 -- | |
750 -- RETURNS | |
751 -- | |
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. */ | |
755 | |
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++) | |
767 { j = cog->orig[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; | |
772 w[t] = temp; | |
773 w[cog->nb + t] = 100 - temp; | |
774 } | |
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 */ | |
778 sum = 0.0; | |
779 for ( t = 1; t <= card; t++) | |
780 { v = sol[t]; | |
781 xassert(1 <= v && v <= 2 * cog->nb); | |
782 if (v <= cog->nb) | |
783 { /* vertex v corresponds to binary variable x[j] */ | |
784 j = cog->orig[v]; | |
785 x = lpx_get_col_prim(lp, j); | |
786 sum += x; | |
787 } | |
788 else | |
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); | |
792 sum += 1.0 - x; | |
793 } | |
794 } | |
795 /* if the sum of binary variables and their complements in the | |
796 clique greater than 1, the clique cut is violated */ | |
797 if (sum >= 1.01) | |
798 { /* construct the inquality */ | |
799 for (j = 1; j <= n; j++) vec[j] = 0; | |
800 b = 1.0; | |
801 for (t = 1; t <= card; t++) | |
802 { v = sol[t]; | |
803 if (v <= cog->nb) | |
804 { /* vertex v corresponds to binary variable x[j] */ | |
805 j = cog->orig[v]; | |
806 xassert(1 <= j && j <= n); | |
807 vec[j] += 1.0; | |
808 } | |
809 else | |
810 { /* vertex v corresponds to the complement of x[j] */ | |
811 j = cog->orig[v - cog->nb]; | |
812 xassert(1 <= j && j <= n); | |
813 vec[j] -= 1.0; | |
814 b -= 1.0; | |
815 } | |
816 } | |
817 xassert(len == 0); | |
818 for (j = 1; j <= n; j++) | |
819 { if (vec[j] != 0.0) | |
820 { len++; | |
821 ind[len] = j, val[len] = vec[j]; | |
822 } | |
823 } | |
824 ind[0] = 0, val[0] = b; | |
825 } | |
826 /* free working arrays */ | |
827 xfree(w); | |
828 xfree(sol); | |
829 xfree(vec); | |
830 /* return to the calling program */ | |
831 return len; | |
832 } | |
833 | |
834 /*---------------------------------------------------------------------- | |
835 -- lpx_delete_cog - delete the conflict graph. | |
836 -- | |
837 -- SYNOPSIS | |
838 -- | |
839 -- #include "glplpx.h" | |
840 -- void lpx_delete_cog(void *cog); | |
841 -- | |
842 -- DESCRIPTION | |
843 -- | |
844 -- The routine lpx_delete_cog deletes the conflict graph, which the | |
845 -- parameter cog points to, freeing all the memory allocated to this | |
846 -- object. */ | |
847 | |
848 static void lpx_delete_cog(void *_cog) | |
849 { struct COG *cog = _cog; | |
850 xfree(cog->vert); | |
851 xfree(cog->orig); | |
852 xfree(cog->a); | |
853 xfree(cog); | |
854 } | |
855 | |
856 /**********************************************************************/ | |
857 | |
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); | |
863 } | |
864 | |
865 /*********************************************************************** | |
866 * NAME | |
867 * | |
868 * ios_clq_gen - generate clique cuts | |
869 * | |
870 * SYNOPSIS | |
871 * | |
872 * #include "glpios.h" | |
873 * void ios_clq_gen(glp_tree *tree, void *gen); | |
874 * | |
875 * DESCRIPTION | |
876 * | |
877 * The routine ios_clq_gen generates clique cuts for the current point | |
878 * and adds them to the clique pool. */ | |
879 | |
880 void ios_clq_gen(glp_tree *tree, void *gen) | |
881 { int n = lpx_get_num_cols(tree->mip); | |
882 int len, *ind; | |
883 double *val; | |
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); | |
888 if (len > 0) | |
889 { /* xprintf("len = %d\n", len); */ | |
890 glp_ios_add_row(tree, NULL, GLP_RF_CLQ, 0, len, ind, val, | |
891 GLP_UP, val[0]); | |
892 } | |
893 xfree(ind); | |
894 xfree(val); | |
895 return; | |
896 } | |
897 | |
898 /**********************************************************************/ | |
899 | |
900 void ios_clq_term(void *gen) | |
901 { /* terminate clique cut generator */ | |
902 xassert(gen != NULL); | |
903 lpx_delete_cog(gen); | |
904 return; | |
905 } | |
906 | |
907 /* eof */ |