SCIP Doxygen Documentation
Loading...
Searching...
No Matches
presol_gateextraction.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2026 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file presol_gateextraction.c
26 * @ingroup DEFPLUGINS_PRESOL
27 * @brief gateextraction presolver
28 * @author Michael Winkler
29 */
30
31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
32
34#include "scip/cons_and.h"
35#include "scip/cons_logicor.h"
36#include "scip/cons_setppc.h"
38#include "scip/pub_cons.h"
39#include "scip/pub_message.h"
40#include "scip/pub_misc.h"
41#include "scip/pub_misc_sort.h"
42#include "scip/pub_presol.h"
43#include "scip/pub_var.h"
44#include "scip/scip_cons.h"
45#include "scip/scip_general.h"
46#include "scip/scip_mem.h"
47#include "scip/scip_message.h"
48#include "scip/scip_param.h"
49#include "scip/scip_presol.h"
50#include "scip/scip_prob.h"
51#include "scip/scip_var.h"
52
53
54#define PRESOL_NAME "gateextraction"
55#define PRESOL_DESC "presolver extracting gate(and)-constraints"
56#define PRESOL_PRIORITY 1000000 /**< priority of the presolver (>= 0: before, < 0: after constraint handlers); combined with propagators */
57#define PRESOL_MAXROUNDS -1 /**< maximal number of presolving rounds the presolver participates in (-1: no limit) */
58#define PRESOL_TIMING SCIP_PRESOLTIMING_EXHAUSTIVE /* timing of the presolver (fast, medium, or exhaustive) */
59
60#define HASHSIZE_LOGICORCONS 500 /**< minimal size of hash table in logicor constraint tables */
61#define HASHSIZE_SETPPCCONS 500 /**< minimal size of hash table in setppc constraint tables */
62
63#define DEFAULT_ONLYSETPART FALSE /**< should only set-partitioning constraints be extracted and no and-constraints */
64#define DEFAULT_SEARCHEQUATIONS TRUE /**< should we try to extract set-partitioning constraint out of one logicor
65 * and one corresponding set-packing constraint
66 */
67#define DEFAULT_SORTING 1 /**< order logicor contraints to extract big-gates before smaller ones (-1), do
68 * not order them (0) or order them to extract smaller gates at first (1)
69 */
70
71
72/* This presolver tries to extract gate-constraints meaning and-constraints and set-partitioning constraints (and could
73 * be expanded to find xor-constraints too). This is done by detecting linearizations or systems of inequalities which
74 * form an and-constraint or a set-partitioning constraint. An example:
75 *
76 * we have a logicor constraint of the form: x + y + z >= 1
77 *
78 * and we also have the following set-packing constraints: (x + y <= 1 and x + z <= 1) <=> (~x + ~y >= 1 and ~x + ~z >= 1)
79 *
80 * - these three constraints form an and-constraint: x = ~y * ~z (x = AND(~y,~z))
81 *
82 * if an additional set-packing constraint exists: y + z <= 1
83 *
84 * - these four constraints form a set-partitioning cons.: x + y + z = 1
85 *
86 * some information can be found:
87 *
88 * http://www.cs.ubc.ca/~hutter/earg/papers07/cnf-structure.pdf
89 * http://www.cadence.com/cn/cadence/cadence_labs/Documents/niklas_SAT_2005_Effective.pdf
90 *
91 * We also do some check for logicor and set-packing/-partitioning constraint with the same variables to upgrade these
92 * both constraints into one. For example:
93 *
94 * x + y + z >= 1 and x + y + z <= 1 form x + y + z = 1
95 *
96 */
97
98
99/*
100 * Data structures
101 */
102
103
104/** data object to compare constraint easier */
106{
107 SCIP_CONS* cons; /**< pointer the the corresponding constraint */
108 SCIP_VAR** vars; /**< constraint variables used for hash comparison */
109 int nvars; /**< number of variables */
110};
111typedef struct HashData HASHDATA;
112
113
114/** presolver data */
115struct SCIP_PresolData
116{
117 HASHDATA* setppchashdatas; /**< setppc-hashdata storage */
118 SCIP_HASHTABLE* hashdatatable; /**< setppc-hashdata hashtable for usable setppc constraints */
119 SCIP_HASHTABLE* setppchashtable; /**< setppc hashtable for usable setppc constraints */
120 SCIP_HASHTABLE* logicorhashtable; /**< logicor hashtable for usable logicor constraints */
121 SCIP_CONS** usefullogicor; /**< array for usable logicors */
122 int nusefullogicor; /**< number of usable logicors */
123 int susefullogicor; /**< size of array for usable logicor constraints */
124 int nsetppchashdatas; /**< number of setppchashdata elements added to the hashtable */
125 int ssetppchashdatas; /**< size of setppchashdata elements added to the hashtable */
126 int ngates; /**< number of found gates in presolving */
127 int firstchangedlogicor;/**< position of the first new/changed logicor constraint in the
128 * usefullogicor array
129 */
130 int maxnvarslogicor; /**< maximal number of variables a logicor constraint has */
131 int sorting; /**< integer parameter how to sort logicor constraints for extracting gates */
132 SCIP_Bool usefulsetppcexist; /**< did we find usable set-packing constraints for gate extraction */
133 SCIP_Bool usefullogicorexist; /**< did we find usable logicor constraints for gate extraction */
134 SCIP_Bool newsetppchashdatas; /**< flag indicating whether we found new set-packing constraint with two
135 * variables since the last presolving round
136 */
137 SCIP_Bool initialized; /**< was data alredy be initialized */
138 SCIP_Bool onlysetpart; /**< boolean parameter whetehr we only want to extract linear gates */
139 SCIP_Bool searchequations; /**< boolean parameter whetehr we want to search for equations arising from
140 * logicor and setppc constraints
141 */
142};
143
144
145/*
146 * Local methods
147 */
148
149
150/** returns TRUE iff both keys are equal; two constraints are equal if they have the same pointer */
151static
152SCIP_DECL_HASHKEYEQ(hashdataKeyEqCons)
153{
154#ifndef NDEBUG
155 SCIP* scip;
156#endif
157 HASHDATA* hashdata1;
158 HASHDATA* hashdata2;
159 int v;
160
161 hashdata1 = (HASHDATA*)key1;
162 hashdata2 = (HASHDATA*)key2;
163#ifndef NDEBUG
164 scip = (SCIP*)userptr;
165 assert(scip != NULL);
166#endif
167
168 /* check data structure */
169 assert(hashdata1->nvars == 2);
170 assert(hashdata2->nvars == 2);
171 /* at least one data object needs to be have a real set packing constraint */
172 /* TODO why does this assert fail on one instance when problem is freed
173 * using the new hashing: assert(hashdata1->cons != NULL || hashdata2->cons != NULL);
174 */
175
176 for( v = 1; v >= 0; --v )
177 {
178 /* tests if variables are equal */
179 if( hashdata1->vars[v] != hashdata2->vars[v] )
180 return FALSE;
181
182 assert(SCIPvarCompare(hashdata1->vars[v], hashdata2->vars[v]) == 0);
183 }
184
185 /* a hashdata object is only equal if it has the same constraint pointer, or one has no constraint pointer, latter
186 * means that this hashdata object is derived from a logicor constraint
187 */
188 if( hashdata1->cons == NULL || hashdata2->cons == NULL || hashdata1->cons == hashdata2->cons )
189 return TRUE;
190 else
191 return FALSE;
192}
193
194/** returns the hash value of the key */
195static
196SCIP_DECL_HASHKEYVAL(hashdataKeyValCons)
197{ /*lint --e{715}*/
198 HASHDATA* hashdata;
199 unsigned int hashval;
200
201 hashdata = (HASHDATA*)key;
202 assert(hashdata != NULL);
203 assert(hashdata->vars != NULL);
204 assert(hashdata->nvars == 2);
205
206 /* if we have only two variables we store at each 16 bits of the hash value the index of a variable */
207 hashval = ((unsigned int)SCIPvarGetIndex(hashdata->vars[1]) << 16) + (unsigned int) SCIPvarGetIndex(hashdata->vars[0]); /*lint !e701*/
208
209 return hashval;
210}
211
212
213/** returns TRUE iff both keys are equal; two constraints are equal if they have the same pointer */
214static
215SCIP_DECL_HASHKEYEQ(setppcHashdataKeyEqCons)
216{
217#ifndef NDEBUG
218 SCIP* scip;
219#endif
220 HASHDATA* hashdata1;
221 HASHDATA* hashdata2;
222 int v;
223
224 hashdata1 = (HASHDATA*)key1;
225 hashdata2 = (HASHDATA*)key2;
226#ifndef NDEBUG
227 scip = (SCIP*)userptr;
228 assert(scip != NULL);
229#endif
230
231 /* check data structure */
232 assert(hashdata1->nvars >= 2);
233 assert(hashdata2->nvars >= 2);
234 /* at least one data object needs to be have a real set-packing/partitioning constraint */
235 assert(hashdata1->cons != NULL || hashdata2->cons != NULL);
236
237 if( hashdata1->nvars != hashdata2->nvars )
238 return FALSE;
239
240 for( v = hashdata1->nvars - 1; v >= 0; --v )
241 {
242 /* tests if variables are equal */
243 if( hashdata1->vars[v] != hashdata2->vars[v] )
244 return FALSE;
245
246 assert(SCIPvarCompare(hashdata1->vars[v], hashdata2->vars[v]) == 0);
247 }
248
249 /* a hashdata object is only equal if it has the same constraint pointer, or one has no constraint pointer, latter
250 * means that this hashdata object is derived from a logicor constraint
251 */
252 if( hashdata1->cons == NULL || hashdata2->cons == NULL || hashdata1->cons == hashdata2->cons )
253 return TRUE;
254 else
255 return FALSE;
256}
257
258/** returns the hash value of the key */
259static
260SCIP_DECL_HASHKEYVAL(setppcHashdataKeyValCons)
261{ /*lint --e{715}*/
262 HASHDATA* hashdata;
263
264 hashdata = (HASHDATA*)key;
265 assert(hashdata != NULL);
266 assert(hashdata->vars != NULL);
267 assert(hashdata->nvars >= 2);
268
269 return SCIPhashFour(hashdata->nvars, SCIPvarGetIndex(hashdata->vars[0]), \
270 SCIPvarGetIndex(hashdata->vars[hashdata->nvars/2]), \
271 SCIPvarGetIndex(hashdata->vars[hashdata->nvars-1]));
272}
273
274/** initialize gateextraction presolver data */
275static
277 SCIP_PRESOLDATA* presoldata /**< data object of presolver */
278 )
279{
280 assert(presoldata != NULL);
281
282 presoldata->usefullogicor = NULL;
283 presoldata->nusefullogicor = 0;
284 presoldata->susefullogicor = 0;
285 presoldata->firstchangedlogicor = -1;
286 presoldata->maxnvarslogicor = 0;;
287 presoldata->nsetppchashdatas = 0;
288 presoldata->ssetppchashdatas = 0;
289 presoldata->ngates = 0;
290 presoldata->usefulsetppcexist = FALSE;
291 presoldata->usefullogicorexist = FALSE;
292 presoldata->newsetppchashdatas = FALSE;
293 presoldata->initialized = FALSE;
294
295 presoldata->hashdatatable = NULL;
296 presoldata->setppchashtable = NULL;
297 presoldata->logicorhashtable = NULL;
298}
299
300/** initialize gateextraction hashtables */
301static
303 SCIP* scip, /**< SCIP data structure */
304 SCIP_PRESOLDATA* presoldata /**< data object of presolver */
305 )
306{
307 assert(scip != NULL);
308 assert(presoldata != NULL);
309
310 assert(presoldata->nusefullogicor == 0);
311 assert(presoldata->susefullogicor == 0);
312 assert(presoldata->nsetppchashdatas == 0);
313 assert(presoldata->ssetppchashdatas == 0);
314 assert(presoldata->firstchangedlogicor == -1);
315 assert(presoldata->ngates == 0);
316 assert(presoldata->usefullogicorexist == FALSE);
317 assert(presoldata->usefulsetppcexist == FALSE);
318 assert(presoldata->newsetppchashdatas == FALSE);
319 assert(presoldata->initialized == FALSE);
320
321 assert(presoldata->hashdatatable == NULL);
322 assert(presoldata->setppchashtable == NULL);
323 assert(presoldata->logicorhashtable == NULL);
324
325 /* create hashtables */
326 SCIP_CALL( SCIPhashtableCreate(&(presoldata->hashdatatable), SCIPblkmem(scip), HASHSIZE_SETPPCCONS,
327 SCIPhashGetKeyStandard, hashdataKeyEqCons, hashdataKeyValCons, (void*) scip) );
328 SCIP_CALL( SCIPhashtableCreate(&(presoldata->setppchashtable), SCIPblkmem(scip), HASHSIZE_SETPPCCONS,
329 SCIPhashGetKeyStandard, SCIPhashKeyEqPtr, SCIPhashKeyValPtr, (void*) scip) );
330 SCIP_CALL( SCIPhashtableCreate(&(presoldata->logicorhashtable), SCIPblkmem(scip), HASHSIZE_LOGICORCONS,
331 SCIPhashGetKeyStandard, SCIPhashKeyEqPtr, SCIPhashKeyValPtr, (void*) scip) );
332
333 return SCIP_OKAY;
334}
335
336
337/** create useful set-packing information by adding new set-packing constraints with two variables */
338static
340 SCIP* scip, /**< SCIP data structure */
341 SCIP_PRESOLDATA* presoldata, /**< data object of presolver */
342 SCIP_CONS** setppcs, /**< active setppc constraints */
343 int nsetppcs, /**< number of active setppc constraints */
344 SCIP_CONS** logicors, /**< active logicor constraints */
345 int nlogicors /**< number of active logicor constraints */
346 )
347{
348 SCIP_CONS** usefulconss;
349 int nusefulconss = 0;
350 int size;
351 int c;
352
353 assert(scip != NULL);
354 assert(presoldata != NULL);
355 assert(setppcs != NULL);
356 assert(nsetppcs > 0);
357 assert(logicors != NULL);
358 assert(nlogicors > 0);
359 assert(presoldata->setppchashtable != NULL);
360 assert(presoldata->logicorhashtable != NULL);
361
362 presoldata->initialized = TRUE;
363
364 size = MAX(nsetppcs, nlogicors);
365
366 /* temporary memory for collecting set-packing constraints */
367 SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, size) );
368
369 if( !presoldata->usefulsetppcexist )
370 {
371 /* find set-packing constraints with exactly two variables */
372 for( c = 0; c < nsetppcs; ++c )
373 {
374 assert(SCIPconsIsActive(setppcs[c]));
375
376 if( !SCIPconsIsModifiable(setppcs[c]) && SCIPconsGetNUpgradeLocks(setppcs[c]) == 0
378 && SCIPgetNVarsSetppc(scip, setppcs[c]) == 2 )
379 {
380 /* insert new element in hashtable */
381 SCIP_CALL( SCIPhashtableInsert(presoldata->setppchashtable, (void*) setppcs[c]) );
382
383 usefulconss[nusefulconss] = setppcs[c];
384 ++nusefulconss;
385 }
386 }
387
388 /* add usefulconss constraints to hashdata elements */
389 if( nusefulconss > 0 )
390 {
391 SCIP_Bool negated[2];
392 int h;
393
394 presoldata->usefulsetppcexist = TRUE;
395 presoldata->ssetppchashdatas = nusefulconss;
396
397 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(presoldata->setppchashdatas), nusefulconss) );
398
399 h = 0;
400 for( c = 0; c < nusefulconss; ++c )
401 {
402 SCIP_VAR** setppcvars = SCIPgetVarsSetppc(scip, usefulconss[c]);
403 assert(SCIPconsIsActive(usefulconss[c]));
404 assert(SCIPgetNVarsSetppc(scip, usefulconss[c]) == 2);
405
406 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(presoldata->setppchashdatas[h].vars), setppcvars, 2) );
407
408 SCIP_CALL( SCIPgetBinvarRepresentative(scip, presoldata->setppchashdatas[h].vars[0], &(presoldata->setppchashdatas[h].vars[0]), &(negated[0])) );
409 SCIP_CALL( SCIPgetBinvarRepresentative(scip, presoldata->setppchashdatas[h].vars[1], &(presoldata->setppchashdatas[h].vars[1]), &(negated[1])) );
410
411 if( SCIPvarGetStatus(presoldata->setppchashdatas[h].vars[0]) == SCIP_VARSTATUS_FIXED || SCIPvarGetStatus(presoldata->setppchashdatas[h].vars[0]) == SCIP_VARSTATUS_MULTAGGR
412 || SCIPvarGetStatus(presoldata->setppchashdatas[h].vars[1]) == SCIP_VARSTATUS_FIXED || SCIPvarGetStatus(presoldata->setppchashdatas[h].vars[1]) == SCIP_VARSTATUS_MULTAGGR )
413 {
414 SCIPfreeBlockMemoryArray(scip, &(presoldata->setppchashdatas[h].vars), 2);
415 continue;
416 }
417
418 presoldata->setppchashdatas[h].nvars = 2;
419
420 /* capture variables */
421 SCIP_CALL( SCIPcaptureVar(scip, presoldata->setppchashdatas[h].vars[0]) );
422 SCIP_CALL( SCIPcaptureVar(scip, presoldata->setppchashdatas[h].vars[1]) );
423
424 /* order the variables after their index */
425 if( SCIPvarGetIndex(presoldata->setppchashdatas[h].vars[0]) > SCIPvarGetIndex(presoldata->setppchashdatas[h].vars[1]) )
426 {
427 SCIP_VAR* tmp = presoldata->setppchashdatas[h].vars[0];
428 presoldata->setppchashdatas[h].vars[0] = presoldata->setppchashdatas[h].vars[1];
429 presoldata->setppchashdatas[h].vars[1] = tmp;
430 }
431
432 presoldata->setppchashdatas[h].cons = usefulconss[c];
433
434 SCIP_CALL( SCIPhashtableInsert(presoldata->hashdatatable, (void*) &presoldata->setppchashdatas[h]) );
435 SCIP_CALL( SCIPcaptureCons(scip, usefulconss[c]) );
436
437 ++h;
438 }
439 presoldata->nsetppchashdatas = h;
440
441 if( presoldata->nsetppchashdatas > 0 )
442 presoldata->newsetppchashdatas = TRUE;
443 }
444 }
445
446 nusefulconss = 0;
447
448 if( !presoldata->usefullogicorexist )
449 {
450 /* capture all logicor constraints */
451 for( c = 0; c < nlogicors; ++c )
452 {
453 assert(SCIPconsIsActive(logicors[c]));
454
455 if( !SCIPconsIsModifiable(logicors[c]) && SCIPconsGetNUpgradeLocks(logicors[c]) == 0
456 && SCIPgetNVarsLogicor(scip, logicors[c]) >= 3 )
457 {
458 /* insert new element in hashtable */
459 SCIP_CALL( SCIPhashtableInsert(presoldata->logicorhashtable, (void*) logicors[c]) );
460 SCIP_CALL( SCIPcaptureCons(scip, logicors[c]) );
461
462 usefulconss[nusefulconss] = logicors[c];
463 ++nusefulconss;
464
465 /* update maximal entries in a logicor constraint */
466 if( presoldata->maxnvarslogicor < SCIPgetNVarsLogicor(scip, logicors[c]) )
467 presoldata->maxnvarslogicor = SCIPgetNVarsLogicor(scip, logicors[c]);
468 }
469 }
470
471 /* no usefulconss constraints */
472 if( nusefulconss > 0 )
473 {
474 presoldata->firstchangedlogicor = 0;
475 presoldata->usefullogicorexist = TRUE;
476 presoldata->susefullogicor = nusefulconss;
477 presoldata->nusefullogicor = nusefulconss;
478 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &presoldata->usefullogicor, usefulconss, presoldata->susefullogicor) );
479 }
480 }
481
482 /* free temporary memory */
483 SCIPfreeBufferArray(scip, &usefulconss);
484
485 return SCIP_OKAY;
486}
487
488
489/** remove old setppchashdatas objects, so that the allocated memory will stay low */
490static
492 SCIP* scip, /**< SCIP data structure */
493 SCIP_PRESOLDATA* presoldata /**< data object of presolver */
494 )
495{
496 assert(scip != NULL);
497 assert(presoldata != NULL);
498
499 if( presoldata->usefulsetppcexist )
500 {
501 int c;
502
503 assert(presoldata->setppchashdatas != NULL || presoldata->nsetppchashdatas == 0);
504
505 for( c = presoldata->nsetppchashdatas - 1; c >= 0; --c )
506 {
507 SCIP_Bool removeentry = FALSE;
508
509 assert(presoldata->setppchashdatas[c].cons != NULL);
510
511 if( SCIPconsIsDeleted(presoldata->setppchashdatas[c].cons)
512 || SCIPconsIsModifiable(presoldata->setppchashdatas[c].cons)
513 || SCIPconsGetNUpgradeLocks(presoldata->setppchashdatas[c].cons) >= 1
514 || SCIPgetTypeSetppc(scip, presoldata->setppchashdatas[c].cons) != SCIP_SETPPCTYPE_PACKING
515 || SCIPgetNVarsSetppc(scip, presoldata->setppchashdatas[c].cons) != 2 )
516 {
517 removeentry = TRUE;
518 }
519 else
520 {
521 SCIP_VAR* vars[2];
522 SCIP_Bool negated[2];
523
524 SCIP_CALL( SCIPgetBinvarRepresentative(scip, presoldata->setppchashdatas[c].vars[0], &(vars[0]), &(negated[0])) );
525 SCIP_CALL( SCIPgetBinvarRepresentative(scip, presoldata->setppchashdatas[c].vars[1], &(vars[1]), &(negated[1])) );
526
529 || presoldata->setppchashdatas[c].vars[0] != vars[0] || presoldata->setppchashdatas[c].vars[1] != vars[1] )
530 {
531 removeentry = TRUE;
532 }
533 }
534
535 if( removeentry )
536 {
537 /* remove constraint from setppc-hashtable */
538 assert(SCIPhashtableExists(presoldata->setppchashtable, (void*) presoldata->setppchashdatas[c].cons));
539 SCIP_CALL( SCIPhashtableRemove(presoldata->setppchashtable, (void*) presoldata->setppchashdatas[c].cons) );
540
541 /* remove hashdata entry from hashtable */
542 SCIP_CALL( SCIPhashtableRemove(presoldata->hashdatatable, (void*) &presoldata->setppchashdatas[c]) );
543
544 /* release old constraints */
545 SCIP_CALL( SCIPreleaseCons(scip, &(presoldata->setppchashdatas[c].cons)) );
546
547 /* release variables */
548 SCIP_CALL( SCIPreleaseVar(scip, &(presoldata->setppchashdatas[c].vars[0])) );
549 SCIP_CALL( SCIPreleaseVar(scip, &(presoldata->setppchashdatas[c].vars[1])) );
550
551 /* free memory for variables */
552 SCIPfreeBlockMemoryArray(scip, &(presoldata->setppchashdatas[c].vars), 2);
553
554 if( c < presoldata->nsetppchashdatas - 1 )
555 {
556 /* remove old hashdata entry from hashtable */
557 SCIP_CALL( SCIPhashtableRemove(presoldata->hashdatatable, (void*) &presoldata->setppchashdatas[presoldata->nsetppchashdatas - 1]) );
558 }
559
560 /* move last content to free position */
561 presoldata->setppchashdatas[c].cons = presoldata->setppchashdatas[presoldata->nsetppchashdatas - 1].cons;
562 presoldata->setppchashdatas[c].vars = presoldata->setppchashdatas[presoldata->nsetppchashdatas - 1].vars;
563 presoldata->setppchashdatas[c].nvars = presoldata->setppchashdatas[presoldata->nsetppchashdatas - 1].nvars;
564
565 if( c < presoldata->nsetppchashdatas - 1 )
566 {
567 /* add new hashdata entry from hashtable */
568 SCIP_CALL( SCIPhashtableInsert(presoldata->hashdatatable, (void*) &presoldata->setppchashdatas[c]) );
569 }
570 --(presoldata->nsetppchashdatas);
571 }
572 }
573
574#ifndef NDEBUG
575 for( c = presoldata->nsetppchashdatas - 1; c >= 0; --c )
576 {
577 assert(presoldata->setppchashdatas[c].nvars == 2);
578 assert(presoldata->setppchashdatas[c].vars != NULL);
579 assert(presoldata->setppchashdatas[c].vars[0] != NULL);
580 assert(presoldata->setppchashdatas[c].vars[1] != NULL);
581 assert(presoldata->setppchashdatas[c].cons != NULL);
582 assert(SCIPconsIsActive(presoldata->setppchashdatas[c].cons));
583 assert(SCIPhashtableExists(presoldata->hashdatatable, (void*) &presoldata->setppchashdatas[c]));
584 assert(SCIPhashtableExists(presoldata->setppchashtable, (void*) presoldata->setppchashdatas[c].cons));
585 }
586#endif
587 }
588
589 return SCIP_OKAY;
590}
591
592/** refresh useful set-packing information, delete redundant constraints and add new constraints */
593static
595 SCIP* scip, /**< SCIP data structure */
596 SCIP_PRESOLDATA* presoldata, /**< data object of presolver */
597 SCIP_CONS** setppcs, /**< active setppc constraints */
598 int nsetppcs, /**< number of active setppc constraints */
599 SCIP_CONS** logicors, /**< active setppc constraints */
600 int nlogicors /**< number of active setppc constraints */
601 )
602{
603 int oldnsetppchashdatas;
604 int c;
605
606 assert(scip != NULL);
607 assert(presoldata != NULL);
608 assert(setppcs != NULL);
609 assert(nsetppcs > 0);
610 assert(logicors != NULL);
611 assert(nlogicors > 0);
612 assert(presoldata->initialized);
613 assert(presoldata->setppchashtable != NULL);
614 assert(presoldata->logicorhashtable != NULL);
615
616 /* check if there already exist some set-packing and some logicor constraints with the right amount of variables */
617 if( !presoldata->usefulsetppcexist || !presoldata->usefullogicorexist )
618 {
619 SCIP_Bool usefullogicorexisted = presoldata->usefullogicorexist;
620
621 SCIP_CALL( createPresoldata(scip, presoldata, setppcs, nsetppcs, logicors, nlogicors) );
622
623 /* if we already had useful logicor constraints but did not find any useful setppc constraint, the maximal number
624 * of variables appearing in a logicor constraint was not updated, so we do it here
625 */
626 if( usefullogicorexisted && !presoldata->usefulsetppcexist )
627 {
628 /* correct maximal number of varables in logicor constraints */
629 for( c = nlogicors - 1; c >= 0; --c )
630 {
631 assert(SCIPconsIsActive(logicors[c]));
632
633 /* update maximal entries in a logicor constraint */
634 if( presoldata->maxnvarslogicor < SCIPgetNVarsLogicor(scip, logicors[c]) )
635 presoldata->maxnvarslogicor = SCIPgetNVarsLogicor(scip, logicors[c]);
636 }
637 }
638
639 /* no correct logicor or set-packing constraints available, so abort */
640 if( !presoldata->usefulsetppcexist || !presoldata->usefullogicorexist )
641 return SCIP_OKAY;
642 }
643
644 /* correct old data */
645 SCIP_CALL( cleanupHashDatas(scip, presoldata) );
646
647 oldnsetppchashdatas = presoldata->nsetppchashdatas;
648
649 /* first update setppc part */
650 /* add new setppc constraints */
651 for( c = nsetppcs - 1; c >= 0; --c )
652 {
653 assert(SCIPconsIsActive(setppcs[c]));
654
655 if( !SCIPconsIsModifiable(setppcs[c]) && SCIPconsGetNUpgradeLocks(setppcs[c]) == 0
657 && SCIPgetNVarsSetppc(scip, setppcs[c]) == 2 )
658 {
659 /* check if constraint is new, and correct array size if necessary */
660 if( !SCIPhashtableExists(presoldata->setppchashtable, (void*) setppcs[c]) )
661 {
662 SCIP_VAR** setppcvars;
663 SCIP_Bool negated[2];
664
665 /* resize array if necessary */
666 if( presoldata->nsetppchashdatas == presoldata->ssetppchashdatas )
667 {
668 int newsize;
669 int d;
670
671 newsize = SCIPcalcMemGrowSize(scip, presoldata->nsetppchashdatas + 1);
672
673 /* array already at maximal size */
674 if( newsize <= presoldata->ssetppchashdatas )
675 return SCIP_NOMEMORY;
676
677 /* correct hashtable, remove old elements */
678 SCIPhashtableRemoveAll(presoldata->hashdatatable);
679
680 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(presoldata->setppchashdatas), presoldata->ssetppchashdatas, newsize) );
681 presoldata->ssetppchashdatas = newsize;
682
683 /* add all elements to the hashtable again */
684 for( d = presoldata->nsetppchashdatas - 1; d >= 0; --d )
685 {
686 SCIP_CALL( SCIPhashtableInsert(presoldata->hashdatatable, (void*) &presoldata->setppchashdatas[d]) );
687 }
688 }
689
690 /* insert new element in hashtable */
691 SCIP_CALL( SCIPhashtableInsert(presoldata->setppchashtable, (void*) setppcs[c]) );
692
693 assert(SCIPgetNVarsSetppc(scip, setppcs[c]) == 2);
694 setppcvars = SCIPgetVarsSetppc(scip, setppcs[c]);
695
696 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(presoldata->setppchashdatas[presoldata->nsetppchashdatas].vars), setppcvars, 2) );
697 SCIP_CALL( SCIPgetBinvarRepresentative(scip, presoldata->setppchashdatas[presoldata->nsetppchashdatas].vars[0], &(presoldata->setppchashdatas[presoldata->nsetppchashdatas].vars[0]), &(negated[0])) );
698 SCIP_CALL( SCIPgetBinvarRepresentative(scip, presoldata->setppchashdatas[presoldata->nsetppchashdatas].vars[1], &(presoldata->setppchashdatas[presoldata->nsetppchashdatas].vars[1]), &(negated[1])) );
699
700 if( SCIPvarGetStatus(presoldata->setppchashdatas[presoldata->nsetppchashdatas].vars[0]) == SCIP_VARSTATUS_FIXED || SCIPvarGetStatus(presoldata->setppchashdatas[presoldata->nsetppchashdatas].vars[0]) == SCIP_VARSTATUS_MULTAGGR
701 || SCIPvarGetStatus(presoldata->setppchashdatas[presoldata->nsetppchashdatas].vars[1]) == SCIP_VARSTATUS_FIXED || SCIPvarGetStatus(presoldata->setppchashdatas[presoldata->nsetppchashdatas].vars[1]) == SCIP_VARSTATUS_MULTAGGR )
702 {
703 SCIPfreeBlockMemoryArray(scip, &(presoldata->setppchashdatas[presoldata->nsetppchashdatas].vars), 2);
704 continue;
705 }
706
707 presoldata->setppchashdatas[presoldata->nsetppchashdatas].nvars = 2;
708
709 /* capture variables */
710 SCIP_CALL( SCIPcaptureVar(scip, presoldata->setppchashdatas[presoldata->nsetppchashdatas].vars[0]) );
711 SCIP_CALL( SCIPcaptureVar(scip, presoldata->setppchashdatas[presoldata->nsetppchashdatas].vars[1]) );
712
713 /* order the variables after their index */
714 if( SCIPvarGetIndex(presoldata->setppchashdatas[presoldata->nsetppchashdatas].vars[0]) > SCIPvarGetIndex(presoldata->setppchashdatas[presoldata->nsetppchashdatas].vars[1]) )
715 {
716 SCIP_VAR* tmp = presoldata->setppchashdatas[presoldata->nsetppchashdatas].vars[0];
717 presoldata->setppchashdatas[presoldata->nsetppchashdatas].vars[0] = presoldata->setppchashdatas[presoldata->nsetppchashdatas].vars[1];
718 presoldata->setppchashdatas[presoldata->nsetppchashdatas].vars[1] = tmp;
719 }
720
721 presoldata->setppchashdatas[presoldata->nsetppchashdatas].cons = setppcs[c];
722
723 SCIP_CALL( SCIPhashtableInsert(presoldata->hashdatatable, (void*) &presoldata->setppchashdatas[presoldata->nsetppchashdatas]) );
724 SCIP_CALL( SCIPcaptureCons(scip, setppcs[c]) );
725
726 ++(presoldata->nsetppchashdatas);
727 }
728 }
729 }
730
731 /* if we found new set-packing constraints, we want to check against all logicors */
732 if( oldnsetppchashdatas < presoldata->nsetppchashdatas )
733 presoldata->newsetppchashdatas = TRUE;
734
735 /* now logicor part */
736 /* removed last deleted logicor constraints from local presolver data */
737 while( presoldata->nusefullogicor > 0 && !SCIPconsIsActive(presoldata->usefullogicor[presoldata->nusefullogicor - 1]) )
738 {
739 SCIP_CALL( SCIPhashtableRemove(presoldata->logicorhashtable, (void*) presoldata->usefullogicor[presoldata->nusefullogicor - 1]) );
740 SCIP_CALL( SCIPreleaseCons(scip, &(presoldata->usefullogicor[presoldata->nusefullogicor - 1])) );
741
742 --(presoldata->nusefullogicor);
743 }
744
745 /* remove old inactive logicor constraints */
746 for( c = presoldata->nusefullogicor - 1; c >= 0; --c )
747 {
748 /* update maximal entries in a logicor constraint */
749 if( presoldata->maxnvarslogicor < SCIPgetNVarsLogicor(scip, presoldata->usefullogicor[c]) )
750 presoldata->maxnvarslogicor = SCIPgetNVarsLogicor(scip, presoldata->usefullogicor[c]);
751
752 if( !SCIPconsIsActive(presoldata->usefullogicor[c]) || SCIPconsIsModifiable(presoldata->usefullogicor[c])
753 || SCIPconsGetNUpgradeLocks(presoldata->usefullogicor[c]) >= 1
754 || SCIPgetNVarsLogicor(scip, presoldata->usefullogicor[c]) < 3 )
755 {
756 SCIP_CALL( SCIPhashtableRemove(presoldata->logicorhashtable, (void*) presoldata->usefullogicor[c]) );
757 SCIP_CALL( SCIPreleaseCons(scip, &(presoldata->usefullogicor[c])) );
758
759 presoldata->usefullogicor[c] = presoldata->usefullogicor[presoldata->nusefullogicor - 1];
760 --(presoldata->nusefullogicor);
761 }
762 }
763
764 presoldata->firstchangedlogicor = presoldata->nusefullogicor;
765 assert(presoldata->firstchangedlogicor >= 0);
766
767 /* add new logicor constraints */
768 for( c = nlogicors - 1; c >= 0; --c )
769 {
770 assert(SCIPconsIsActive(logicors[c]));
771
772 if( !SCIPconsIsModifiable(logicors[c]) && SCIPconsGetNUpgradeLocks(logicors[c]) == 0
773 && SCIPgetNVarsLogicor(scip, logicors[c]) >= 3 )
774 {
775 /* check if constraint is new, and correct array size if necessary */
776 if( !SCIPhashtableExists(presoldata->logicorhashtable, (void*) logicors[c]) )
777 {
778 /* resize array if necessary */
779 if( presoldata->nusefullogicor == presoldata->susefullogicor )
780 {
781 int newsize;
782
783 newsize = SCIPcalcMemGrowSize(scip, presoldata->nusefullogicor + 1);
784
785 /* array already at maximal size */
786 if( newsize <= presoldata->susefullogicor )
787 return SCIP_NOMEMORY;
788
789 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(presoldata->usefullogicor), presoldata->susefullogicor, newsize) );
790 presoldata->susefullogicor = newsize;
791 }
792
793 /* insert new element in hashtable */
794 SCIP_CALL( SCIPhashtableInsert(presoldata->logicorhashtable, (void*) logicors[c]) );
795 SCIP_CALL( SCIPcaptureCons(scip, logicors[c]) );
796
797 presoldata->usefullogicor[presoldata->nusefullogicor] = logicors[c];
798 ++(presoldata->nusefullogicor);
799
800 /* update maximal entries in a logicor constraint */
801 if( presoldata->maxnvarslogicor < SCIPgetNVarsLogicor(scip, logicors[c]) )
802 presoldata->maxnvarslogicor = SCIPgetNVarsLogicor(scip, logicors[c]);
803 }
804 }
805 }
806
807 return SCIP_OKAY;
808}
809
810
811/** extract and-constraints and set-partitioning constraints */
812static
814 SCIP* scip, /**< SCIP data structure */
815 SCIP_PRESOLDATA* presoldata, /**< data object of presolver */
816 int pos, /**< position of logicor in usefullogicor array to presolve */
817 SCIP_HASHMAP* varmap, /**< variable map mapping inactive variables to their active representation */
818 SCIP_CONS** gateconss, /**< allocated memory for all gate-constraints */
819 SCIP_VAR** activevars, /**< allocated memory for active variables */
820 SCIP_VAR** posresultants, /**< allocated memory for all possible resultant variables */
821 HASHDATA* hashdata, /**< allocated memory for a hashdata object */
822 int* ndelconss, /**< pointer to store number of deleted constraints */
823 int* naddconss /**< pointer to store number of added constraints */
824 )
825{
826 SCIP_VAR** logicorvars;
827 HASHDATA* hashmaphashdata;
828 SCIP_CONS* logicor;
829 SCIP_Bool negated;
830 int ngateconss;
831 int nlogicorvars;
832 int nposresultants;
833 int d;
834 int v;
835
836 assert(scip != NULL);
837 assert(presoldata != NULL);
838 assert(0 <= pos && pos < presoldata->nusefullogicor);
839 assert(gateconss != NULL);
840 assert(activevars != NULL);
841 assert(posresultants != NULL);
842 assert(hashdata != NULL);
843 assert(hashdata->vars != NULL);
844 assert(hashdata->nvars == 2);
845 assert(hashdata->cons == NULL);
846 assert(ndelconss != NULL);
847 assert(naddconss != NULL);
848
849 assert(presoldata->usefullogicor != NULL);
850 logicor = presoldata->usefullogicor[pos];
851 assert(logicor != NULL);
852
853 if( !SCIPconsIsActive(logicor) )
854 return SCIP_OKAY;
855
856 assert(!SCIPconsIsModifiable(logicor));
857
858 nlogicorvars = SCIPgetNVarsLogicor(scip, logicor);
859 assert(nlogicorvars >= 3 && nlogicorvars <= presoldata->maxnvarslogicor);
860
861 logicorvars = SCIPgetVarsLogicor(scip, logicor);
862 assert(logicorvars != NULL);
863
864 nposresultants = 0;
865
866 /* get active logicor variables and determine all possible resultants */
867 for( d = nlogicorvars - 1; d >= 0; --d )
868 {
869 /* do not work with fixed variables */
870 if( SCIPvarGetLbLocal(logicorvars[d]) > 0.5 || SCIPvarGetUbLocal(logicorvars[d]) < 0.5 )
871 return SCIP_OKAY;
872
873 activevars[d] = (SCIP_VAR*) SCIPhashmapGetImage(varmap, logicorvars[d]);
874
875 if( activevars[d] == NULL )
876 {
877 SCIP_CALL( SCIPgetBinvarRepresentative(scip, logicorvars[d], &(activevars[d]), &negated) );
878 SCIP_CALL( SCIPhashmapInsert(varmap, logicorvars[d], activevars[d]) );
879 }
880
881 /* determine possible resultants a check if the other variables can appear in a set-packing constraint */
882 if( SCIPvarIsNegated(activevars[d]) )
883 {
885
886 if( SCIPvarGetNLocksDownType(SCIPvarGetNegatedVar(activevars[d]), SCIP_LOCKTYPE_MODEL) >= nlogicorvars - 1 )
887 {
888 posresultants[nposresultants] = activevars[d];
889 ++nposresultants;
890 }
892 return SCIP_OKAY;
893 }
894 else
895 {
896 assert(SCIPvarIsActive(activevars[d]));
897
898 if( SCIPvarGetNLocksUpType(activevars[d], SCIP_LOCKTYPE_MODEL) >= nlogicorvars - 1 )
899 {
900 posresultants[nposresultants] = activevars[d];
901 ++nposresultants;
902 }
903 else if( SCIPvarGetNLocksUpType(activevars[d], SCIP_LOCKTYPE_MODEL) == 0 )
904 return SCIP_OKAY;
905 }
906 }
907
908 if( nposresultants == 0 )
909 return SCIP_OKAY;
910
911 /* sort variables after indices */
912 SCIPsortPtr((void**)activevars, SCIPvarComp, nlogicorvars);
913
914 /* check that we have really different variables, if not remove the constraint from the hashmap and the data
915 * storage
916 */
917 for( d = nlogicorvars - 1; d > 0; --d )
918 {
919 if( SCIPvarGetIndex(activevars[d]) == SCIPvarGetIndex(activevars[d - 1]) )
920 {
921 assert(presoldata->usefullogicor[pos] == logicor);
922
923 SCIP_CALL( SCIPhashtableRemove(presoldata->logicorhashtable, (void*) logicor) );
924 SCIP_CALL( SCIPreleaseCons(scip, &logicor) );
925
926 presoldata->usefullogicor[pos] = presoldata->usefullogicor[presoldata->nusefullogicor - 1];
927 --(presoldata->nusefullogicor);
928
929 return SCIP_OKAY;
930 }
931 }
932
933 ngateconss = 0;
934
935 for( d = nposresultants - 1; d >= 0; --d )
936 {
937 ngateconss = 0;
938
939 for( v = nlogicorvars - 1; v >= 0; --v )
940 {
941 if( activevars[v] == posresultants[d] )
942 continue;
943
944 /* variables need to be sorted */
945 if( SCIPvarCompare(posresultants[d], activevars[v]) > 0 )
946 {
947 hashdata->vars[0] = activevars[v];
948 hashdata->vars[1] = posresultants[d];
949 }
950 else
951 {
952 hashdata->vars[0] = posresultants[d];
953 hashdata->vars[1] = activevars[v];
954 }
955
956 hashmaphashdata = (HASHDATA*) SCIPhashtableRetrieve(presoldata->hashdatatable, (void*) hashdata);
957
958 if( hashmaphashdata != NULL && SCIPconsIsActive(hashmaphashdata->cons) )
959 {
960 gateconss[ngateconss] = hashmaphashdata->cons;
961 ++ngateconss;
962 }
963 else
964 break;
965 }
966 if( ngateconss == nlogicorvars - 1 )
967 break;
968 }
969
970 /* @todo, check for clique of all variables except the resultant */
971 /* check if we have a set-partitioning 'gate' */
972 if( ngateconss == nlogicorvars - 1 && nlogicorvars == 3 )
973 {
974 assert(d >= 0 && d < nposresultants);
975 assert(ngateconss >= 2);
976
977 if( activevars[0] == posresultants[d] )
978 {
979 hashdata->vars[0] = activevars[1];
980 hashdata->vars[1] = activevars[2];
981 }
982 else if( activevars[1] == posresultants[d] )
983 {
984 hashdata->vars[0] = activevars[0];
985 hashdata->vars[1] = activevars[2];
986 }
987 else
988 {
989 assert(activevars[2] == posresultants[d]);
990 hashdata->vars[0] = activevars[0];
991 hashdata->vars[1] = activevars[1];
992 }
993
994 hashmaphashdata = (HASHDATA*) SCIPhashtableRetrieve(presoldata->hashdatatable, (void*) hashdata);
995 assert(hashmaphashdata == NULL || hashmaphashdata->cons != NULL);
996
997 if( hashmaphashdata != NULL && SCIPconsIsActive(hashmaphashdata->cons) )
998 {
999 gateconss[ngateconss] = hashmaphashdata->cons;
1000 ++ngateconss;
1001 }
1002 }
1003
1004 /* did we find enough (>= number of variables in logicor - 1) set-packing constraints for an upgrade to either
1005 * an and-constraint or even a set-partitioning constraint
1006 */
1007 if( ngateconss == nlogicorvars || (ngateconss >= nlogicorvars - 1 && !presoldata->onlysetpart))
1008 {
1009 SCIP_CONS* newcons;
1010 char name[SCIP_MAXSTRLEN];
1011 SCIP_Bool initial;
1013 SCIP_Bool enforce;
1014 SCIP_Bool check;
1016 SCIP_Bool local;
1017 SCIP_Bool modifiable;
1018 SCIP_Bool dynamic;
1019 SCIP_Bool removable;
1020 SCIP_Bool stickingatnode;
1021 int i;
1022
1023 assert(ngateconss <= nlogicorvars);
1024 assert(d >= 0 && d < nposresultants);
1025
1026 initial = SCIPconsIsInitial(logicor);
1027 separate = SCIPconsIsSeparated(logicor);
1028 enforce = SCIPconsIsEnforced(logicor);
1029 check = SCIPconsIsChecked(logicor);
1031 local = SCIPconsIsLocal(logicor);
1032 modifiable = SCIPconsIsModifiable(logicor);
1033 dynamic = SCIPconsIsDynamic(logicor);
1034 removable = SCIPconsIsRemovable(logicor);
1035 stickingatnode = SCIPconsIsStickingAtNode(logicor);
1036
1037#ifdef SCIP_DEBUG
1038 if( ngateconss == nlogicorvars )
1039 {
1040 SCIPdebugMsg(scip, "Following constraints form a set-partitioning constraint.\n");
1041 }
1042 else
1043 {
1044 SCIPdebugMsg(scip, "Following constraints form an and-constraint.\n");
1045 }
1046#endif
1047
1048 for( v = ngateconss - 1; v >= 0; --v )
1049 {
1050 assert(gateconss[v] != NULL);
1051
1052 initial |= SCIPconsIsInitial(gateconss[v]);
1053 separate |= SCIPconsIsSeparated(gateconss[v]);
1054 enforce |= SCIPconsIsEnforced(gateconss[v]);
1055 check |= SCIPconsIsChecked(gateconss[v]);
1056 propagate |= SCIPconsIsPropagated(gateconss[v]);
1057 local &= SCIPconsIsLocal(gateconss[v]);
1058 modifiable &= SCIPconsIsModifiable(gateconss[v]);
1059 dynamic &= SCIPconsIsDynamic(gateconss[v]);
1060 removable &= SCIPconsIsRemovable(gateconss[v]);
1061 stickingatnode &= SCIPconsIsStickingAtNode(gateconss[v]);
1062
1063 SCIPdebugPrintCons(scip, gateconss[v], NULL);
1064
1065 SCIP_CALL( SCIPdelCons(scip, gateconss[v]) );
1066 ++(*ndelconss);
1067 }
1068
1069 SCIPdebugPrintCons(scip, logicor, NULL);
1070
1071 if( ngateconss == nlogicorvars - 1 )
1072 {
1073 SCIP_VAR** consvars;
1074
1075 assert(!presoldata->onlysetpart);
1076
1077 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, ngateconss) );
1078 i = 0;
1079
1080 /* determine and operands */
1081 for( v = nlogicorvars - 1; v >= 0; --v )
1082 {
1083 if( activevars[v] == posresultants[d] )
1084 continue;
1085
1086 SCIP_CALL( SCIPgetNegatedVar(scip, activevars[v], &consvars[i]) );
1087 ++i;
1088 }
1089 assert(i == ngateconss);
1090
1091 /* create and add "and" constraint for the extracted gate */
1092 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "andgate_%d", presoldata->ngates);
1093 SCIP_CALL( SCIPcreateConsAnd(scip, &newcons, name, posresultants[d], ngateconss, consvars,
1094 initial, separate, enforce, check, propagate,
1095 local, modifiable, dynamic, removable, stickingatnode) );
1096
1097 SCIPdebugMsg(scip, "-------------->\n");
1098 SCIPdebugPrintCons(scip, newcons, NULL);
1099 SCIP_CALL( SCIPaddCons(scip, newcons) );
1100 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
1101
1102 ++(*naddconss);
1103 ++(presoldata->ngates);
1104
1105 SCIP_CALL( SCIPdelCons(scip, logicor) );
1106 ++(*ndelconss);
1107
1108 SCIPfreeBufferArray(scip, &consvars);
1109 }
1110 else
1111 {
1112 assert(ngateconss == nlogicorvars);
1113
1114 /* create and add set-partitioning constraint */
1115 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "setpart_%d", presoldata->ngates);
1116 SCIP_CALL( SCIPcreateConsSetpart(scip, &newcons, name, nlogicorvars, activevars,
1117 initial, separate, enforce, check, propagate,
1118 local, modifiable, dynamic, removable, stickingatnode) );
1119
1120 SCIPdebugMsg(scip, "-------------->\n");
1121 SCIPdebugPrintCons(scip, newcons, NULL);
1122 SCIP_CALL( SCIPaddCons(scip, newcons) );
1123 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
1124
1125 ++(*naddconss);
1126 ++(presoldata->ngates);
1127
1128 SCIP_CALL( SCIPdelCons(scip, logicor) );
1129 ++(*ndelconss);
1130 }
1131 }
1132
1133 return SCIP_OKAY;
1134}
1135
1136
1137/*
1138 * Callback methods of presolver
1139 */
1140
1141
1142/** copy method for constraint handler plugins (called when SCIP copies plugins) */
1143static
1144SCIP_DECL_PRESOLCOPY(presolCopyGateextraction)
1145{ /*lint --e{715}*/
1146 assert(scip != NULL);
1147 assert(presol != NULL);
1148
1150
1151 /* call inclusion method of presolver */
1153
1154 return SCIP_OKAY;
1155}
1156
1157
1158/** destructor of presolver to free user data (called when SCIP is exiting) */
1159static
1160SCIP_DECL_PRESOLFREE(presolFreeGateextraction)
1161{ /*lint --e{715}*/
1162 SCIP_PRESOLDATA* presoldata;
1163
1164 /* free presolver data */
1165 presoldata = SCIPpresolGetData(presol);
1166 assert(presoldata != NULL);
1167
1168 if( presoldata->hashdatatable != NULL )
1169 {
1170 assert(presoldata->setppchashtable != NULL);
1171 assert(presoldata->logicorhashtable != NULL);
1172
1173 SCIPhashtableFree(&(presoldata->logicorhashtable));
1174 SCIPhashtableFree(&(presoldata->setppchashtable));
1175 SCIPhashtableFree(&(presoldata->hashdatatable));
1176 }
1177
1178 SCIPfreeBlockMemory(scip, &presoldata);
1179 SCIPpresolSetData(presol, NULL);
1180
1181 return SCIP_OKAY;
1182}
1183
1184
1185/** deinitialization method of presolver (called before transformed problem is freed) */
1186static
1187SCIP_DECL_PRESOLEXIT(presolExitGateextraction)
1188{ /*lint --e{715}*/
1189 SCIP_PRESOLDATA* presoldata;
1190 int c;
1191
1192 /* free presolver data */
1193 presoldata = SCIPpresolGetData(presol);
1194 assert(presoldata != NULL);
1195
1196 /* release old constraints */
1197 for( c = presoldata->nusefullogicor - 1; c >= 0; --c )
1198 {
1199 SCIP_CALL( SCIPreleaseCons(scip, &(presoldata->usefullogicor[c])) );
1200 }
1201
1202 if( presoldata->usefullogicorexist )
1203 {
1204 SCIPfreeBlockMemoryArray(scip, &presoldata->usefullogicor, presoldata->susefullogicor);
1205 }
1206
1207 if( presoldata->usefulsetppcexist )
1208 {
1209 assert(presoldata->setppchashdatas != NULL || presoldata->nsetppchashdatas == 0);
1210 for( c = presoldata->nsetppchashdatas - 1; c >= 0; --c )
1211 {
1212 assert(presoldata->setppchashdatas[c].cons != NULL);
1213 assert(presoldata->setppchashdatas[c].vars != NULL);
1214
1215 /* remove constraint from setppc-hashtable */
1216 assert(SCIPhashtableExists(presoldata->setppchashtable, (void*) presoldata->setppchashdatas[c].cons));
1217 SCIP_CALL( SCIPhashtableRemove(presoldata->setppchashtable, (void*) presoldata->setppchashdatas[c].cons) );
1218
1219 /* remove hashdata entry from hashtable */
1220 SCIP_CALL( SCIPhashtableRemove(presoldata->hashdatatable, (void*) &presoldata->setppchashdatas[c]) );
1221
1222 /* release old constraints */
1223 SCIP_CALL( SCIPreleaseCons(scip, &(presoldata->setppchashdatas[c].cons)) );
1224
1225 /* release variables */
1226 SCIP_CALL( SCIPreleaseVar(scip, &(presoldata->setppchashdatas[c].vars[0])) );
1227 SCIP_CALL( SCIPreleaseVar(scip, &(presoldata->setppchashdatas[c].vars[1])) );
1228
1229 /* free memory for variables */
1230 SCIPfreeBlockMemoryArray(scip, &(presoldata->setppchashdatas[c].vars), 2);
1231 }
1232
1233 SCIPfreeBlockMemoryArray(scip, &(presoldata->setppchashdatas), presoldata->ssetppchashdatas);
1234 }
1235
1236 if( presoldata->hashdatatable != NULL )
1237 {
1238 assert(presoldata->setppchashtable != NULL);
1239 assert(presoldata->logicorhashtable != NULL);
1240
1241 /* clear old hashtable entries */
1242 SCIPhashtableRemoveAll(presoldata->hashdatatable);
1243 SCIPhashtableRemoveAll(presoldata->setppchashtable);
1244 SCIPhashtableRemoveAll(presoldata->logicorhashtable);
1245 }
1246
1247 presoldata->nusefullogicor = 0;
1248 presoldata->susefullogicor = 0;
1249 presoldata->nsetppchashdatas = 0;
1250 presoldata->ssetppchashdatas = 0;
1251 presoldata->firstchangedlogicor = -1;
1252 presoldata->ngates = 0;
1253 presoldata->usefullogicorexist = FALSE;
1254 presoldata->usefulsetppcexist = FALSE;
1255 presoldata->newsetppchashdatas = FALSE;
1256 presoldata->initialized = FALSE;
1257
1258 return SCIP_OKAY;
1259}
1260
1261
1262/** presolving initialization method of presolver (called when presolving is about to begin) */
1263static
1264SCIP_DECL_PRESOLINITPRE(presolInitpreGateextraction)
1265{ /*lint --e{715}*/
1266 return SCIP_OKAY;
1267}
1268
1269
1270/** presolving deinitialization method of presolver (called after presolving has been finished) */
1271static
1272SCIP_DECL_PRESOLEXITPRE(presolExitpreGateextraction)
1273{ /*lint --e{715}*/
1274 return SCIP_OKAY;
1275}
1276
1277
1278/** execution method of presolver */
1279static
1280SCIP_DECL_PRESOLEXEC(presolExecGateextraction)
1281{ /*lint --e{715}*/
1282 SCIP_PRESOLDATA* presoldata;
1283 SCIP_HASHMAP* varmap;
1284 HASHDATA hashdata;
1285 SCIP_VAR* tmpvars[2];
1286 SCIP_CONSHDLR* conshdlrsetppc;
1287 SCIP_CONSHDLR* conshdlrlogicor;
1288 SCIP_CONSHDLR* conshdlrand;
1289 SCIP_CONS** setppcconss;
1290 SCIP_CONS** logicorconss;
1291 int nsetppcconss;
1292 int nlogicorconss;
1293 int size;
1294 int c;
1295 SCIP_Bool paramvalue;
1296
1297 assert(scip != NULL);
1298 assert(presol != NULL);
1299 assert(result != NULL);
1300
1302
1304
1305#ifdef SCIP_DISABLED_CODE
1306 /* need to include cons_knapsack on top of this file */
1307 /* check for possible knapsacks that form with a logicor a weak relaxation of an and-constraint
1308 *
1309 * the weak relaxation of an and-constraint looks like:
1310 * - row1: resvar - v1 - ... - vn >= 1-n
1311 * - row2: n*resvar - v1 - ... - vn <= 0.0
1312 *
1313 * which look like the following contraints
1314 * - logicor: resvar + ~v1 + ... + ~vn >= 1
1315 * - knapsack: n*resvar + ~v1 + ... + ~vn <= n
1316 */
1317 {
1318 SCIP_CONSHDLR* conshdlrknapsack;
1319 SCIP_CONS** knapsackconss;
1320 int nknapsackconss;
1321 SCIP_Longint* vals;
1322 SCIP_Longint capacity;
1323 int nvars;
1324
1325 conshdlrknapsack = SCIPfindConshdlr(scip, "knapsack");
1326
1327 /* get number of active constraints */
1328 knapsackconss = SCIPconshdlrGetConss(conshdlrknapsack);
1329 nknapsackconss = SCIPconshdlrGetNActiveConss(conshdlrknapsack);
1330 assert(nknapsackconss >= 0);
1331 assert(knapsackconss != NULL || nknapsackconss == 0);
1332
1333 for( c = nknapsackconss - 1; c >= 0; --c )
1334 {
1335 /* not implemented in master branch, but the constraint may be already sorted */
1336 /*SCIPsortKnapsack(scip, knapsackconss[c]);*/
1337
1338 nvars = SCIPgetNVarsKnapsack(scip, knapsackconss[c]);
1339 vals = SCIPgetWeightsKnapsack(scip, knapsackconss[c]);
1340 capacity = SCIPgetCapacityKnapsack(scip, knapsackconss[c]);
1341
1342 if( nvars > 1 && capacity == nvars - 1 && vals[0] == capacity && vals[1] == 1 )
1343 {
1344 printf("possible knapsack for gate extraction\n");
1345 }
1346 }
1347 }
1348#endif
1349
1350 /* get necessary constraint handlers */
1351 conshdlrsetppc = SCIPfindConshdlr(scip, "setppc");
1352 conshdlrlogicor = SCIPfindConshdlr(scip, "logicor");
1353
1354 if( conshdlrsetppc == NULL || conshdlrlogicor == NULL )
1355 return SCIP_OKAY;
1356
1357 /* get number of active constraints */
1358 nsetppcconss = SCIPconshdlrGetNActiveConss(conshdlrsetppc);
1359 assert(nsetppcconss >= 0);
1360 nlogicorconss = SCIPconshdlrGetNActiveConss(conshdlrlogicor);
1361 assert(nlogicorconss >= 0);
1362
1363 if( nsetppcconss == 0 || nlogicorconss == 0 )
1364 return SCIP_OKAY;
1365
1366 /* get presolver data */
1367 presoldata = SCIPpresolGetData(presol);
1368 assert(presoldata != NULL);
1369
1370 conshdlrand = SCIPfindConshdlr(scip, "and");
1371
1372 /* need and-constraint handler to extract and-gates */
1373 if( conshdlrand == NULL )
1374 {
1375 /* nothing to do when we cannot extract anything */
1376 if( !presoldata->searchequations )
1377 return SCIP_OKAY;
1378 else
1379 {
1380 /* make sure that we correct the parameter for only extrating set-partitioning constraints */
1381 if( SCIPisParamFixed(scip, "presolving/" PRESOL_NAME "/onlysetpart") )
1382 {
1383 SCIPwarningMessage(scip, "unfixing parameter <presolving/" PRESOL_NAME "/onlysetpart> in gate extration presolver\n");
1384 SCIP_CALL( SCIPunfixParam(scip, "presolving/" PRESOL_NAME "/onlysetpart") );
1385 }
1386 SCIP_CALL( SCIPsetBoolParam(scip, "presolving/" PRESOL_NAME "/onlysetpart", TRUE) );
1387 assert(presoldata->onlysetpart);
1388 }
1389 }
1390
1391 paramvalue = FALSE;
1392 if( conshdlrand != NULL && SCIPgetBoolParam(scip, "constraints/and/linearize", &paramvalue) == SCIP_OKAY )
1393 {
1394 if( paramvalue )
1395 {
1396 SCIPwarningMessage(scip, "Gate-presolving is the 'counterpart' of linearizing all and-constraints, so enabling both presolving steps simultaneously does not make sense.\n");
1397 }
1398 }
1400
1401 /* get active constraints */
1402 SCIP_CALL( SCIPduplicateBufferArray(scip, &setppcconss, SCIPconshdlrGetConss(conshdlrsetppc), nsetppcconss) ); /*lint !e666*/
1403
1404 assert(setppcconss != NULL);
1405 logicorconss = SCIPconshdlrGetConss(conshdlrlogicor);
1406 assert(logicorconss != NULL);
1407
1408 /* first we need to initialized the hashtables if not yet done */
1409 if( presoldata->hashdatatable == NULL )
1410 {
1411 SCIP_CALL( presoldataInitHashtables(scip, presoldata) );
1412 }
1413 assert(presoldata->hashdatatable != NULL);
1414 assert(presoldata->setppchashtable != NULL);
1415 assert(presoldata->logicorhashtable != NULL);
1416
1417 presoldata->newsetppchashdatas = FALSE;
1418
1419 if( !presoldata->initialized )
1420 {
1421 assert(presoldata->usefullogicor == NULL);
1422
1423 /* create useful set-packing information by adding new set-packing constraints with two variables */
1424 SCIP_CALL( createPresoldata(scip, presoldata, setppcconss, nsetppcconss, logicorconss, nlogicorconss) );
1425 }
1426 else
1427 {
1428 /* refresh useful set-packing information, delete redundant constraints and add new constraints */
1429 SCIP_CALL( correctPresoldata(scip, presoldata, setppcconss, nsetppcconss, logicorconss, nlogicorconss) );
1430 }
1431 assert(presoldata->initialized);
1432
1433 if( presoldata->nusefullogicor == 0 )
1434 goto TERMINATE;
1435
1436 /* move the biggate extraction to front or back by sort the logicors after number of variables */
1437
1438 if( presoldata->sorting != 0 )
1439 {
1440 int* lengths;
1441
1442 SCIP_CALL( SCIPallocBufferArray(scip, &lengths, presoldata->nusefullogicor) );
1443
1444 for( c = presoldata->nusefullogicor - 1; c >= 0; --c )
1445 {
1446 lengths[c] = SCIPgetNVarsLogicor(scip, presoldata->usefullogicor[c]);
1447 }
1448
1449 if( presoldata->sorting == -1 )
1450 SCIPsortDownIntPtr(lengths, (void**)presoldata->usefullogicor, presoldata->nusefullogicor);
1451 else
1452 SCIPsortIntPtr(lengths, (void**)presoldata->usefullogicor, presoldata->nusefullogicor);
1453
1454 SCIPfreeBufferArray(scip, &lengths);
1455 }
1456
1457 /* maximal number of binary variables */
1459
1460 /* create the variable mapping hash map */
1461 SCIP_CALL( SCIPhashmapCreate(&varmap, SCIPblkmem(scip), size) );
1462
1463 /* search for set-partitioning constraints arising from a logicor and a set-packing constraints with equal variables */
1464 if( presoldata->searchequations && !SCIPisStopped(scip) )
1465 {
1466 SCIP_HASHTABLE* setppchashdatatable;
1467 HASHDATA** setppchashdatas;
1468 HASHDATA* setppchashdatastore;
1469 HASHDATA* hashmaphashdata;
1470 SCIP_CONS* logicor;
1471 SCIP_CONS* setppc;
1472 SCIP_VAR** logicorvars;
1473 SCIP_VAR** setppcvars;
1474 SCIP_VAR** activevarslogicor;
1475 SCIP_VAR** activevarssetppc;
1476 SCIP_Bool negated;
1477 int nsetppchashdatas;
1478 int nlogicorvars;
1479 int nsetppcvars;
1480 int d;
1481 int v;
1482
1483 assert(nsetppcconss > 0);
1484
1485 /* create local hashtable */
1486 SCIP_CALL( SCIPhashtableCreate(&setppchashdatatable, SCIPblkmem(scip), nsetppcconss, SCIPhashGetKeyStandard, setppcHashdataKeyEqCons, setppcHashdataKeyValCons, (void*) scip) );
1487
1488 /* maximal number of binary variables */
1489 size = presoldata->maxnvarslogicor;
1490 assert(size >= 3);
1491
1492 /* get temporary memory */
1493 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &setppchashdatastore, nsetppcconss) );
1494 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &setppchashdatas, nsetppcconss) );
1495 SCIP_CALL( SCIPallocBufferArray(scip, &activevarssetppc, size) );
1496 SCIP_CALL( SCIPallocBufferArray(scip, &activevarslogicor, size) );
1497
1498 hashdata.cons = NULL;
1499
1500 nsetppchashdatas = 0;
1501
1502 /* collect all set-packing/-partitioning constraints and corresponding data to be able to search faster */
1503 for( d = nsetppcconss - 1; d >= 0; --d )
1504 {
1505 setppc = setppcconss[d];
1506 assert(setppc != NULL);
1507
1508 if( SCIPconsIsDeleted(setppc) || SCIPconsIsModifiable(setppc) || SCIPconsGetNUpgradeLocks(setppc) >= 1 )
1509 continue;
1510
1511 /* @todo if of interest could also be implemented for set-covering constraints */
1512#if 1
1514 continue;
1515#endif
1516
1517 nsetppcvars = SCIPgetNVarsSetppc(scip, setppc);
1518
1519 /* to big setppc constraints are picked out */
1520 if( nsetppcvars < 2 || nsetppcvars > size )
1521 continue;
1522
1523 setppcvars = SCIPgetVarsSetppc(scip, setppc);
1524 assert(setppcvars != NULL);
1525
1526 /* get active setppc variables */
1527 for( v = nsetppcvars - 1; v >= 0; --v )
1528 {
1529 /* do not work with fixed variables */
1530 if( SCIPvarGetLbLocal(setppcvars[v]) > 0.5 || SCIPvarGetUbLocal(setppcvars[v]) < 0.5 )
1531 break;
1532
1533 activevarssetppc[v] = (SCIP_VAR*) SCIPhashmapGetImage(varmap, setppcvars[v]);
1534
1535 if( activevarssetppc[v] == NULL )
1536 {
1537 SCIP_CALL( SCIPgetBinvarRepresentative(scip, setppcvars[v], &(activevarssetppc[v]), &negated) );
1538 SCIP_CALL( SCIPhashmapInsert(varmap, setppcvars[v], activevarssetppc[v]) );
1539 }
1540 }
1541
1542 /* if we found a fixed variable we want disregard this constraint */
1543 if( v >= 0 )
1544 continue;
1545
1546 /* variables need to be sorted after indices to be able to do a fast comparison */
1547 SCIPsortPtr((void**)activevarssetppc, SCIPvarComp, nsetppcvars);
1548
1549 setppchashdatas[nsetppchashdatas] = &(setppchashdatastore[nsetppchashdatas]);
1550
1551 /* memorize set-packing data */
1552 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(setppchashdatas[nsetppchashdatas]->vars), activevarssetppc, nsetppcvars) );
1553
1554 setppchashdatas[nsetppchashdatas]->nvars = nsetppcvars;
1555 setppchashdatas[nsetppchashdatas]->cons = setppc;
1556 /* need to capture this constraint, because it might get deleted during the process */
1557 SCIP_CALL( SCIPcaptureCons(scip, setppc) );
1558
1559 /* add entry to local hashtable */
1560 SCIP_CALL( SCIPhashtableInsert(setppchashdatatable, (void*) setppchashdatas[nsetppchashdatas]) );
1561 ++nsetppchashdatas;
1562 }
1563
1564 /* check all (new) logicors against all collected set-packing/-partitioning constraints */
1565 for( c = nlogicorconss - 1; c >= 0 && !SCIPisStopped(scip); --c )
1566 {
1567 logicor = logicorconss[c];
1568 assert(logicor != NULL);
1569
1570 if( SCIPconsIsDeleted(logicor) || SCIPconsIsModifiable(logicor) || SCIPconsGetNUpgradeLocks(logicor) >= 1 )
1571 continue;
1572
1573 nlogicorvars = SCIPgetNVarsLogicor(scip, logicor);
1574
1575 if( nlogicorvars < 2 )
1576 continue;
1577
1578 assert(nlogicorvars <= size);
1579
1580 logicorvars = SCIPgetVarsLogicor(scip, logicor);
1581 assert(logicorvars != NULL);
1582
1583 /* get active logicor variables */
1584 for( v = nlogicorvars - 1; v >= 0; --v )
1585 {
1586 /* do not work with fixed variables */
1587 if( SCIPvarGetLbLocal(logicorvars[v]) > 0.5 || SCIPvarGetUbLocal(logicorvars[v]) < 0.5 )
1588 break;
1589
1590 activevarslogicor[v] = (SCIP_VAR*) SCIPhashmapGetImage(varmap, logicorvars[v]);
1591
1592 /* if image does not exist, then there is no corresponding set-packing constraint */
1593 if( activevarslogicor[v] == NULL )
1594 break;
1595 }
1596
1597 if( v == -1 )
1598 {
1599 /* need sorting to be able to find the correct hashdata element */
1600 SCIPsortPtr((void**)activevarslogicor, SCIPvarComp, nlogicorvars);
1601
1602 hashdata.nvars = nlogicorvars;
1603 hashdata.vars = activevarslogicor;
1604
1605 hashmaphashdata = (HASHDATA*) SCIPhashtableRetrieve(setppchashdatatable, (void*) &hashdata);
1606 assert(hashmaphashdata == NULL || hashmaphashdata->cons != NULL);
1607
1608 if( hashmaphashdata != NULL && !SCIPconsIsDeleted(hashmaphashdata->cons) )
1609 {
1610 SCIP_Bool initial;
1612 SCIP_Bool enforce;
1613 SCIP_Bool check;
1615 SCIP_Bool local;
1616 SCIP_Bool modifiable;
1617 SCIP_Bool dynamic;
1618 SCIP_Bool removable;
1619 SCIP_Bool stickingatnode;
1620
1621 setppc = hashmaphashdata->cons;
1622 assert(SCIPconsGetHdlr(setppc) == SCIPfindConshdlr(scip, "setppc"));
1623
1624 initial = SCIPconsIsInitial(logicor) || SCIPconsIsInitial(setppc);
1625 separate = SCIPconsIsSeparated(logicor) || SCIPconsIsSeparated(setppc);
1626 enforce = SCIPconsIsEnforced(logicor) || SCIPconsIsEnforced(setppc);
1627 check = SCIPconsIsChecked(logicor) || SCIPconsIsChecked(setppc);
1629 local = SCIPconsIsLocal(logicor) && SCIPconsIsLocal(setppc);
1630 modifiable = SCIPconsIsModifiable(logicor) && SCIPconsIsModifiable(setppc);
1631 dynamic = SCIPconsIsDynamic(logicor) && SCIPconsIsDynamic(setppc);
1632 removable = SCIPconsIsRemovable(logicor) && SCIPconsIsRemovable(setppc);
1633 stickingatnode = SCIPconsIsStickingAtNode(logicor) && SCIPconsIsStickingAtNode(setppc);
1634
1635 /* check if logicor is redundant against a set-partitioning constraint */
1637 {
1638 SCIP_CALL( SCIPsetConsInitial(scip, setppc, initial) );
1640 SCIP_CALL( SCIPsetConsEnforced(scip, setppc, enforce) );
1641 SCIP_CALL( SCIPsetConsChecked(scip, setppc, check) );
1643 SCIP_CALL( SCIPsetConsLocal(scip, setppc, local) );
1644 SCIP_CALL( SCIPsetConsModifiable(scip, setppc, modifiable) );
1645 SCIP_CALL( SCIPsetConsDynamic(scip, setppc, dynamic) );
1646 SCIP_CALL( SCIPsetConsRemovable(scip, setppc, removable) );
1647 SCIP_CALL( SCIPsetConsStickingAtNode(scip, setppc, stickingatnode) );
1648
1649 SCIPdebugMsg(scip, "Following logicor is redundant to the set-partitioning constraint.\n");
1650 SCIPdebugPrintCons(scip, logicor, NULL);
1651 SCIPdebugPrintCons(scip, setppc, NULL);
1652 }
1653 else
1654 {
1655 SCIP_CONS* newcons;
1656 char name[SCIP_MAXSTRLEN];
1657
1659
1660 SCIPdebugMsg(scip, "Following logicor and set-packing constraints form a set-partitioning constraint.\n");
1661 SCIPdebugPrintCons(scip, logicor, NULL);
1662 SCIPdebugPrintCons(scip, setppc, NULL);
1663
1664 /* create and add set-partitioning constraint */
1665 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "setpart_%d", presoldata->ngates);
1666 SCIP_CALL( SCIPcreateConsSetpart(scip, &newcons, name, nlogicorvars, activevarslogicor,
1667 initial, separate, enforce, check, propagate,
1668 local, modifiable, dynamic, removable, stickingatnode) );
1669
1670 SCIPdebugMsg(scip, "-------------->\n");
1671 SCIPdebugPrintCons(scip, newcons, NULL);
1672 SCIP_CALL( SCIPaddCons(scip, newcons) );
1673 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
1674
1675 ++(*naddconss);
1676 ++(presoldata->ngates);
1677
1678 /* delete redundant set-packing constraint */
1679 SCIP_CALL( SCIPdelCons(scip, setppc) );
1680 ++(*ndelconss);
1681 }
1682
1683 /* delete redundant logicor constraint */
1684 SCIP_CALL( SCIPdelCons(scip, logicor) );
1685 ++(*ndelconss);
1686 }
1687 }
1688 }
1689
1690 /* need to clear/release parts of hashdata objects */
1691 for( d = nsetppchashdatas - 1; d >= 0; --d )
1692 {
1693 /* need to release captured constraint */
1694 SCIP_CALL( SCIPreleaseCons(scip, &(setppchashdatas[d]->cons)) );
1695 /* need to free copied memory */
1696 SCIPfreeBlockMemoryArray(scip, &(setppchashdatas[d]->vars), setppchashdatas[d]->nvars);
1697 }
1698
1699 /* delete local hashtable */
1700 SCIPhashtableFree(&setppchashdatatable);
1701
1702 /* free all temporary memory */
1703 SCIPfreeBufferArray(scip, &activevarslogicor);
1704 SCIPfreeBufferArray(scip, &activevarssetppc);
1705 SCIPfreeBlockMemoryArray(scip, &setppchashdatas, nsetppcconss);
1706 SCIPfreeBlockMemoryArray(scip, &setppchashdatastore, nsetppcconss);
1707 }
1708
1709 /* we do not have any useful set-packing or logicor constraint, or since last run did not get any new constraints, so abort */
1710 if( presoldata->nsetppchashdatas == 0 || (presoldata->firstchangedlogicor == presoldata->nusefullogicor && !presoldata->newsetppchashdatas) )
1711 {
1712 SCIPhashmapFree(&varmap);
1713 goto TERMINATE;
1714 }
1715
1716 assert(presoldata->usefullogicor != NULL);
1717 assert(presoldata->nusefullogicor > 0);
1718 assert(presoldata->firstchangedlogicor >= 0);
1719 assert(presoldata->nsetppchashdatas > 0);
1720
1721 /* search for gates */
1722 if( presoldata->nsetppchashdatas > 0 && !SCIPisStopped(scip) )
1723 {
1724 SCIP_CONS** gateconss;
1725 SCIP_VAR** activevars;
1726 SCIP_VAR** posresultants;
1727 int endloop;
1728
1729 /* if we found new setppcs we want to check all logicors again */
1730 if( presoldata->newsetppchashdatas )
1731 endloop = 0;
1732 else
1733 endloop = MAX(presoldata->firstchangedlogicor, 0);
1734
1735 assert(presoldata->maxnvarslogicor >= 3);
1736 SCIP_CALL( SCIPallocBufferArray(scip, &gateconss, presoldata->maxnvarslogicor) );
1737 SCIP_CALL( SCIPallocBufferArray(scip, &activevars, presoldata->maxnvarslogicor) );
1738 SCIP_CALL( SCIPallocBufferArray(scip, &posresultants, presoldata->maxnvarslogicor) );
1739
1740 hashdata.nvars = 2;
1741 hashdata.cons = NULL;
1742 /* assign array of two variables as temporary storage to hashdata */
1743 hashdata.vars = tmpvars;
1744
1745 /* check all (new) logicors against all set-packing constraints, to extract and-constraints with two or more
1746 * operands or set-partitioning constraints three or more variables
1747 */
1748 for( c = presoldata->nusefullogicor - 1; c >= endloop && !SCIPisStopped(scip); --c )
1749 {
1750 assert(presoldata->usefullogicor[c] != NULL);
1751
1752 /* logicor constraint has the form: x + y + z >= 1
1753 *
1754 * find set-packing constraints: (~x + ~y >= 1 and ~x + ~z >= 1) <=> (x + y <= 1 and x + z <= 1)
1755 *
1756 * - these three constraints are equivalent to: x = ~y * ~z (x = AND(~y,~z))
1757 *
1758 * if an additional set-packing constraint exists: y + z <= 1
1759 *
1760 * - these four constraints are equivalent to: x + y + z = 1
1761 */
1762 SCIP_CALL( extractGates(scip, presoldata, c, varmap, gateconss, activevars, posresultants, &hashdata, ndelconss, naddconss) );
1763 }
1764
1765 SCIPfreeBufferArray(scip, &posresultants);
1766 SCIPfreeBufferArray(scip, &activevars);
1767 SCIPfreeBufferArray(scip, &gateconss);
1768 }
1769
1770 SCIPhashmapFree(&varmap);
1771
1772 TERMINATE:
1773 SCIPfreeBufferArray(scip, &setppcconss);
1774
1775 /* remove old setppchashdatas objects */
1776 SCIP_CALL( cleanupHashDatas(scip, presoldata) );
1777
1778 return SCIP_OKAY;
1779}
1780
1781
1782/*
1783 * presolver specific interface methods
1784 */
1785
1786/** creates the gateextraction presolver and includes it in SCIP */
1788 SCIP* scip /**< SCIP data structure */
1789 )
1790{
1791 SCIP_PRESOLDATA* presoldata;
1792 SCIP_PRESOL* presol;
1793
1794 /* alloc presolve data object */
1795 SCIP_CALL( SCIPallocBlockMemory(scip, &presoldata) );
1796
1797 /* initialize gateextraction presolver data */
1798 presoldataInit(presoldata);
1799
1800 /* include presolver */
1802 PRESOL_TIMING, presolExecGateextraction, presoldata) );
1803
1804 SCIP_CALL( SCIPsetPresolCopy(scip, presol, presolCopyGateextraction) );
1805 SCIP_CALL( SCIPsetPresolFree(scip, presol, presolFreeGateextraction) );
1806 SCIP_CALL( SCIPsetPresolExit(scip, presol, presolExitGateextraction) );
1807 SCIP_CALL( SCIPsetPresolInitpre(scip, presol, presolInitpreGateextraction) );
1808 SCIP_CALL( SCIPsetPresolExitpre(scip, presol, presolExitpreGateextraction) );
1809
1810 /* add gateextraction presolver parameters */
1812 "presolving/" PRESOL_NAME "/onlysetpart",
1813 "should we only try to extract set-partitioning constraints and no and-constraints",
1814 &presoldata->onlysetpart, TRUE, DEFAULT_ONLYSETPART, NULL, NULL) );
1815
1816 /* add gateextraction presolver parameters */
1818 "presolving/" PRESOL_NAME "/searchequations",
1819 "should we try to extract set-partitioning constraint out of one logicor and one corresponding set-packing constraint",
1820 &presoldata->searchequations, TRUE, DEFAULT_SEARCHEQUATIONS, NULL, NULL) );
1821
1822 /* add gateextraction presolver parameters */
1824 "presolving/" PRESOL_NAME "/sorting",
1825 "order logicor contraints to extract big-gates before smaller ones (-1), do not order them (0) or order them to extract smaller gates at first (1)",
1826 &presoldata->sorting, TRUE, DEFAULT_SORTING, -1, 1, NULL, NULL) );
1827
1828 return SCIP_OKAY;
1829}
SCIP_VAR * h
Constraint handler for AND constraints, .
#define HASHSIZE_LOGICORCONS
Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
#define HASHSIZE_SETPPCCONS
Definition cons_setppc.c:96
Constraint handler for the set partitioning / packing / covering constraints .
#define NULL
Definition def.h:257
#define SCIP_MAXSTRLEN
Definition def.h:278
#define SCIP_Longint
Definition def.h:150
#define SCIP_Bool
Definition def.h:100
#define SCIP_STRINGEQ(name, reference, retcode)
Definition def.h:454
#define TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#define MAX(x, y)
Definition def.h:229
#define SCIP_CALL(x)
Definition def.h:364
int SCIPgetNVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNVarsLogicor(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsAnd(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *resvar, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition cons_and.c:5059
int SCIPgetNVarsSetppc(SCIP *scip, SCIP_CONS *cons)
SCIP_VAR ** SCIPgetVarsSetppc(SCIP *scip, SCIP_CONS *cons)
SCIP_Longint * SCIPgetWeightsKnapsack(SCIP *scip, SCIP_CONS *cons)
SCIP_Longint SCIPgetCapacityKnapsack(SCIP *scip, SCIP_CONS *cons)
SCIP_SETPPCTYPE SCIPgetTypeSetppc(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsSetpart(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_VAR ** SCIPgetVarsLogicor(SCIP *scip, SCIP_CONS *cons)
@ SCIP_SETPPCTYPE_PARTITIONING
Definition cons_setppc.h:87
@ SCIP_SETPPCTYPE_COVERING
Definition cons_setppc.h:89
@ SCIP_SETPPCTYPE_PACKING
Definition cons_setppc.h:88
SCIP_Bool SCIPisStopped(SCIP *scip)
int SCIPgetNImplVars(SCIP *scip)
Definition scip_prob.c:2387
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition scip_prob.c:3274
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition scip_prob.c:3420
int SCIPgetNBinVars(SCIP *scip)
Definition scip_prob.c:2293
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition misc.c:3095
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition misc.c:3284
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition misc.c:3143
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition misc.c:3061
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition misc.c:2348
SCIP_Bool SCIPhashtableExists(SCIP_HASHTABLE *hashtable, void *element)
Definition misc.c:2647
#define SCIPhashFour(a, b, c, d)
Definition pub_misc.h:573
SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition misc.c:2298
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition misc.c:2596
void SCIPhashtableRemoveAll(SCIP_HASHTABLE *hashtable)
Definition misc.c:2743
SCIP_RETCODE SCIPhashtableRemove(SCIP_HASHTABLE *hashtable, void *element)
Definition misc.c:2665
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition misc.c:2535
#define SCIPdebugMsg
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
Definition scip_param.c:250
SCIP_Bool SCIPisParamFixed(SCIP *scip, const char *name)
Definition scip_param.c:219
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:83
SCIP_RETCODE SCIPunfixParam(SCIP *scip, const char *name)
Definition scip_param.c:385
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:57
SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
Definition scip_param.c:429
SCIP_RETCODE SCIPincludePresolGateextraction(SCIP *scip)
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition scip_cons.c:940
int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4816
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4739
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition cons.c:8652
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition cons.c:8413
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition cons.c:8562
SCIP_RETCODE SCIPsetConsStickingAtNode(SCIP *scip, SCIP_CONS *cons, SCIP_Bool stickingatnode)
Definition scip_cons.c:1499
int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
Definition cons.c:8845
SCIP_RETCODE SCIPsetConsSeparated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool separate)
Definition scip_cons.c:1296
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition cons.c:8592
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition cons.c:8522
SCIP_RETCODE SCIPsetConsDynamic(SCIP *scip, SCIP_CONS *cons, SCIP_Bool dynamic)
Definition scip_cons.c:1449
SCIP_RETCODE SCIPsetConsInitial(SCIP *scip, SCIP_CONS *cons, SCIP_Bool initial)
Definition scip_cons.c:1271
SCIP_RETCODE SCIPsetConsEnforced(SCIP *scip, SCIP_CONS *cons, SCIP_Bool enforce)
Definition scip_cons.c:1321
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition cons.c:8582
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition cons.c:8454
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition cons.c:8612
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition cons.c:8632
SCIP_RETCODE SCIPsetConsModifiable(SCIP *scip, SCIP_CONS *cons, SCIP_Bool modifiable)
Definition scip_cons.c:1424
SCIP_RETCODE SCIPsetConsRemovable(SCIP *scip, SCIP_CONS *cons, SCIP_Bool removable)
Definition scip_cons.c:1474
SCIP_RETCODE SCIPsetConsLocal(SCIP *scip, SCIP_CONS *cons, SCIP_Bool local)
Definition scip_cons.c:1398
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition cons.c:8642
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition cons.c:8672
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition scip_cons.c:1173
SCIP_RETCODE SCIPsetConsPropagated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool propagate)
Definition scip_cons.c:1371
SCIP_RETCODE SCIPsetConsChecked(SCIP *scip, SCIP_CONS *cons, SCIP_Bool check)
Definition scip_cons.c:1346
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition cons.c:8572
SCIP_RETCODE SCIPcaptureCons(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:1138
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition cons.c:8662
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:110
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition scip_mem.c:57
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition scip_mem.c:139
#define SCIPallocBufferArray(scip, ptr, num)
Definition scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition scip_mem.h:136
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition scip_mem.h:132
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:93
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition scip_mem.h:99
#define SCIPfreeBlockMemory(scip, ptr)
Definition scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition scip_mem.h:89
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition scip_mem.h:105
SCIP_RETCODE SCIPsetPresolExit(SCIP *scip, SCIP_PRESOL *presol,)
SCIP_RETCODE SCIPsetPresolExitpre(SCIP *scip, SCIP_PRESOL *presol,)
SCIP_RETCODE SCIPsetPresolFree(SCIP *scip, SCIP_PRESOL *presol,)
void SCIPpresolSetData(SCIP_PRESOL *presol, SCIP_PRESOLDATA *presoldata)
Definition presol.c:538
SCIP_PRESOLDATA * SCIPpresolGetData(SCIP_PRESOL *presol)
Definition presol.c:528
SCIP_RETCODE SCIPsetPresolInitpre(SCIP *scip, SCIP_PRESOL *presol,)
SCIP_RETCODE SCIPsetPresolCopy(SCIP *scip, SCIP_PRESOL *presol,)
SCIP_RETCODE SCIPincludePresolBasic(SCIP *scip, SCIP_PRESOL **presolptr, const char *name, const char *desc, int priority, int maxrounds, SCIP_PRESOLTIMING timing, SCIP_DECL_PRESOLEXEC((*presolexec)), SCIP_PRESOLDATA *presoldata)
const char * SCIPpresolGetName(SCIP_PRESOL *presol)
Definition presol.c:625
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition var.c:23900
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition var.c:23674
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition var.c:23418
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4380
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24300
int SCIPvarGetIndex(SCIP_VAR *var)
Definition var.c:23684
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition scip_var.c:1887
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition scip_var.c:2166
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24266
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition var.c:23475
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition var.c:17319
SCIP_RETCODE SCIPgetBinvarRepresentative(SCIP *scip, SCIP_VAR *var, SCIP_VAR **repvar, SCIP_Bool *negated)
Definition scip_var.c:2236
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4322
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:1853
void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
void SCIPsortDownIntPtr(int *intarray, void **ptrarray, int len)
void SCIPsortIntPtr(int *intarray, void **ptrarray, int len)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition misc.c:10827
return SCIP_OKAY
int c
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
static SCIP_Bool propagate
static SCIP_VAR ** vars
memory allocation routines
#define PRESOL_NAME
#define PRESOL_PRIORITY
#define PRESOL_MAXROUNDS
#define PRESOL_TIMING
#define PRESOL_DESC
static SCIP_RETCODE cleanupHashDatas(SCIP *scip, SCIP_PRESOLDATA *presoldata)
#define DEFAULT_ONLYSETPART
static SCIP_RETCODE extractGates(SCIP *scip, SCIP_PRESOLDATA *presoldata, int pos, SCIP_HASHMAP *varmap, SCIP_CONS **gateconss, SCIP_VAR **activevars, SCIP_VAR **posresultants, HASHDATA *hashdata, int *ndelconss, int *naddconss)
static SCIP_RETCODE presoldataInitHashtables(SCIP *scip, SCIP_PRESOLDATA *presoldata)
static SCIP_RETCODE createPresoldata(SCIP *scip, SCIP_PRESOLDATA *presoldata, SCIP_CONS **setppcs, int nsetppcs, SCIP_CONS **logicors, int nlogicors)
struct HashData HASHDATA
static void presoldataInit(SCIP_PRESOLDATA *presoldata)
static SCIP_RETCODE correctPresoldata(SCIP *scip, SCIP_PRESOLDATA *presoldata, SCIP_CONS **setppcs, int nsetppcs, SCIP_CONS **logicors, int nlogicors)
#define DEFAULT_SORTING
#define DEFAULT_SEARCHEQUATIONS
gateextraction presolver
public methods for managing constraints
public methods for message output
#define SCIPdebugPrintCons(x, y, z)
public data structures and miscellaneous methods
methods for sorting joint arrays of various types
public methods for presolvers
public methods for problem variables
public methods for constraint handler plugins and constraints
general public methods
public methods for memory management
public methods for message handling
public methods for SCIP parameter handling
public methods for presolving plugins
public methods for global and local (sub)problems
public methods for SCIP variables
static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
Main separation function.
struct SCIP_Cons SCIP_CONS
Definition type_cons.h:63
struct SCIP_Conshdlr SCIP_CONSHDLR
Definition type_cons.h:62
struct SCIP_HashMap SCIP_HASHMAP
Definition type_misc.h:106
#define SCIP_DECL_HASHKEYEQ(x)
Definition type_misc.h:195
#define SCIP_DECL_HASHKEYVAL(x)
Definition type_misc.h:198
struct SCIP_HashTable SCIP_HASHTABLE
Definition type_misc.h:88
#define SCIP_DECL_PRESOLCOPY(x)
Definition type_presol.h:60
struct SCIP_PresolData SCIP_PRESOLDATA
Definition type_presol.h:51
#define SCIP_DECL_PRESOLFREE(x)
Definition type_presol.h:68
#define SCIP_DECL_PRESOLINITPRE(x)
Definition type_presol.h:98
struct SCIP_Presol SCIP_PRESOL
Definition type_presol.h:50
#define SCIP_DECL_PRESOLEXITPRE(x)
#define SCIP_DECL_PRESOLEXIT(x)
Definition type_presol.h:84
#define SCIP_DECL_PRESOLEXEC(x)
@ SCIP_DIDNOTRUN
Definition type_result.h:42
@ SCIP_DIDNOTFIND
Definition type_result.h:44
@ SCIP_NOMEMORY
@ SCIP_INVALIDCALL
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
@ SCIP_VARSTATUS_FIXED
Definition type_var.h:54
@ SCIP_VARSTATUS_MULTAGGR
Definition type_var.h:56
@ SCIP_LOCKTYPE_MODEL
Definition type_var.h:141