Scippy

    SCIP

    Solving Constraint Integer Programs

    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-2025 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#include <string.h>
    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 {
    884 assert(SCIPvarIsActive(SCIPvarGetNegatedVar(activevars[d])));
    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;
    1015 SCIP_Bool propagate;
    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);
    1030 propagate = SCIPconsIsPropagated(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 assert(strcmp(SCIPpresolGetName(presol), PRESOL_NAME) == 0);
    1149
    1150 /* call inclusion method of presolver */
    1152
    1153 return SCIP_OKAY;
    1154}
    1155
    1156
    1157/** destructor of presolver to free user data (called when SCIP is exiting) */
    1158static
    1159SCIP_DECL_PRESOLFREE(presolFreeGateextraction)
    1160{ /*lint --e{715}*/
    1161 SCIP_PRESOLDATA* presoldata;
    1162
    1163 /* free presolver data */
    1164 presoldata = SCIPpresolGetData(presol);
    1165 assert(presoldata != NULL);
    1166
    1167 if( presoldata->hashdatatable != NULL )
    1168 {
    1169 assert(presoldata->setppchashtable != NULL);
    1170 assert(presoldata->logicorhashtable != NULL);
    1171
    1172 SCIPhashtableFree(&(presoldata->logicorhashtable));
    1173 SCIPhashtableFree(&(presoldata->setppchashtable));
    1174 SCIPhashtableFree(&(presoldata->hashdatatable));
    1175 }
    1176
    1177 SCIPfreeBlockMemory(scip, &presoldata);
    1178 SCIPpresolSetData(presol, NULL);
    1179
    1180 return SCIP_OKAY;
    1181}
    1182
    1183
    1184/** deinitialization method of presolver (called before transformed problem is freed) */
    1185static
    1186SCIP_DECL_PRESOLEXIT(presolExitGateextraction)
    1187{ /*lint --e{715}*/
    1188 SCIP_PRESOLDATA* presoldata;
    1189 int c;
    1190
    1191 /* free presolver data */
    1192 presoldata = SCIPpresolGetData(presol);
    1193 assert(presoldata != NULL);
    1194
    1195 /* release old constraints */
    1196 for( c = presoldata->nusefullogicor - 1; c >= 0; --c )
    1197 {
    1198 SCIP_CALL( SCIPreleaseCons(scip, &(presoldata->usefullogicor[c])) );
    1199 }
    1200
    1201 if( presoldata->usefullogicorexist )
    1202 {
    1203 SCIPfreeBlockMemoryArray(scip, &presoldata->usefullogicor, presoldata->susefullogicor);
    1204 }
    1205
    1206 if( presoldata->usefulsetppcexist )
    1207 {
    1208 assert(presoldata->setppchashdatas != NULL || presoldata->nsetppchashdatas == 0);
    1209 for( c = presoldata->nsetppchashdatas - 1; c >= 0; --c )
    1210 {
    1211 assert(presoldata->setppchashdatas[c].cons != NULL);
    1212 assert(presoldata->setppchashdatas[c].vars != NULL);
    1213
    1214 /* remove constraint from setppc-hashtable */
    1215 assert(SCIPhashtableExists(presoldata->setppchashtable, (void*) presoldata->setppchashdatas[c].cons));
    1216 SCIP_CALL( SCIPhashtableRemove(presoldata->setppchashtable, (void*) presoldata->setppchashdatas[c].cons) );
    1217
    1218 /* remove hashdata entry from hashtable */
    1219 SCIP_CALL( SCIPhashtableRemove(presoldata->hashdatatable, (void*) &presoldata->setppchashdatas[c]) );
    1220
    1221 /* release old constraints */
    1222 SCIP_CALL( SCIPreleaseCons(scip, &(presoldata->setppchashdatas[c].cons)) );
    1223
    1224 /* release variables */
    1225 SCIP_CALL( SCIPreleaseVar(scip, &(presoldata->setppchashdatas[c].vars[0])) );
    1226 SCIP_CALL( SCIPreleaseVar(scip, &(presoldata->setppchashdatas[c].vars[1])) );
    1227
    1228 /* free memory for variables */
    1229 SCIPfreeBlockMemoryArray(scip, &(presoldata->setppchashdatas[c].vars), 2);
    1230 }
    1231
    1232 SCIPfreeBlockMemoryArray(scip, &(presoldata->setppchashdatas), presoldata->ssetppchashdatas);
    1233 }
    1234
    1235 if( presoldata->hashdatatable != NULL )
    1236 {
    1237 assert(presoldata->setppchashtable != NULL);
    1238 assert(presoldata->logicorhashtable != NULL);
    1239
    1240 /* clear old hashtable entries */
    1241 SCIPhashtableRemoveAll(presoldata->hashdatatable);
    1242 SCIPhashtableRemoveAll(presoldata->setppchashtable);
    1243 SCIPhashtableRemoveAll(presoldata->logicorhashtable);
    1244 }
    1245
    1246 presoldata->nusefullogicor = 0;
    1247 presoldata->susefullogicor = 0;
    1248 presoldata->nsetppchashdatas = 0;
    1249 presoldata->ssetppchashdatas = 0;
    1250 presoldata->firstchangedlogicor = -1;
    1251 presoldata->ngates = 0;
    1252 presoldata->usefullogicorexist = FALSE;
    1253 presoldata->usefulsetppcexist = FALSE;
    1254 presoldata->newsetppchashdatas = FALSE;
    1255 presoldata->initialized = FALSE;
    1256
    1257 return SCIP_OKAY;
    1258}
    1259
    1260
    1261/** presolving initialization method of presolver (called when presolving is about to begin) */
    1262static
    1263SCIP_DECL_PRESOLINITPRE(presolInitpreGateextraction)
    1264{ /*lint --e{715}*/
    1265 return SCIP_OKAY;
    1266}
    1267
    1268
    1269/** presolving deinitialization method of presolver (called after presolving has been finished) */
    1270static
    1271SCIP_DECL_PRESOLEXITPRE(presolExitpreGateextraction)
    1272{ /*lint --e{715}*/
    1273 return SCIP_OKAY;
    1274}
    1275
    1276
    1277/** execution method of presolver */
    1278static
    1279SCIP_DECL_PRESOLEXEC(presolExecGateextraction)
    1280{ /*lint --e{715}*/
    1281 SCIP_PRESOLDATA* presoldata;
    1282 SCIP_HASHMAP* varmap;
    1283 HASHDATA hashdata;
    1284 SCIP_VAR* tmpvars[2];
    1285 SCIP_CONSHDLR* conshdlrsetppc;
    1286 SCIP_CONSHDLR* conshdlrlogicor;
    1287 SCIP_CONSHDLR* conshdlrand;
    1288 SCIP_CONS** setppcconss;
    1289 SCIP_CONS** logicorconss;
    1290 int nsetppcconss;
    1291 int nlogicorconss;
    1292 int size;
    1293 int c;
    1294 SCIP_Bool paramvalue;
    1295
    1296 assert(scip != NULL);
    1297 assert(presol != NULL);
    1298 assert(strcmp(SCIPpresolGetName(presol), PRESOL_NAME) == 0);
    1299 assert(result != NULL);
    1300
    1301 *result = SCIP_DIDNOTRUN;
    1302
    1303#ifdef SCIP_DISABLED_CODE
    1304 /* need to include cons_knapsack on top of this file */
    1305 /* check for possible knapsacks that form with a logicor a weak relaxation of an and-constraint
    1306 *
    1307 * the weak relaxation of an and-constraint looks like:
    1308 * - row1: resvar - v1 - ... - vn >= 1-n
    1309 * - row2: n*resvar - v1 - ... - vn <= 0.0
    1310 *
    1311 * which look like the following contraints
    1312 * - logicor: resvar + ~v1 + ... + ~vn >= 1
    1313 * - knapsack: n*resvar + ~v1 + ... + ~vn <= n
    1314 */
    1315 {
    1316 SCIP_CONSHDLR* conshdlrknapsack;
    1317 SCIP_CONS** knapsackconss;
    1318 int nknapsackconss;
    1319 SCIP_Longint* vals;
    1320 SCIP_Longint capacity;
    1321 int nvars;
    1322
    1323 conshdlrknapsack = SCIPfindConshdlr(scip, "knapsack");
    1324
    1325 /* get number of active constraints */
    1326 knapsackconss = SCIPconshdlrGetConss(conshdlrknapsack);
    1327 nknapsackconss = SCIPconshdlrGetNActiveConss(conshdlrknapsack);
    1328 assert(nknapsackconss >= 0);
    1329 assert(knapsackconss != NULL || nknapsackconss == 0);
    1330
    1331 for( c = nknapsackconss - 1; c >= 0; --c )
    1332 {
    1333 /* not implemented in master branch, but the constraint may be already sorted */
    1334 /*SCIPsortKnapsack(scip, knapsackconss[c]);*/
    1335
    1336 nvars = SCIPgetNVarsKnapsack(scip, knapsackconss[c]);
    1337 vals = SCIPgetWeightsKnapsack(scip, knapsackconss[c]);
    1338 capacity = SCIPgetCapacityKnapsack(scip, knapsackconss[c]);
    1339
    1340 if( nvars > 1 && capacity == nvars - 1 && vals[0] == capacity && vals[1] == 1 )
    1341 {
    1342 printf("possible knapsack for gate extraction\n");
    1343 }
    1344 }
    1345 }
    1346#endif
    1347
    1348 /* get necessary constraint handlers */
    1349 conshdlrsetppc = SCIPfindConshdlr(scip, "setppc");
    1350 conshdlrlogicor = SCIPfindConshdlr(scip, "logicor");
    1351
    1352 if( conshdlrsetppc == NULL || conshdlrlogicor == NULL )
    1353 return SCIP_OKAY;
    1354
    1355 /* get number of active constraints */
    1356 nsetppcconss = SCIPconshdlrGetNActiveConss(conshdlrsetppc);
    1357 assert(nsetppcconss >= 0);
    1358 nlogicorconss = SCIPconshdlrGetNActiveConss(conshdlrlogicor);
    1359 assert(nlogicorconss >= 0);
    1360
    1361 if( nsetppcconss == 0 || nlogicorconss == 0 )
    1362 return SCIP_OKAY;
    1363
    1364 /* get presolver data */
    1365 presoldata = SCIPpresolGetData(presol);
    1366 assert(presoldata != NULL);
    1367
    1368 conshdlrand = SCIPfindConshdlr(scip, "and");
    1369
    1370 /* need and-constraint handler to extract and-gates */
    1371 if( conshdlrand == NULL )
    1372 {
    1373 /* nothing to do when we cannot extract anything */
    1374 if( !presoldata->searchequations )
    1375 return SCIP_OKAY;
    1376 else
    1377 {
    1378 /* make sure that we correct the parameter for only extrating set-partitioning constraints */
    1379 if( SCIPisParamFixed(scip, "presolving/" PRESOL_NAME "/onlysetpart") )
    1380 {
    1381 SCIPwarningMessage(scip, "unfixing parameter <presolving/" PRESOL_NAME "/onlysetpart> in gate extration presolver\n");
    1382 SCIP_CALL( SCIPunfixParam(scip, "presolving/" PRESOL_NAME "/onlysetpart") );
    1383 }
    1384 SCIP_CALL( SCIPsetBoolParam(scip, "presolving/" PRESOL_NAME "/onlysetpart", TRUE) );
    1385 assert(presoldata->onlysetpart);
    1386 }
    1387 }
    1388
    1389 paramvalue = FALSE;
    1390 if( conshdlrand != NULL && SCIPgetBoolParam(scip, "constraints/and/linearize", &paramvalue) == SCIP_OKAY )
    1391 {
    1392 if( paramvalue )
    1393 {
    1394 SCIPwarningMessage(scip, "Gate-presolving is the 'counterpart' of linearizing all and-constraints, so enabling both presolving steps simultaneously does not make sense.\n");
    1395 }
    1396 }
    1397 *result = SCIP_DIDNOTFIND;
    1398
    1399 /* get active constraints */
    1400 SCIP_CALL( SCIPduplicateBufferArray(scip, &setppcconss, SCIPconshdlrGetConss(conshdlrsetppc), nsetppcconss) ); /*lint !e666*/
    1401
    1402 assert(setppcconss != NULL);
    1403 logicorconss = SCIPconshdlrGetConss(conshdlrlogicor);
    1404 assert(logicorconss != NULL);
    1405
    1406 /* first we need to initialized the hashtables if not yet done */
    1407 if( presoldata->hashdatatable == NULL )
    1408 {
    1409 SCIP_CALL( presoldataInitHashtables(scip, presoldata) );
    1410 }
    1411 assert(presoldata->hashdatatable != NULL);
    1412 assert(presoldata->setppchashtable != NULL);
    1413 assert(presoldata->logicorhashtable != NULL);
    1414
    1415 presoldata->newsetppchashdatas = FALSE;
    1416
    1417 if( !presoldata->initialized )
    1418 {
    1419 assert(presoldata->usefullogicor == NULL);
    1420
    1421 /* create useful set-packing information by adding new set-packing constraints with two variables */
    1422 SCIP_CALL( createPresoldata(scip, presoldata, setppcconss, nsetppcconss, logicorconss, nlogicorconss) );
    1423 }
    1424 else
    1425 {
    1426 /* refresh useful set-packing information, delete redundant constraints and add new constraints */
    1427 SCIP_CALL( correctPresoldata(scip, presoldata, setppcconss, nsetppcconss, logicorconss, nlogicorconss) );
    1428 }
    1429 assert(presoldata->initialized);
    1430
    1431 if( presoldata->nusefullogicor == 0 )
    1432 goto TERMINATE;
    1433
    1434 /* move the biggate extraction to front or back by sort the logicors after number of variables */
    1435
    1436 if( presoldata->sorting != 0 )
    1437 {
    1438 int* lengths;
    1439
    1440 SCIP_CALL( SCIPallocBufferArray(scip, &lengths, presoldata->nusefullogicor) );
    1441
    1442 for( c = presoldata->nusefullogicor - 1; c >= 0; --c )
    1443 {
    1444 lengths[c] = SCIPgetNVarsLogicor(scip, presoldata->usefullogicor[c]);
    1445 }
    1446
    1447 if( presoldata->sorting == -1 )
    1448 SCIPsortDownIntPtr(lengths, (void**)presoldata->usefullogicor, presoldata->nusefullogicor);
    1449 else
    1450 SCIPsortIntPtr(lengths, (void**)presoldata->usefullogicor, presoldata->nusefullogicor);
    1451
    1452 SCIPfreeBufferArray(scip, &lengths);
    1453 }
    1454
    1455 /* maximal number of binary variables */
    1457
    1458 /* create the variable mapping hash map */
    1459 SCIP_CALL( SCIPhashmapCreate(&varmap, SCIPblkmem(scip), size) );
    1460
    1461 /* search for set-partitioning constraints arising from a logicor and a set-packing constraints with equal variables */
    1462 if( presoldata->searchequations && !SCIPisStopped(scip) )
    1463 {
    1464 SCIP_HASHTABLE* setppchashdatatable;
    1465 HASHDATA** setppchashdatas;
    1466 HASHDATA* setppchashdatastore;
    1467 HASHDATA* hashmaphashdata;
    1468 SCIP_CONS* logicor;
    1469 SCIP_CONS* setppc;
    1470 SCIP_VAR** logicorvars;
    1471 SCIP_VAR** setppcvars;
    1472 SCIP_VAR** activevarslogicor;
    1473 SCIP_VAR** activevarssetppc;
    1474 SCIP_Bool negated;
    1475 int nsetppchashdatas;
    1476 int nlogicorvars;
    1477 int nsetppcvars;
    1478 int d;
    1479 int v;
    1480
    1481 assert(nsetppcconss > 0);
    1482
    1483 /* create local hashtable */
    1484 SCIP_CALL( SCIPhashtableCreate(&setppchashdatatable, SCIPblkmem(scip), nsetppcconss, SCIPhashGetKeyStandard, setppcHashdataKeyEqCons, setppcHashdataKeyValCons, (void*) scip) );
    1485
    1486 /* maximal number of binary variables */
    1487 size = presoldata->maxnvarslogicor;
    1488 assert(size >= 3);
    1489
    1490 /* get temporary memory */
    1491 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &setppchashdatastore, nsetppcconss) );
    1492 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &setppchashdatas, nsetppcconss) );
    1493 SCIP_CALL( SCIPallocBufferArray(scip, &activevarssetppc, size) );
    1494 SCIP_CALL( SCIPallocBufferArray(scip, &activevarslogicor, size) );
    1495
    1496 hashdata.cons = NULL;
    1497
    1498 nsetppchashdatas = 0;
    1499
    1500 /* collect all set-packing/-partitioning constraints and corresponding data to be able to search faster */
    1501 for( d = nsetppcconss - 1; d >= 0; --d )
    1502 {
    1503 setppc = setppcconss[d];
    1504 assert(setppc != NULL);
    1505
    1506 if( SCIPconsIsDeleted(setppc) || SCIPconsIsModifiable(setppc) || SCIPconsGetNUpgradeLocks(setppc) >= 1 )
    1507 continue;
    1508
    1509 /* @todo if of interest could also be implemented for set-covering constraints */
    1510#if 1
    1512 continue;
    1513#endif
    1514
    1515 nsetppcvars = SCIPgetNVarsSetppc(scip, setppc);
    1516
    1517 /* to big setppc constraints are picked out */
    1518 if( nsetppcvars < 2 || nsetppcvars > size )
    1519 continue;
    1520
    1521 setppcvars = SCIPgetVarsSetppc(scip, setppc);
    1522 assert(setppcvars != NULL);
    1523
    1524 /* get active setppc variables */
    1525 for( v = nsetppcvars - 1; v >= 0; --v )
    1526 {
    1527 /* do not work with fixed variables */
    1528 if( SCIPvarGetLbLocal(setppcvars[v]) > 0.5 || SCIPvarGetUbLocal(setppcvars[v]) < 0.5 )
    1529 break;
    1530
    1531 activevarssetppc[v] = (SCIP_VAR*) SCIPhashmapGetImage(varmap, setppcvars[v]);
    1532
    1533 if( activevarssetppc[v] == NULL )
    1534 {
    1535 SCIP_CALL( SCIPgetBinvarRepresentative(scip, setppcvars[v], &(activevarssetppc[v]), &negated) );
    1536 SCIP_CALL( SCIPhashmapInsert(varmap, setppcvars[v], activevarssetppc[v]) );
    1537 }
    1538 }
    1539
    1540 /* if we found a fixed variable we want disregard this constraint */
    1541 if( v >= 0 )
    1542 continue;
    1543
    1544 /* variables need to be sorted after indices to be able to do a fast comparison */
    1545 SCIPsortPtr((void**)activevarssetppc, SCIPvarComp, nsetppcvars);
    1546
    1547 setppchashdatas[nsetppchashdatas] = &(setppchashdatastore[nsetppchashdatas]);
    1548
    1549 /* memorize set-packing data */
    1550 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(setppchashdatas[nsetppchashdatas]->vars), activevarssetppc, nsetppcvars) );
    1551
    1552 setppchashdatas[nsetppchashdatas]->nvars = nsetppcvars;
    1553 setppchashdatas[nsetppchashdatas]->cons = setppc;
    1554 /* need to capture this constraint, because it might get deleted during the process */
    1555 SCIP_CALL( SCIPcaptureCons(scip, setppc) );
    1556
    1557 /* add entry to local hashtable */
    1558 SCIP_CALL( SCIPhashtableInsert(setppchashdatatable, (void*) setppchashdatas[nsetppchashdatas]) );
    1559 ++nsetppchashdatas;
    1560 }
    1561
    1562 /* check all (new) logicors against all collected set-packing/-partitioning constraints */
    1563 for( c = nlogicorconss - 1; c >= 0 && !SCIPisStopped(scip); --c )
    1564 {
    1565 logicor = logicorconss[c];
    1566 assert(logicor != NULL);
    1567
    1568 if( SCIPconsIsDeleted(logicor) || SCIPconsIsModifiable(logicor) || SCIPconsGetNUpgradeLocks(logicor) >= 1 )
    1569 continue;
    1570
    1571 nlogicorvars = SCIPgetNVarsLogicor(scip, logicor);
    1572
    1573 if( nlogicorvars < 2 )
    1574 continue;
    1575
    1576 assert(nlogicorvars <= size);
    1577
    1578 logicorvars = SCIPgetVarsLogicor(scip, logicor);
    1579 assert(logicorvars != NULL);
    1580
    1581 /* get active logicor variables */
    1582 for( v = nlogicorvars - 1; v >= 0; --v )
    1583 {
    1584 /* do not work with fixed variables */
    1585 if( SCIPvarGetLbLocal(logicorvars[v]) > 0.5 || SCIPvarGetUbLocal(logicorvars[v]) < 0.5 )
    1586 break;
    1587
    1588 activevarslogicor[v] = (SCIP_VAR*) SCIPhashmapGetImage(varmap, logicorvars[v]);
    1589
    1590 /* if image does not exist, then there is no corresponding set-packing constraint */
    1591 if( activevarslogicor[v] == NULL )
    1592 break;
    1593 }
    1594
    1595 if( v == -1 )
    1596 {
    1597 /* need sorting to be able to find the correct hashdata element */
    1598 SCIPsortPtr((void**)activevarslogicor, SCIPvarComp, nlogicorvars);
    1599
    1600 hashdata.nvars = nlogicorvars;
    1601 hashdata.vars = activevarslogicor;
    1602
    1603 hashmaphashdata = (HASHDATA*) SCIPhashtableRetrieve(setppchashdatatable, (void*) &hashdata);
    1604 assert(hashmaphashdata == NULL || hashmaphashdata->cons != NULL);
    1605
    1606 if( hashmaphashdata != NULL && !SCIPconsIsDeleted(hashmaphashdata->cons) )
    1607 {
    1608 SCIP_Bool initial;
    1610 SCIP_Bool enforce;
    1611 SCIP_Bool check;
    1612 SCIP_Bool propagate;
    1613 SCIP_Bool local;
    1614 SCIP_Bool modifiable;
    1615 SCIP_Bool dynamic;
    1616 SCIP_Bool removable;
    1617 SCIP_Bool stickingatnode;
    1618
    1619 setppc = hashmaphashdata->cons;
    1620 assert(SCIPconsGetHdlr(setppc) == SCIPfindConshdlr(scip, "setppc"));
    1621
    1622 initial = SCIPconsIsInitial(logicor) || SCIPconsIsInitial(setppc);
    1623 separate = SCIPconsIsSeparated(logicor) || SCIPconsIsSeparated(setppc);
    1624 enforce = SCIPconsIsEnforced(logicor) || SCIPconsIsEnforced(setppc);
    1625 check = SCIPconsIsChecked(logicor) || SCIPconsIsChecked(setppc);
    1626 propagate = SCIPconsIsPropagated(logicor) || SCIPconsIsPropagated(setppc);
    1627 local = SCIPconsIsLocal(logicor) && SCIPconsIsLocal(setppc);
    1628 modifiable = SCIPconsIsModifiable(logicor) && SCIPconsIsModifiable(setppc);
    1629 dynamic = SCIPconsIsDynamic(logicor) && SCIPconsIsDynamic(setppc);
    1630 removable = SCIPconsIsRemovable(logicor) && SCIPconsIsRemovable(setppc);
    1631 stickingatnode = SCIPconsIsStickingAtNode(logicor) && SCIPconsIsStickingAtNode(setppc);
    1632
    1633 /* check if logicor is redundant against a set-partitioning constraint */
    1635 {
    1636 SCIP_CALL( SCIPsetConsInitial(scip, setppc, initial) );
    1638 SCIP_CALL( SCIPsetConsEnforced(scip, setppc, enforce) );
    1639 SCIP_CALL( SCIPsetConsChecked(scip, setppc, check) );
    1640 SCIP_CALL( SCIPsetConsPropagated(scip, setppc, propagate) );
    1641 SCIP_CALL( SCIPsetConsLocal(scip, setppc, local) );
    1642 SCIP_CALL( SCIPsetConsModifiable(scip, setppc, modifiable) );
    1643 SCIP_CALL( SCIPsetConsDynamic(scip, setppc, dynamic) );
    1644 SCIP_CALL( SCIPsetConsRemovable(scip, setppc, removable) );
    1645 SCIP_CALL( SCIPsetConsStickingAtNode(scip, setppc, stickingatnode) );
    1646
    1647 SCIPdebugMsg(scip, "Following logicor is redundant to the set-partitioning constraint.\n");
    1648 SCIPdebugPrintCons(scip, logicor, NULL);
    1649 SCIPdebugPrintCons(scip, setppc, NULL);
    1650 }
    1651 else
    1652 {
    1653 SCIP_CONS* newcons;
    1654 char name[SCIP_MAXSTRLEN];
    1655
    1657
    1658 SCIPdebugMsg(scip, "Following logicor and set-packing constraints form a set-partitioning constraint.\n");
    1659 SCIPdebugPrintCons(scip, logicor, NULL);
    1660 SCIPdebugPrintCons(scip, setppc, NULL);
    1661
    1662 /* create and add set-partitioning constraint */
    1663 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "setpart_%d", presoldata->ngates);
    1664 SCIP_CALL( SCIPcreateConsSetpart(scip, &newcons, name, nlogicorvars, activevarslogicor,
    1665 initial, separate, enforce, check, propagate,
    1666 local, modifiable, dynamic, removable, stickingatnode) );
    1667
    1668 SCIPdebugMsg(scip, "-------------->\n");
    1669 SCIPdebugPrintCons(scip, newcons, NULL);
    1670 SCIP_CALL( SCIPaddCons(scip, newcons) );
    1671 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    1672
    1673 ++(*naddconss);
    1674 ++(presoldata->ngates);
    1675
    1676 /* delete redundant set-packing constraint */
    1677 SCIP_CALL( SCIPdelCons(scip, setppc) );
    1678 ++(*ndelconss);
    1679 }
    1680
    1681 /* delete redundant logicor constraint */
    1682 SCIP_CALL( SCIPdelCons(scip, logicor) );
    1683 ++(*ndelconss);
    1684 }
    1685 }
    1686 }
    1687
    1688 /* need to clear/release parts of hashdata objects */
    1689 for( d = nsetppchashdatas - 1; d >= 0; --d )
    1690 {
    1691 /* need to release captured constraint */
    1692 SCIP_CALL( SCIPreleaseCons(scip, &(setppchashdatas[d]->cons)) );
    1693 /* need to free copied memory */
    1694 SCIPfreeBlockMemoryArray(scip, &(setppchashdatas[d]->vars), setppchashdatas[d]->nvars);
    1695 }
    1696
    1697 /* delete local hashtable */
    1698 SCIPhashtableFree(&setppchashdatatable);
    1699
    1700 /* free all temporary memory */
    1701 SCIPfreeBufferArray(scip, &activevarslogicor);
    1702 SCIPfreeBufferArray(scip, &activevarssetppc);
    1703 SCIPfreeBlockMemoryArray(scip, &setppchashdatas, nsetppcconss);
    1704 SCIPfreeBlockMemoryArray(scip, &setppchashdatastore, nsetppcconss);
    1705 }
    1706
    1707 /* we do not have any useful set-packing or logicor constraint, or since last run did not get any new constraints, so abort */
    1708 if( presoldata->nsetppchashdatas == 0 || (presoldata->firstchangedlogicor == presoldata->nusefullogicor && !presoldata->newsetppchashdatas) )
    1709 {
    1710 SCIPhashmapFree(&varmap);
    1711 goto TERMINATE;
    1712 }
    1713
    1714 assert(presoldata->usefullogicor != NULL);
    1715 assert(presoldata->nusefullogicor > 0);
    1716 assert(presoldata->firstchangedlogicor >= 0);
    1717 assert(presoldata->nsetppchashdatas > 0);
    1718
    1719 /* search for gates */
    1720 if( presoldata->nsetppchashdatas > 0 && !SCIPisStopped(scip) )
    1721 {
    1722 SCIP_CONS** gateconss;
    1723 SCIP_VAR** activevars;
    1724 SCIP_VAR** posresultants;
    1725 int endloop;
    1726
    1727 /* if we found new setppcs we want to check all logicors again */
    1728 if( presoldata->newsetppchashdatas )
    1729 endloop = 0;
    1730 else
    1731 endloop = MAX(presoldata->firstchangedlogicor, 0);
    1732
    1733 assert(presoldata->maxnvarslogicor >= 3);
    1734 SCIP_CALL( SCIPallocBufferArray(scip, &gateconss, presoldata->maxnvarslogicor) );
    1735 SCIP_CALL( SCIPallocBufferArray(scip, &activevars, presoldata->maxnvarslogicor) );
    1736 SCIP_CALL( SCIPallocBufferArray(scip, &posresultants, presoldata->maxnvarslogicor) );
    1737
    1738 hashdata.nvars = 2;
    1739 hashdata.cons = NULL;
    1740 /* assign array of two variables as temporary storage to hashdata */
    1741 hashdata.vars = tmpvars;
    1742
    1743 /* check all (new) logicors against all set-packing constraints, to extract and-constraints with two or more
    1744 * operands or set-partitioning constraints three or more variables
    1745 */
    1746 for( c = presoldata->nusefullogicor - 1; c >= endloop && !SCIPisStopped(scip); --c )
    1747 {
    1748 assert(presoldata->usefullogicor[c] != NULL);
    1749
    1750 /* logicor constraint has the form: x + y + z >= 1
    1751 *
    1752 * find set-packing constraints: (~x + ~y >= 1 and ~x + ~z >= 1) <=> (x + y <= 1 and x + z <= 1)
    1753 *
    1754 * - these three constraints are equivalent to: x = ~y * ~z (x = AND(~y,~z))
    1755 *
    1756 * if an additional set-packing constraint exists: y + z <= 1
    1757 *
    1758 * - these four constraints are equivalent to: x + y + z = 1
    1759 */
    1760 SCIP_CALL( extractGates(scip, presoldata, c, varmap, gateconss, activevars, posresultants, &hashdata, ndelconss, naddconss) );
    1761 }
    1762
    1763 SCIPfreeBufferArray(scip, &posresultants);
    1764 SCIPfreeBufferArray(scip, &activevars);
    1765 SCIPfreeBufferArray(scip, &gateconss);
    1766 }
    1767
    1768 SCIPhashmapFree(&varmap);
    1769
    1770 TERMINATE:
    1771 SCIPfreeBufferArray(scip, &setppcconss);
    1772
    1773 /* remove old setppchashdatas objects */
    1774 SCIP_CALL( cleanupHashDatas(scip, presoldata) );
    1775
    1776 return SCIP_OKAY;
    1777}
    1778
    1779
    1780/*
    1781 * presolver specific interface methods
    1782 */
    1783
    1784/** creates the gateextraction presolver and includes it in SCIP */
    1786 SCIP* scip /**< SCIP data structure */
    1787 )
    1788{
    1789 SCIP_PRESOLDATA* presoldata;
    1790 SCIP_PRESOL* presol;
    1791
    1792 /* alloc presolve data object */
    1793 SCIP_CALL( SCIPallocBlockMemory(scip, &presoldata) );
    1794
    1795 /* initialize gateextraction presolver data */
    1796 presoldataInit(presoldata);
    1797
    1798 /* include presolver */
    1800 PRESOL_TIMING, presolExecGateextraction, presoldata) );
    1801
    1802 SCIP_CALL( SCIPsetPresolCopy(scip, presol, presolCopyGateextraction) );
    1803 SCIP_CALL( SCIPsetPresolFree(scip, presol, presolFreeGateextraction) );
    1804 SCIP_CALL( SCIPsetPresolExit(scip, presol, presolExitGateextraction) );
    1805 SCIP_CALL( SCIPsetPresolInitpre(scip, presol, presolInitpreGateextraction) );
    1806 SCIP_CALL( SCIPsetPresolExitpre(scip, presol, presolExitpreGateextraction) );
    1807
    1808 /* add gateextraction presolver parameters */
    1810 "presolving/" PRESOL_NAME "/onlysetpart",
    1811 "should we only try to extract set-partitioning constraints and no and-constraints",
    1812 &presoldata->onlysetpart, TRUE, DEFAULT_ONLYSETPART, NULL, NULL) );
    1813
    1814 /* add gateextraction presolver parameters */
    1816 "presolving/" PRESOL_NAME "/searchequations",
    1817 "should we try to extract set-partitioning constraint out of one logicor and one corresponding set-packing constraint",
    1818 &presoldata->searchequations, TRUE, DEFAULT_SEARCHEQUATIONS, NULL, NULL) );
    1819
    1820 /* add gateextraction presolver parameters */
    1822 "presolving/" PRESOL_NAME "/sorting",
    1823 "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)",
    1824 &presoldata->sorting, TRUE, DEFAULT_SORTING, -1, 1, NULL, NULL) );
    1825
    1826 return SCIP_OKAY;
    1827}
    SCIP_VAR * h
    Definition: circlepacking.c:68
    Constraint handler for AND constraints, .
    Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
    Constraint handler for the set partitioning / packing / covering constraints .
    #define NULL
    Definition: def.h:248
    #define SCIP_MAXSTRLEN
    Definition: def.h:269
    #define SCIP_Longint
    Definition: def.h:141
    #define SCIP_Bool
    Definition: def.h:91
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define SCIP_CALL(x)
    Definition: def.h:355
    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)
    Definition: cons_setppc.c:9596
    SCIP_VAR ** SCIPgetVarsSetppc(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_setppc.c:9619
    SCIP_Longint * SCIPgetWeightsKnapsack(SCIP *scip, SCIP_CONS *cons)
    SCIP_Longint SCIPgetCapacityKnapsack(SCIP *scip, SCIP_CONS *cons)
    SCIP_SETPPCTYPE SCIPgetTypeSetppc(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_setppc.c:9642
    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)
    Definition: cons_setppc.c:9402
    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)
    Definition: scip_general.c:759
    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
    Definition: scip_message.h:78
    void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
    Definition: scip_message.c:120
    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:4812
    SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4735
    SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
    Definition: cons.c:8648
    SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
    Definition: cons.c:8409
    SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
    Definition: cons.c:8558
    SCIP_RETCODE SCIPsetConsStickingAtNode(SCIP *scip, SCIP_CONS *cons, SCIP_Bool stickingatnode)
    Definition: scip_cons.c:1499
    int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
    Definition: cons.c:8841
    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:8588
    SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
    Definition: cons.c:8518
    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:8578
    SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
    Definition: cons.c:8450
    SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
    Definition: cons.c:8608
    SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
    Definition: cons.c:8628
    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:8638
    SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
    Definition: cons.c:8668
    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:8568
    SCIP_RETCODE SCIPcaptureCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1138
    SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
    Definition: cons.c:8658
    #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
    void SCIPpresolSetData(SCIP_PRESOL *presol, SCIP_PRESOLDATA *presoldata)
    Definition: presol.c:538
    SCIP_PRESOLDATA * SCIPpresolGetData(SCIP_PRESOL *presol)
    Definition: presol.c:528
    SCIP_RETCODE SCIPsetPresolExitpre(SCIP *scip, SCIP_PRESOL *presol, SCIP_DECL_PRESOLEXITPRE((*presolexitpre)))
    Definition: scip_presol.c:228
    SCIP_RETCODE SCIPsetPresolFree(SCIP *scip, SCIP_PRESOL *presol, SCIP_DECL_PRESOLFREE((*presolfree)))
    Definition: scip_presol.c:164
    SCIP_RETCODE SCIPsetPresolExit(SCIP *scip, SCIP_PRESOL *presol, SCIP_DECL_PRESOLEXIT((*presolexit)))
    Definition: scip_presol.c:196
    SCIP_RETCODE SCIPsetPresolCopy(SCIP *scip, SCIP_PRESOL *presol, SCIP_DECL_PRESOLCOPY((*presolcopy)))
    Definition: scip_presol.c:148
    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)
    Definition: scip_presol.c:113
    SCIP_RETCODE SCIPsetPresolInitpre(SCIP *scip, SCIP_PRESOL *presol, SCIP_DECL_PRESOLINITPRE((*presolinitpre)))
    Definition: scip_presol.c:212
    const char * SCIPpresolGetName(SCIP_PRESOL *presol)
    Definition: presol.c:625
    SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
    Definition: var.c:23868
    SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
    Definition: var.c:23642
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23386
    int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4386
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24268
    int SCIPvarGetIndex(SCIP_VAR *var)
    Definition: var.c:23652
    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:24234
    SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
    Definition: var.c:23443
    int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
    Definition: var.c:17274
    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:4328
    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
    memory allocation routines
    static SCIP_RETCODE cleanupHashDatas(SCIP *scip, SCIP_PRESOLDATA *presoldata)
    #define PRESOL_NAME
    #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_DECL_PRESOLCOPY(presolCopyGateextraction)
    static SCIP_DECL_HASHKEYEQ(hashdataKeyEqCons)
    #define HASHSIZE_SETPPCCONS
    static SCIP_DECL_HASHKEYVAL(hashdataKeyValCons)
    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)
    static SCIP_DECL_PRESOLFREE(presolFreeGateextraction)
    #define PRESOL_PRIORITY
    #define HASHSIZE_LOGICORCONS
    static SCIP_DECL_PRESOLEXIT(presolExitGateextraction)
    static SCIP_DECL_PRESOLINITPRE(presolInitpreGateextraction)
    static SCIP_DECL_PRESOLEXITPRE(presolExitpreGateextraction)
    static SCIP_DECL_PRESOLEXEC(presolExecGateextraction)
    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 PRESOL_MAXROUNDS
    #define DEFAULT_SORTING
    #define PRESOL_TIMING
    #define DEFAULT_SEARCHEQUATIONS
    #define PRESOL_DESC
    gateextraction presolver
    public methods for managing constraints
    public methods for message output
    #define SCIPdebugPrintCons(x, y, z)
    Definition: pub_message.h:102
    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.
    Definition: sepa_flower.c:1221
    SCIP_VAR ** vars
    SCIP_CONS * cons
    struct SCIP_PresolData SCIP_PRESOLDATA
    Definition: type_presol.h:51
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_NOMEMORY
    Definition: type_retcode.h:44
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_VARSTATUS_FIXED
    Definition: type_var.h:54
    @ SCIP_VARSTATUS_MULTAGGR
    Definition: type_var.h:56
    @ SCIP_LOCKTYPE_MODEL
    Definition: type_var.h:141