SCIP

    Solving Constraint Integer Programs

    iisfinder_greedy.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 iisfinder_greedy.c
    26 * @brief greedy deletion and addition filter heuristic to compute (I)ISs
    27 * @author Marc Pfetsch
    28 * @author Mark Turner
    29 * @author Paul Meinhold
    30 */
    31
    34
    35#define IISFINDER_NAME "greedy"
    36#define IISFINDER_DESC "greedy deletion or addition constraint deletion"
    37#define IISFINDER_PRIORITY 8000
    38
    39#define DEFAULT_TIMELIMPERITER 1e+20 /**< time limit of optimization process for each individual subproblem */
    40#define DEFAULT_NODELIMPERITER -1L /**< node limit of optimization process for each individual subproblem */
    41
    42#define DEFAULT_ADDITIVE TRUE /**< should an additive constraint approach be used instead of deletion */
    43#define DEFAULT_CONSERVATIVE TRUE /**< should an unsolved problem (by e.g. user interrupt, node limit, time limit) be considered feasible when deleting constraints */
    44#define DEFAULT_DELAFTERADD TRUE /**< should the deletion routine be performed after the addition routine (in the case of additive) */
    45#define DEFAULT_DYNAMICREORDERING TRUE /**< should satisfied constraints outside the batch of an intermediate solve be added during the additive method */
    46
    47#define DEFAULT_INITBATCHSIZE 16 /**< the initial batchsize for the first iteration, ignored if initrelbatchsize is positive */
    48#define DEFAULT_INITRELBATCHSIZE 0.03125 /**< the initial batchsize relative to the original problem for the first iteration (0.0: use initbatchsize) */
    49#define DEFAULT_MAXBATCHSIZE INT_MAX /**< the maximum batchsize per iteration */
    50#define DEFAULT_MAXRELBATCHSIZE 0.5 /**< the maximum batchsize relative to the original problem per iteration */
    51#define DEFAULT_BATCHINGFACTOR 2.0 /**< the factor with which the batchsize is multiplied in every update */
    52#define DEFAULT_BATCHINGOFFSET 0.0 /**< the offset which is added to the multiplied batchsize in every update */
    53#define DEFAULT_BATCHUPDATEINTERVAL 1 /**< the number of iterations to run with a constant batchsize before updating (1: always update) */
    54
    55
    56/*
    57 * Data structures
    58 */
    59
    60/** IIS finder data */
    61struct SCIP_IISfinderData
    62{
    63 SCIP_Real timelimperiter; /**< time limit of optimization process for each individual subproblem */
    64 SCIP_Longint nodelimperiter; /**< node limit of optimization process for each individual subproblem */
    65
    66 SCIP_Bool additive; /**< should an additive constraint approach be used instead of deletion */
    67 SCIP_Bool conservative; /**< should an unsolved problem (by e.g. user interrupt, node limit, time limit) be considered feasible when deleting constraints */
    68 SCIP_Bool delafteradd; /**< should the deletion routine be performed after the addition routine (in the case of additive) */
    69 SCIP_Bool dynamicreordering; /**< should satisfied constraints outside the batch of an intermediate solve be added during the additive method */
    70
    71 int initbatchsize; /**< the initial batchsize for the first iteration, ignored if initrelbatchsize is positive */
    72 SCIP_Real initrelbatchsize; /**< the initial batchsize relative to the original problem for the first iteration (0.0: use initbatchsize) */
    73 int maxbatchsize; /**< the maximum batchsize per iteration */
    74 SCIP_Real maxrelbatchsize; /**< the maximum batchsize relative to the original problem per iteration */
    75 SCIP_Real batchingfactor; /**< the factor with which the batchsize is multiplied in every update */
    76 SCIP_Real batchingoffset; /**< the offset which is added to the multiplied batchsize in every update */
    77 int batchupdateinterval; /**< the number of iterations to run with a constant batchsize before updating (1: always update) */
    78};
    79
    80/*
    81 * Local methods
    82 */
    83
    84/* Set time and node limits on the subproblem */
    85static
    87 SCIP* scip, /**< SCIP instance to analyze */
    88 SCIP_IIS* iis, /**< IIS data structure containing subscip */
    89 SCIP_Real timelim, /**< total time limit allowed of the whole call */
    90 SCIP_Real timelimperiter, /**< time limit per individual solve call */
    91 SCIP_Longint nodelim, /**< node limit allowed for the whole call */
    92 SCIP_Longint nodelimperiter /**< maximum number of nodes per individual solve call */
    93 )
    94{
    95 SCIP_Real currtime;
    96 SCIP_Real mintimelim;
    97 SCIP_Longint globalnodelim;
    98
    99 /* Set the time limit for the solve call. Take into account the global time limit, the current time used, and the time lim on each individual call */
    100 currtime = SCIPiisGetTime(iis);
    101 mintimelim = MIN(timelim - currtime, timelimperiter);
    102 mintimelim = MAX(mintimelim, 0);
    103 SCIP_CALL( SCIPsetRealParam(scip, "limits/time", mintimelim) );
    104
    105 /* Set the node limit for the solve call. Take into account the global node limit, the current nodes processed, and the node lim on each individual call */
    106 if( nodelim == -1 )
    107 globalnodelim = -1;
    108 else
    109 {
    110 globalnodelim = nodelim - SCIPiisGetNNodes(iis);
    111 assert( globalnodelim >= 0 );
    112 }
    113 if( globalnodelim == -1 && nodelimperiter == -1 )
    114 {
    115 SCIP_CALL( SCIPsetLongintParam(scip, "limits/nodes", nodelim) );
    116 }
    117 else if( globalnodelim == -1 || nodelimperiter == -1 )
    118 {
    119 SCIP_CALL( SCIPsetLongintParam(scip, "limits/nodes", MAX(globalnodelim, nodelimperiter)) );
    120 }
    121 else
    122 {
    123 SCIP_CALL( SCIPsetLongintParam(scip, "limits/nodes", MIN(globalnodelim, nodelimperiter)) );
    124 }
    125 return SCIP_OKAY;
    126}
    127
    128/* Revert bound changes made in the subproblem */
    129static
    131 SCIP* scip, /**< SCIP instance to analyze */
    132 SCIP_VAR** vars, /**< the array of variables whose bounds are changed */
    133 SCIP_Real* bounds, /**< the array of original bounds for the variables */
    134 int* idxs, /**< the indices of the vars (in the vars array) that have been deleted */
    135 int ndelbounds, /**< the number of bounds that will be deleted */
    136 SCIP_Bool islb /**< are the bounds that are being deleted LBs? */
    137 )
    138{
    139 int i;
    140
    141 /* Iterate over the affected variables and restore the bounds back to their original values */
    142 for (i = 0; i < ndelbounds; ++i)
    143 {
    144 if( islb )
    145 {
    146 if( !SCIPisInfinity(scip, -bounds[i]) )
    147 SCIP_CALL( SCIPchgVarLb(scip, vars[idxs[i]], bounds[i]) );
    148 }
    149 else
    150 {
    151 if( !SCIPisInfinity(scip, bounds[i]) )
    152 SCIP_CALL( SCIPchgVarUb(scip, vars[idxs[i]], bounds[i]) );
    153 }
    154 }
    155 return SCIP_OKAY;
    156}
    157
    158/* Revert deleted constraint changes made in the subproblem */
    159static
    161 SCIP* scip, /**< SCIP instance to analyze */
    162 SCIP_CONS** conss, /**< the array of constraints where some have been deleted */
    163 int* idxs, /**< the indices of the cons (in the conss array) that have been deleted */
    164 int ndelconss, /**< the number of constraints that have been deleted */
    165 SCIP_Bool releaseonly /**< Should the constraints just be released instead of added back */
    166 )
    167{
    168 int i;
    169 SCIP_CONS* copycons;
    170
    171 for( i = 0; i < ndelconss; ++i )
    172 {
    173 if( releaseonly )
    174 {
    175 SCIP_CALL( SCIPreleaseCons(scip, &conss[idxs[i]]) );
    176 }
    177 else
    178 {
    179 SCIP_CALL( SCIPaddCons(scip, conss[idxs[i]]) );
    180 copycons = conss[idxs[i]];
    181 assert(SCIPconsGetNUses(copycons) > 1);
    182 SCIP_CALL( SCIPreleaseCons(scip, &copycons) );
    183 }
    184 }
    185
    186 return SCIP_OKAY;
    187}
    188
    189/* Update the batchsize accoring to the chosen rule */
    190static
    192 SCIP* scip, /**< SCIP data structure */
    193 int initbatchsize, /**< the initial batchsize */
    194 int maxbatchsize, /**< the maximum batchsize per iteration */
    195 int iteration, /**< the current iteration */
    196 SCIP_Bool resettoinit, /**< should the batchsize be reset to the initial batchsize? */
    197 SCIP_Real batchingfactor, /**< the factor with which the batchsize is multiplied in every update */
    198 SCIP_Real batchingoffset, /**< the offset which is added to the multiplied batchsize in every update */
    199 int batchupdateinterval, /**< the number of iterations to run with a constant batchsize before updating (1: always update) */
    200 int* batchsize /**< the batchsize to be updated */
    201 )
    202{
    203 if( resettoinit )
    204 *batchsize = initbatchsize;
    205 else if( iteration % batchupdateinterval == 0 )
    206 *batchsize = (int)ceil(batchingfactor * (*batchsize) + batchingoffset);
    207
    208 /* respect limits and maximum */
    209 *batchsize = MIN(*batchsize, maxbatchsize);
    210 *batchsize = MAX(*batchsize, 1);
    211 SCIPdebugMsg(scip, "Updated batchsize to %d\n", *batchsize);
    212
    213 return SCIP_OKAY;
    214}
    215
    216/** solve subproblem for deletionFilter */
    217static
    219 SCIP_IIS* iis, /**< IIS data structure containing subscip */
    220 SCIP_CONS** conss, /**< The array of constraints (may be a superset of the current constraints) */
    221 SCIP_VAR** vars, /**< the array of vars */
    222 int* idxs, /**< the indices of the constraints / vars that will be deleted / bounds removed */
    223 int ndels, /**< the number of bounds that will be deleted */
    224 SCIP_Real timelim, /**< The global time limit on the IIS finder call */
    225 SCIP_Real timelimperiter, /**< time limit per individual solve call */
    226 SCIP_Longint nodelim, /**< The global node limit on the IIS finder call */
    227 SCIP_Longint nodelimperiter, /**< maximum number of nodes per individual solve call */
    228 SCIP_Bool conservative, /**< whether we treat a subproblem to be feasible, if it reaches some status that could result in infeasible, e.g. node limit */
    229 SCIP_Bool delbounds, /**< whether bounds should be deleted instead of constraints */
    230 SCIP_Bool islb, /**< are the bounds that are being deleted LBs? */
    231 SCIP_Bool* deleted, /**< have the deleted bounds or constraints stayed deleted */
    232 SCIP_Bool* stop, /**< pointer to store whether we have to stop */
    233 SCIP_Bool* alldeletionssolved /**< pointer to store whether all the subscips solved */
    234 )
    235{
    236 SCIP* scip;
    237 SCIP_Real* bounds = NULL;
    238 SCIP_RETCODE retcode;
    239 SCIP_STATUS status;
    240 SCIP_Bool chgmade = FALSE;
    241 int i;
    242
    243 *deleted = FALSE;
    244 *stop = FALSE;
    245 scip = SCIPiisGetSubscip(iis);
    246
    247 /* remove bounds or constraints */
    248 if( delbounds )
    249 {
    250 assert(vars != NULL);
    251 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &bounds, ndels) );
    252 for (i = 0; i < ndels; ++i)
    253 {
    254 if( islb )
    255 {
    256 bounds[i] = SCIPvarGetLbOriginal(vars[idxs[i]]);
    257 if( !SCIPisInfinity(scip, -bounds[i]) )
    258 {
    259 SCIP_CALL( SCIPchgVarLb(scip, vars[idxs[i]], -SCIPinfinity(scip)) );
    260 chgmade = TRUE;
    261 }
    262 }
    263 else
    264 {
    265 bounds[i] = SCIPvarGetUbOriginal(vars[idxs[i]]);
    266 if( !SCIPisInfinity(scip, bounds[i]) )
    267 {
    268 SCIP_CALL( SCIPchgVarUb(scip, vars[idxs[i]], SCIPinfinity(scip)) );
    269 chgmade = TRUE;
    270 }
    271 }
    272 }
    273 }
    274 else
    275 {
    276 assert(conss != NULL);
    277
    278 if( ndels > 0 )
    279 chgmade = TRUE;
    280 for (i = 0; i < ndels; ++i)
    281 {
    282 assert( SCIPconsIsInProb(conss[idxs[i]]) );
    283 SCIP_CALL( SCIPcaptureCons(scip, conss[idxs[i]]) );
    284 SCIP_CALL( SCIPdelCons(scip, conss[idxs[i]]) );
    285 }
    286 }
    287
    288 if( !chgmade )
    289 {
    290 if( delbounds )
    291 SCIPfreeBlockMemoryArray(scip, &bounds, ndels);
    292 return SCIP_OKAY;
    293 }
    294
    295 /* solve problem until first solution is found or infeasibility has been proven */
    296 SCIP_CALL( setLimits(scip, iis, timelim, timelimperiter, nodelim, nodelimperiter) );
    297 retcode = SCIPsolve(scip);
    299
    300 if( retcode != SCIP_OKAY )
    301 {
    303 SCIPdebugMsg(scip, "Error in sub-scip with deleted constraints / bounds. Re-adding them.\n");
    304 if( delbounds )
    305 {
    306 SCIP_CALL( revertBndChgs(scip, vars, bounds, idxs, ndels, islb) );
    307 SCIPfreeBlockMemoryArray(scip, &bounds, ndels);
    308 }
    309 else
    310 {
    311 SCIP_CALL( revertConssDeletions(scip, conss, idxs, ndels, FALSE) );
    312 }
    313 *alldeletionssolved = FALSE;
    314 return SCIP_OKAY;
    315 }
    316
    317 status = SCIPgetStatus(scip);
    319
    320 /* check status and handle accordingly */
    321 switch ( status )
    322 {
    323 case SCIP_STATUS_USERINTERRUPT: /* if a user interrupt occurred, just stop */
    325 SCIPdebugMsg(scip, "User interrupt. Stopping.\n");
    326 if( delbounds )
    327 {
    328 SCIP_CALL( revertBndChgs(scip, vars, bounds, idxs, ndels, islb) );
    329 }
    330 else
    331 {
    332 SCIP_CALL( revertConssDeletions(scip, conss, idxs, ndels, !conservative) );
    333 }
    334 *stop = TRUE;
    335 *alldeletionssolved = FALSE;
    336 break;
    337
    338 case SCIP_STATUS_TIMELIMIT: /* if we reached some status that may have ended up in an infeasible problem */
    347 *alldeletionssolved = FALSE;
    348 SCIPdebugMsg(scip, "Some limit reached. Keeping bounds / constraints removed if non-conservative.\n");
    349 if( !conservative )
    350 {
    352 *deleted = TRUE;
    353 }
    354 if( conservative && delbounds )
    355 {
    356 SCIP_CALL( revertBndChgs(scip, vars, bounds, idxs, ndels, islb) );
    357 }
    358 if( !delbounds )
    359 {
    360 SCIP_CALL( revertConssDeletions(scip, conss, idxs, ndels, !conservative) );
    361 }
    362 break;
    363
    364 case SCIP_STATUS_INFEASIBLE: /* if the problem is infeasible */
    365 SCIPdebugMsg(scip, "Subproblem with bounds / constraints removed infeasible. Keep them removed.\n");
    367 if( !delbounds )
    368 {
    369 SCIP_CALL( revertConssDeletions(scip, conss, idxs, ndels, TRUE) );
    370 }
    371 *deleted = TRUE;
    372 break;
    373
    374 case SCIP_STATUS_BESTSOLLIMIT: /* we found a solution */
    379 SCIPdebugMsg(scip, "Found solution to subproblem with bounds / constraints removed. Add them back.\n");
    380 if( delbounds )
    381 {
    382 SCIP_CALL( revertBndChgs(scip, vars, bounds, idxs, ndels, islb) );
    383 }
    384 else
    385 {
    386 SCIP_CALL( revertConssDeletions(scip, conss, idxs, ndels, FALSE) );
    387 }
    388 break;
    389
    391 default:
    392 *alldeletionssolved = FALSE;
    393 SCIPerrorMessage("Unexpected return status %d in removed bounds subproblem. Exiting...\n", status);
    394 if( delbounds )
    395 SCIPfreeBlockMemoryArray(scip, &bounds, ndels);
    396 return SCIP_ERROR;
    397 }
    398
    399 if( delbounds )
    400 SCIPfreeBlockMemoryArray(scip, &bounds, ndels);
    401
    402 return SCIP_OKAY;
    403}
    404
    405/** solve subproblem for additionFilter */
    406static
    408 SCIP_IIS* iis, /**< IIS data structure containing subscip */
    409 SCIP_Real timelim, /**< The global time limit on the IIS finder call */
    410 SCIP_Real timelimperiter, /**< time limit per individual solve call */
    411 SCIP_Longint nodelim, /**< The global node limit on the IIS finder call */
    412 SCIP_Longint nodelimperiter, /**< maximum number of nodes per individual solve call */
    413 SCIP_Bool* feasible, /**< pointer to store whether the problem is feasible */
    414 SCIP_Bool* stop /**< pointer to store whether we have to stop */
    415 )
    416{
    417 SCIP* scip;
    418 SCIP_RETCODE retcode;
    419 SCIP_STATUS status;
    420
    421 assert( stop != NULL );
    422 scip = SCIPiisGetSubscip(iis);
    423
    424 *stop = FALSE;
    425
    426 /* solve problem until first solution is found or infeasibility has been proven */
    427 SCIP_CALL( setLimits(scip, iis, timelim, timelimperiter, nodelim, nodelimperiter) );
    428 retcode = SCIPsolve(scip);
    429
    430 if( retcode != SCIP_OKAY )
    431 {
    432 SCIPdebugMsg(scip, "Error in sub-scip with added constraints. Keep added constraints.\n");
    433 return SCIP_ERROR;
    434 }
    435
    437 status = SCIPgetStatus(scip);
    438
    439 /* check status */
    440 switch ( status )
    441 {
    442 case SCIP_STATUS_USERINTERRUPT: /* if an user interrupt occurred, just stop */
    444 SCIPdebugMsg(scip, "User interrupt. Stopping.\n");
    445 *stop = TRUE;
    446 break;
    447
    448 case SCIP_STATUS_NODELIMIT: /* if we reached some limit */
    458 SCIPdebugMsg(scip, "Some limit reached. Added constraint batch failed to induce infeasibility. Continue adding.\n");
    459 break;
    460
    461 case SCIP_STATUS_INFEASIBLE: /* if the problem is infeasible */
    462 SCIPdebugMsg(scip, "Subproblem with added constraints infeasible. Final batch of constraints added.\n");
    463 *feasible = FALSE;
    464 break;
    465
    466 case SCIP_STATUS_BESTSOLLIMIT: /* we found a solution */
    470 SCIPdebugMsg(scip, "Found solution of subproblem with added constraints. Keep adding constraint batches.\n");
    471 *feasible = TRUE;
    472 break;
    473
    475 default:
    476 SCIPerrorMessage("Unexpected return status %d. Exiting ...\n", status);
    477 return SCIP_ERROR;
    478 }
    479
    480 return SCIP_OKAY;
    481}
    482
    483
    484/** Deletion filter to greedily remove constraints to obtain an (I)IS */
    485static
    487 SCIP_IIS* iis, /**< IIS data structure containing subscip */
    488 SCIP_Real timelim, /**< The global time limit on the IIS finder call */
    489 SCIP_Longint nodelim, /**< The global node limit on the IIS finder call */
    490 SCIP_Bool removebounds, /**< Whether the algorithm should remove bounds as well as constraints */
    491 SCIP_Bool silent, /**< should the run be performed silently without printing progress information */
    492
    493 SCIP_Real timelimperiter, /**< time limit per individual solve call */
    494 SCIP_Longint nodelimperiter, /**< maximum number of nodes per individual solve call */
    495 SCIP_Bool conservative, /**< should a node or time limit solve be counted as feasible when deleting constraints */
    496
    497 int initbatchsize, /**< the initial batchsize for the first iteration */
    498 int maxbatchsize, /**< the maximum batchsize per iteration */
    499 SCIP_Real batchingfactor, /**< the factor with which the batchsize is multiplied in every update */
    500 SCIP_Real batchingoffset, /**< the offset which is added to the multiplied batchsize in every update */
    501 int batchupdateinterval, /**< the number of iterations to run with a constant batchsize before updating (1: always update) */
    502
    503 SCIP_Bool* alldeletionssolved /**< pointer to store whether all the subscips solved */
    504 )
    505{
    506 SCIP* scip;
    507 SCIP_CONS** origconss;
    508 SCIP_CONS** conss;
    509 SCIP_VAR** origvars;
    510 SCIP_VAR** vars;
    511 SCIP_RANDNUMGEN* randnumgen;
    512 int* order;
    513 int* idxs;
    514 SCIP_Bool stopiter;
    515 SCIP_Bool deleted;
    516 int nconss;
    517 int nvars;
    518 int batchindex;
    519 int batchsize = initbatchsize;
    520 int iteration;
    521 int i;
    522 int k;
    523
    524 /* get current subscip */
    525 scip = SCIPiisGetSubscip(iis);
    526 assert( scip != NULL );
    527 assert( SCIPiisIsSubscipInfeasible(iis) );
    528
    529 /* get random generator */
    530 randnumgen = SCIPiisGetRandnumgen(iis);
    531 assert( randnumgen != NULL );
    532
    533 /* get batch size */
    534 assert( initbatchsize >= 1 );
    535 assert( maxbatchsize >= 1 );
    536 initbatchsize = MIN(initbatchsize, maxbatchsize);
    537
    538 /* allocate indices array */
    539 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &idxs, maxbatchsize) );
    540
    541 /* get constraint information */
    542 nconss = SCIPgetNOrigConss(scip);
    543 origconss = SCIPgetOrigConss(scip);
    544 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &conss, origconss, nconss) );
    545
    546 /* reset problem */
    549
    550 /* prepare random order for constraints */
    551 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &order, nconss) );
    552 for (i = 0; i < nconss; ++i)
    553 order[i] = i;
    554 SCIPrandomPermuteIntArray(randnumgen, order, 0, nconss);
    555
    556 /* Loop through all batches of constraints in random order */
    557 i = 0;
    558 iteration = 0;
    559 deleted = FALSE;
    560 stopiter = FALSE;
    561 while( i < nconss )
    562 {
    563 /* update batchsize */
    564 SCIP_CALL( updateBatchsize(scip, initbatchsize, maxbatchsize, iteration, !deleted, batchingfactor, batchingoffset, batchupdateinterval, &batchsize) );
    565
    566 k = 0;
    567 batchindex = i;
    568 while( i < nconss && k < batchsize )
    569 {
    570 assert( conss[order[i]] != NULL );
    571 if( SCIPconsGetNUses(conss[order[i]]) == 1 )
    572 {
    573 idxs[k] = order[i];
    574 k++;
    575 }
    576 i++;
    577 }
    578
    579 /* treat subproblem */
    580 SCIP_CALL( deletionSubproblem(iis, conss, NULL, idxs, k, timelim, timelimperiter, nodelim, nodelimperiter,
    581 conservative, FALSE, FALSE, &deleted, &stopiter, alldeletionssolved) );
    582 if( !silent && deleted )
    584
    585 if( timelim - SCIPiisGetTime(iis) <= 0 || ( nodelim != -1 && SCIPiisGetNNodes(iis) >= nodelim ) || stopiter )
    586 break;
    587
    588 /* reset i to beginning of current batch if batch has not been deleted and k was large */
    589 if( !deleted && k > initbatchsize )
    590 i = batchindex;
    591
    592 ++iteration;
    593
    595 }
    596
    597 SCIPfreeBlockMemoryArray(scip, &order, nconss);
    598 SCIPfreeBlockMemoryArray(scip, &conss, nconss);
    599 SCIPfreeBlockMemoryArray(scip, &idxs, maxbatchsize);
    600
    601 if( timelim - SCIPiisGetTime(iis) <= 0 || ( nodelim != -1 && SCIPiisGetNNodes(iis) >= nodelim ) || stopiter )
    602 return SCIP_OKAY;
    603
    604 /* Repeat the above procedure but for bounds instead of constraints */
    605 if( removebounds )
    606 {
    607 /* allocate indices array */
    608 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &idxs, maxbatchsize) );
    609
    610 nvars = SCIPgetNOrigVars(scip);
    611 origvars = SCIPgetOrigVars(scip);
    612 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &vars, origvars, nvars) );
    613
    614 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &order, nvars) );
    615 for (i = 0; i < nvars; ++i)
    616 order[i] = i;
    617 SCIPrandomPermuteIntArray(randnumgen, order, 0, nvars);
    618
    619 i = 0;
    620 iteration = 0;
    621 deleted = FALSE;
    622 while( i < nvars )
    623 {
    624 /* update batchsize */
    625 SCIP_CALL( updateBatchsize(scip, initbatchsize, maxbatchsize, iteration, !deleted, batchingfactor, batchingoffset, batchupdateinterval, &batchsize) );
    626
    627 k = 0;
    628 batchindex = i;
    629 /* Do not delete bounds of binary variables or bother with calculations of free variables */
    630 while( i < nvars && k < batchsize )
    631 {
    632 if( (SCIPvarGetType(vars[order[i]]) != SCIP_VARTYPE_BINARY) && (!SCIPisInfinity(scip, -SCIPvarGetLbOriginal(vars[order[i]])) || !SCIPisInfinity(scip, SCIPvarGetUbOriginal(vars[order[i]]))) )
    633 {
    634 idxs[k] = order[i];
    635 k++;
    636 }
    637 i++;
    638 }
    639 if( k == 0 )
    640 break;
    641
    642 /* treat subproblem with LB deletions */
    643 SCIP_CALL( deletionSubproblem(iis, NULL, vars, idxs, k, timelim, timelimperiter, nodelim, nodelimperiter,
    644 conservative, TRUE, TRUE, &deleted, &stopiter, alldeletionssolved) );
    645 if( timelim - SCIPiisGetTime(iis) <= 0 || ( nodelim != -1 && SCIPiisGetNNodes(iis) >= nodelim ) || stopiter )
    646 break;
    647 if( !silent && deleted )
    649
    650 /* treat subproblem with UB deletions */
    651 SCIP_CALL( deletionSubproblem(iis, NULL, vars, idxs, k, timelim, timelimperiter, nodelim, nodelimperiter,
    652 conservative, TRUE, FALSE, &deleted, &stopiter, alldeletionssolved) );
    653
    654 if( timelim - SCIPiisGetTime(iis) <= 0 || ( nodelim != -1 && SCIPiisGetNNodes(iis) >= nodelim ) || stopiter )
    655 break;
    656 if( !silent && deleted )
    658
    659 /* reset i to beginning of current batch if batch has not been deleted and k was large */
    660 if( !deleted && k > initbatchsize )
    661 i = batchindex;
    662
    663 ++iteration;
    664 }
    665
    666 SCIPfreeBlockMemoryArray(scip, &order, nvars);
    667 SCIPfreeBlockMemoryArray(scip, &vars, nvars);
    668 SCIPfreeBlockMemoryArray(scip, &idxs, maxbatchsize);
    669 }
    670
    671 return SCIP_OKAY;
    672}
    673
    674/** Addition filter to greedily add constraints to obtain an (I)IS */
    675static
    677 SCIP_IIS* iis, /**< IIS data structure containing subscip */
    678 SCIP_Real timelim, /**< The global time limit on the IIS finder call */
    679 SCIP_Longint nodelim, /**< The global node limit on the IIS finder call */
    680 SCIP_Bool silent, /**< should the run be performed silently without printing progress information */
    681
    682 SCIP_Real timelimperiter, /**< time limit per individual solve call */
    683 SCIP_Longint nodelimperiter, /**< maximum number of nodes per individual solve call */
    684 SCIP_Bool dynamicreordering, /**< should satisfied constraints outside the batch of an intermediate solve be added during the additive method */
    685
    686 int initbatchsize, /**< the initial batchsize for the first iteration */
    687 int maxbatchsize, /**< the maximum batchsize per iteration */
    688 SCIP_Real batchingfactor, /**< the factor with which the batchsize is multiplied in every update */
    689 SCIP_Real batchingoffset, /**< the offset which is added to the multiplied batchsize in every update */
    690 int batchupdateinterval /**< the number of iterations to run with a constant batchsize before updating (1: always update) */
    691 )
    692{
    693 SCIP* scip;
    694 SCIP_CONS** origconss;
    695 SCIP_CONS** conss;
    696 SCIP_RANDNUMGEN* randnumgen;
    697 SCIP_SOL* sol;
    698 SCIP_SOL* copysol;
    699 SCIP_Bool* inIS;
    700 int* order;
    701 SCIP_Bool feasible;
    702 SCIP_Bool stopiter;
    703 SCIP_RETCODE retcode;
    704 SCIP_RESULT result;
    705 int nconss;
    706 int batchsize;
    707 int iteration;
    708 int i;
    709 int j;
    710 int k;
    711
    712 /* get current subscip */
    713 scip = SCIPiisGetSubscip(iis);
    714 assert( scip != NULL );
    715 assert( SCIPiisIsSubscipInfeasible(iis) );
    716
    717 /* get random generator */
    718 randnumgen = SCIPiisGetRandnumgen(iis);
    719 assert( randnumgen != NULL );
    720
    721 /* get batch size */
    722 assert( initbatchsize >= 1 );
    723 assert( maxbatchsize >= 1 );
    724 initbatchsize = MIN(initbatchsize, maxbatchsize);
    725 batchsize = initbatchsize;
    726
    727 /* get constraint information */
    728 nconss = SCIPgetNOrigConss(scip);
    729 origconss = SCIPgetOrigConss(scip);
    730 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &conss, origconss, nconss) );
    731
    732 /* Initialise information for whether a constraint is in the final infeasible system */
    733 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &inIS, nconss) );
    734
    735 /* First capture and then delete all constraints */
    737 for( i = 0; i < nconss; ++i )
    738 {
    739 assert( SCIPconsIsInProb(conss[i]) );
    740 if( SCIPconsGetNUses(conss[i]) > 1 )
    741 {
    742 inIS[i] = TRUE;
    743 }
    744 else
    745 {
    746 SCIP_CALL( SCIPcaptureCons(scip, conss[i]) );
    747 SCIP_CALL( SCIPdelCons(scip, conss[i]) );
    748 inIS[i] = FALSE;
    749 }
    750 }
    752
    753 /* Prepare random order in which the constraints will be added back */
    754 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &order, nconss) );
    755 for (i = 0; i < nconss; ++i)
    756 order[i] = i;
    757 SCIPrandomPermuteIntArray(randnumgen, order, 0, nconss);
    758
    759 /* Continue to add constraints until an infeasible status is reached */
    760 i = 0;
    761 iteration = 0;
    762 feasible = TRUE;
    763 stopiter = FALSE;
    764 while( i < nconss )
    765 {
    766 /* Add the next batch of constraints */
    767 k = 0;
    768 while( i < nconss && k < batchsize )
    769 {
    770 if( !inIS[order[i]] )
    771 {
    772 SCIP_CALL( SCIPaddCons(scip, conss[order[i]]) );
    773 SCIP_CALL( SCIPreleaseCons(scip, &conss[order[i]]) );
    774 inIS[order[i]] = TRUE;
    775 ++k;
    776 }
    777 i++;
    778 }
    779
    780 /* We have the full infeasible problem again */
    781 if( i == nconss )
    782 {
    783 feasible = FALSE;
    784 break;
    785 }
    786
    787 /* Solve the reduced problem */
    788 retcode = additionSubproblem(iis, timelim, timelimperiter, nodelim, nodelimperiter, &feasible, &stopiter);
    789 if( !feasible || stopiter || timelim - SCIPiisGetTime(iis) <= 0 || ( nodelim != -1 && SCIPiisGetNNodes(iis) >= nodelim ) )
    790 {
    792 break;
    793 }
    794
    795 if( !silent )
    797
    798 if( dynamicreordering && retcode == SCIP_OKAY )
    799 {
    800 /* free transform and copy solution if there is one */
    801 copysol = NULL;
    802 sol = SCIPgetBestSol(scip);
    803 if( sol != NULL )
    804 {
    805 SCIP_CALL( SCIPcreateSolCopyOrig(scip, &copysol, sol) );
    806 SCIP_CALL( SCIPunlinkSol(scip, copysol) );
    807 }
    810
    811 /* Add any other constraints that are also feasible for the current solution */
    812 if( copysol != NULL )
    813 {
    814 k = 0;
    815 for( j = i; j < nconss; ++j )
    816 {
    817 /* Don't dynamically add indicator constraints */
    818 if( !inIS[order[j]]
    819 && strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(conss[order[j]])), "indicator") != 0 )
    820 {
    821 SCIP_CALL( SCIPcheckCons(scip, conss[order[j]], copysol, FALSE, FALSE, FALSE, &result) );
    822 if( result == SCIP_FEASIBLE )
    823 {
    824 SCIP_CALL( SCIPaddCons(scip, conss[order[j]]) );
    825 SCIP_CALL( SCIPreleaseCons(scip, &conss[order[j]]) );
    826 inIS[order[j]] = TRUE;
    827 k++;
    828 }
    829 }
    830 }
    831 SCIPdebugMsg(scip, "Added %d constraints by reordering dynamically.\n", k);
    832 SCIP_CALL( SCIPfreeSol(scip, &copysol) );
    833 }
    834 }
    835 else
    836 {
    839 }
    840
    841 ++iteration;
    842
    843 /* update batchsize */
    844 SCIP_CALL( updateBatchsize(scip, initbatchsize, maxbatchsize, iteration, FALSE, batchingfactor, batchingoffset, batchupdateinterval, &batchsize) );
    845 }
    846
    847 /* If problem is feasible due to limit or interrupt, add the deleted constraints of the full infeasible problem */
    848 if( feasible )
    849 {
    850 assert(stopiter || SCIPiisGetTime(iis) >= timelim || (nodelim != -1 && SCIPiisGetNNodes(iis) >= nodelim));
    851 SCIPdebugMsg(scip, "Hit limit or interrupt. Restore full infeasible problem.\n");
    852 for( i = 0; i < nconss; ++i )
    853 {
    854 if( !inIS[order[i]] )
    855 {
    856 SCIP_CALL( SCIPaddCons(scip, conss[order[i]]) );
    857 SCIP_CALL( SCIPreleaseCons(scip, &conss[order[i]]) );
    858 inIS[order[i]] = TRUE;
    859 }
    860 }
    861 }
    862 else
    863 {
    864 /* Release any cons not in the IS */
    865 for( i = 0; i < nconss; ++i )
    866 {
    867 if( !inIS[order[i]] )
    868 {
    869 SCIP_CALL( SCIPreleaseCons(scip, &conss[order[i]]) );
    870 }
    871 }
    872 }
    873
    874 SCIPfreeBlockMemoryArray(scip, &order, nconss);
    875 SCIPfreeBlockMemoryArray(scip, &inIS, nconss);
    876 SCIPfreeBlockMemoryArray(scip, &conss, nconss);
    878
    879 if( !silent )
    881
    882 return SCIP_OKAY;
    883}
    884
    885/** perform a greedy addition or deletion algorithm to obtain an infeasible subsystem (IS).
    886 *
    887 * This is the generation method for the greedy IIS finder rule.
    888 * Depending on the parameter choices, constraints are either greedily added from an empty problem,
    889 * or deleted from a complete problem. In the case of constraints being added, this is done until the problem
    890 * becomes infeasible, after which one can then begin deleting constraints. In the case of deleting constraints,
    891 * this is done until no more constraints (or batches of constraints) can be deleted without making
    892 * the problem feasible.
    893 */
    894static
    896 SCIP_IIS* iis, /**< IIS data structure */
    897 SCIP_IISFINDERDATA* iisfinderdata, /**< IIS finder data */
    898 SCIP_RESULT* result /**< pointer to store the result of the IIS finder run. SCIP_DIDNOTFIND if the algorithm failed, otherwise SCIP_SUCCESS. */
    899 )
    900{
    902 SCIP_Real timelim;
    903 SCIP_Longint nodelim;
    904 SCIP_Bool removebounds;
    905 SCIP_Bool silent;
    906 SCIP_Bool alldeletionssolved = TRUE;
    907 int nvars;
    908 int nconss;
    909 int maxbatchsize;
    910 int initbatchsize;
    911
    912 assert( scip != NULL );
    913 assert( iisfinderdata != NULL );
    914 assert( result != NULL );
    915
    916 SCIP_CALL( SCIPgetRealParam(scip, "iis/time", &timelim) );
    917 SCIP_CALL( SCIPgetLongintParam(scip, "iis/nodes", &nodelim) );
    918 SCIP_CALL( SCIPgetBoolParam(scip, "iis/removebounds", &removebounds) );
    919 SCIP_CALL( SCIPgetBoolParam(scip, "iis/silent", &silent) );
    920
    921 nvars = SCIPgetNOrigVars(scip);
    922 nconss = SCIPgetNOrigConss(scip);
    923 maxbatchsize = MAX(nvars, nconss);
    924 initbatchsize = iisfinderdata->initrelbatchsize > 0.0
    925 ? (int)ceil(iisfinderdata->initrelbatchsize * maxbatchsize) : MIN(iisfinderdata->initbatchsize, maxbatchsize);
    926 maxbatchsize = (int)ceil(iisfinderdata->maxrelbatchsize * maxbatchsize);
    927 maxbatchsize = MIN(iisfinderdata->maxbatchsize, maxbatchsize);
    928 initbatchsize = MAX(initbatchsize, 1);
    929 maxbatchsize = MAX(maxbatchsize, 1);
    930
    931 *result = SCIP_SUCCESS;
    932
    933 if( iisfinderdata->additive )
    934 {
    935 if( !silent )
    936 {
    937 SCIPdebugMsg(scip, "----- STARTING GREEDY ADDITION ALGORITHM -----\n");
    938 }
    939 SCIP_CALL( additionFilterBatch(iis, timelim, nodelim, silent, iisfinderdata->timelimperiter,
    940 iisfinderdata->nodelimperiter, iisfinderdata->dynamicreordering, initbatchsize, maxbatchsize,
    941 iisfinderdata->batchingfactor, iisfinderdata->batchingoffset, iisfinderdata->batchupdateinterval) );
    943 if( timelim - SCIPiisGetTime(iis) <= 0 || ( nodelim != -1 && SCIPiisGetNNodes(iis) >= nodelim ) )
    944 return SCIP_OKAY;
    945 }
    946 else
    947 {
    948 if( !silent )
    949 {
    950 SCIPdebugMsg(scip, "----- STARTING GREEDY DELETION ALGORITHM -----\n");
    951 }
    952 SCIP_CALL( deletionFilterBatch(iis, timelim, nodelim, removebounds, silent, iisfinderdata->timelimperiter,
    953 iisfinderdata->nodelimperiter, iisfinderdata->conservative, initbatchsize, maxbatchsize,
    954 iisfinderdata->batchingfactor, iisfinderdata->batchingoffset, iisfinderdata->batchupdateinterval,
    955 &alldeletionssolved) );
    956 if( timelim - SCIPiisGetTime(iis) <= 0 || ( nodelim != -1 && SCIPiisGetNNodes(iis) >= nodelim ) )
    957 return SCIP_OKAY;
    958 if( alldeletionssolved && initbatchsize == 1 )
    960 }
    961
    962 if( iisfinderdata->delafteradd && iisfinderdata->additive )
    963 {
    964 if( !silent )
    965 {
    966 SCIPdebugMsg(scip, "----- STARTING GREEDY DELETION ALGORITHM FOLLOWING COMPLETED ADDITION ALGORITHM -----\n");
    967 }
    968 SCIP_CALL( deletionFilterBatch(iis, timelim, nodelim, removebounds, silent, iisfinderdata->timelimperiter,
    969 iisfinderdata->nodelimperiter, iisfinderdata->conservative, initbatchsize, maxbatchsize,
    970 iisfinderdata->batchingfactor, iisfinderdata->batchingoffset, iisfinderdata->batchupdateinterval,
    971 &alldeletionssolved) );
    972 if( timelim - SCIPiisGetTime(iis) <= 0 || ( nodelim != -1 && SCIPiisGetNNodes(iis) >= nodelim ) )
    973 return SCIP_OKAY;
    974 if( alldeletionssolved && initbatchsize == 1 )
    976 }
    977
    978 return SCIP_OKAY;
    979}
    980
    981
    982/*
    983 * Callback methods of IIS finder
    984 */
    985
    986
    987/** copy method for IIS finder plugin (called when SCIP copies plugins) */
    988static
    989SCIP_DECL_IISFINDERCOPY(iisfinderCopyGreedy)
    990{ /*lint --e{715}*/
    991 assert(scip != NULL);
    992 assert(iisfinder != NULL);
    993
    995
    996 /* call inclusion method of IIS finder */
    998
    999 return SCIP_OKAY;
    1000}
    1001
    1002/** destructor of IIS finder to free user data (called when SCIP is exiting) */
    1003/**! [SnippetIISfinderFreeGreedy] */
    1004static
    1005SCIP_DECL_IISFINDERFREE(iisfinderFreeGreedy)
    1006{ /*lint --e{715}*/
    1007 SCIP_IISFINDERDATA* iisfinderdata;
    1008
    1009 iisfinderdata = SCIPiisfinderGetData(iisfinder);
    1010
    1011 SCIPfreeBlockMemory(scip, &iisfinderdata);
    1012
    1013 SCIPiisfinderSetData(iisfinder, NULL);
    1014
    1015 return SCIP_OKAY;
    1016}
    1017/**! [SnippetIISfinderFreeGreedy] */
    1018
    1019/** IIS finder generation method of IIS */
    1020static
    1021SCIP_DECL_IISFINDEREXEC(iisfinderExecGreedy)
    1022{ /*lint --e{715}*/
    1023 SCIP_IISFINDERDATA* iisfinderdata;
    1024
    1025 assert(iisfinder != NULL);
    1026 assert(result != NULL);
    1027
    1028 *result = SCIP_DIDNOTFIND;
    1029
    1030 iisfinderdata = SCIPiisfinderGetData(iisfinder);
    1031 assert(iisfinderdata != NULL);
    1032
    1033 SCIP_CALL( execIISfinderGreedy(iis, iisfinderdata, result) );
    1034
    1035 return SCIP_OKAY;
    1036}
    1037
    1038
    1039/*
    1040 * IIS finder specific interface methods
    1041 */
    1042
    1043/** creates the greedy IIS finder and includes it in SCIP */
    1045 SCIP* scip /**< SCIP data structure */
    1046 )
    1047{
    1048 SCIP_IISFINDERDATA* iisfinderdata;
    1049 SCIP_IISFINDER* iisfinder;
    1050
    1051 /* create greedy IIS finder data */
    1052 SCIP_CALL( SCIPallocBlockMemory(scip, &iisfinderdata) );
    1053 BMSclearMemory(iisfinderdata);
    1054
    1056 iisfinderExecGreedy, iisfinderdata) );
    1057
    1058 assert(iisfinder != NULL);
    1059
    1060 /* set non fundamental callbacks via setter functions */
    1061 SCIP_CALL( SCIPsetIISfinderCopy(scip, iisfinder, iisfinderCopyGreedy) );
    1062 SCIP_CALL( SCIPsetIISfinderFree(scip, iisfinder, iisfinderFreeGreedy) );
    1063
    1064 /* add greedy IIS finder parameters */
    1066 "iis/" IISFINDER_NAME "/timelimperiter",
    1067 "time limit of optimization process for each individual subproblem",
    1068 &iisfinderdata->timelimperiter, FALSE, DEFAULT_TIMELIMPERITER, 0.0, SCIP_INVALID/10.0, NULL, NULL) );
    1069
    1071 "iis/" IISFINDER_NAME "/nodelimperiter",
    1072 "node limit of optimization process for each individual subproblem",
    1073 &iisfinderdata->nodelimperiter, FALSE, DEFAULT_NODELIMPERITER, -1L, SCIP_LONGINT_MAX, NULL, NULL) );
    1074
    1076 "iis/" IISFINDER_NAME "/additive",
    1077 "should an additive constraint approach be used instead of deletion",
    1078 &iisfinderdata->additive, FALSE, DEFAULT_ADDITIVE, NULL, NULL) );
    1079
    1081 "iis/" IISFINDER_NAME "/conservative",
    1082 "should an unsolved problem (by e.g. user interrupt, node limit, time limit) be considered feasible when deleting constraints",
    1083 &iisfinderdata->conservative, TRUE, DEFAULT_CONSERVATIVE, NULL, NULL) );
    1084
    1086 "iis/" IISFINDER_NAME "/delafteradd",
    1087 "should the deletion routine be performed after the addition routine (in the case of additive)",
    1088 &iisfinderdata->delafteradd, TRUE, DEFAULT_DELAFTERADD, NULL, NULL) );
    1089
    1091 "iis/" IISFINDER_NAME "/dynamicreordering",
    1092 "should satisfied constraints outside the batch of an intermediate solve be added during the additive method",
    1093 &iisfinderdata->dynamicreordering, TRUE, DEFAULT_DYNAMICREORDERING, NULL, NULL) );
    1094
    1096 "iis/" IISFINDER_NAME "/initbatchsize",
    1097 "the initial batchsize for the first iteration, ignored if initrelbatchsize is positive",
    1098 &iisfinderdata->initbatchsize, FALSE, DEFAULT_INITBATCHSIZE, 1, INT_MAX, NULL, NULL) );
    1099
    1101 "iis/" IISFINDER_NAME "/initrelbatchsize",
    1102 "the initial batchsize relative to the original problem for the first iteration (0.0: use initbatchsize)",
    1103 &iisfinderdata->initrelbatchsize, FALSE, DEFAULT_INITRELBATCHSIZE, 0.0, 1.0, NULL, NULL) );
    1104
    1106 "iis/" IISFINDER_NAME "/maxbatchsize",
    1107 "the maximum batchsize per iteration",
    1108 &iisfinderdata->maxbatchsize, TRUE, DEFAULT_MAXBATCHSIZE, 1, INT_MAX, NULL, NULL) );
    1109
    1111 "iis/" IISFINDER_NAME "/maxrelbatchsize",
    1112 "the maximum batchsize relative to the original problem per iteration",
    1113 &iisfinderdata->maxrelbatchsize, TRUE, DEFAULT_MAXRELBATCHSIZE, 0.0, 1.0, NULL, NULL) );
    1114
    1116 "iis/" IISFINDER_NAME "/batchingfactor",
    1117 "the factor with which the batchsize is multiplied in every update",
    1118 &iisfinderdata->batchingfactor, TRUE, DEFAULT_BATCHINGFACTOR, SCIP_REAL_MIN, SCIP_REAL_MAX, NULL, NULL) );
    1119
    1121 "iis/" IISFINDER_NAME "/batchingoffset",
    1122 "the offset which is added to the multiplied batchsize in every update",
    1123 &iisfinderdata->batchingoffset, TRUE, DEFAULT_BATCHINGOFFSET, SCIP_REAL_MIN, SCIP_REAL_MAX, NULL, NULL) );
    1124
    1126 "iis/" IISFINDER_NAME "/batchupdateinterval",
    1127 "the number of iterations to run with a constant batchsize before updating (1: always update)",
    1128 &iisfinderdata->batchupdateinterval, TRUE, DEFAULT_BATCHUPDATEINTERVAL, 1, INT_MAX, NULL, NULL) );
    1129
    1130 return SCIP_OKAY;
    1131}
    1132
    1133/** perform the greedy deletion algorithm with singleton batches to obtain an irreducible infeasible subsystem (IIS) */
    1135 SCIP_IIS* iis /**< IIS data structure */
    1136 )
    1137{
    1138 SCIP* scip;
    1139 SCIP_HASHMAP* invconssmap = NULL;
    1140 SCIP_Real timelim;
    1141 SCIP_Longint nodelim;
    1142 SCIP_Bool isstandalone;
    1143 SCIP_Bool removebounds;
    1144 SCIP_Bool silent;
    1145 SCIP_Bool alldeletionssolved = TRUE;
    1146 int nvars;
    1147 int nconss;
    1148
    1149 if( !SCIPiisIsSubscipInfeasible(iis) )
    1150 {
    1151 SCIPerrorMessage("infeasible problem required\n");
    1152 return SCIP_INVALIDDATA;
    1153 }
    1154
    1155 scip = SCIPiisGetSubscip(iis);
    1156 assert( scip != NULL );
    1157
    1158 /* if this function is called by a user outside of iisfinder.c::SCIPiisGenerate(), build inverse constraints hashmap */
    1159 isstandalone = !SCIPhashmapIsEmpty(iis->conssmap);
    1160 if( isstandalone )
    1161 {
    1162 SCIP_HASHMAPENTRY* entry;
    1163 SCIP_CONS* imagecons;
    1164 int nentries;
    1165 int c;
    1166
    1168 nentries = SCIPhashmapGetNEntries(iis->conssmap);
    1169 for( c = 0; c < nentries; ++c )
    1170 {
    1171 entry = SCIPhashmapGetEntry(iis->conssmap, c);
    1172 if( entry == NULL )
    1173 continue;
    1174
    1175 imagecons = SCIPhashmapEntryGetImage(entry);
    1176 assert(imagecons != NULL);
    1177
    1178 SCIP_CALL( SCIPhashmapInsert(invconssmap, imagecons, SCIPhashmapEntryGetOrigin(entry)) );
    1179 }
    1181 }
    1182
    1183 /* get relevant parameters */
    1184 SCIP_CALL( SCIPgetRealParam(scip, "iis/time", &timelim) );
    1185 SCIP_CALL( SCIPgetLongintParam(scip, "iis/nodes", &nodelim) );
    1186 SCIP_CALL( SCIPgetBoolParam(scip, "iis/removebounds", &removebounds) );
    1187 SCIP_CALL( SCIPgetBoolParam(scip, "iis/silent", &silent) );
    1188
    1189 nvars = SCIPgetNOrigVars(scip);
    1190 nconss = SCIPgetNOrigConss(scip);
    1191
    1192 /* make irreducible by running the deletion filter with singleton batches */
    1193 SCIP_CALL( deletionFilterBatch(iis, timelim, nodelim, removebounds, silent,
    1196 if( alldeletionssolved && SCIPiisGetTime(iis) < timelim && ( nodelim == -1 || SCIPiisGetNNodes(iis) < nodelim ) )
    1198
    1199 /* recreate main constraints hashmap */
    1200 if( isstandalone )
    1201 {
    1202 SCIP_CONS** conss;
    1203 SCIP_CONS* imagecons;
    1204 int c;
    1205
    1206 assert(invconssmap != NULL);
    1207 nconss = SCIPgetNOrigConss(scip);
    1208 conss = SCIPgetOrigConss(scip);
    1209 for( c = 0; c < nconss; ++c )
    1210 {
    1211 imagecons = SCIPhashmapGetImage(invconssmap, conss[c]);
    1212 assert(imagecons != NULL);
    1213 SCIP_CALL( SCIPhashmapInsert(iis->conssmap, imagecons, conss[c]) );
    1214 }
    1215 SCIPhashmapFree(&invconssmap);
    1216 }
    1217
    1218 return SCIP_OKAY;
    1219}
    #define NULL
    Definition: def.h:257
    #define SCIP_Longint
    Definition: def.h:150
    #define SCIP_REAL_MAX
    Definition: def.h:167
    #define SCIP_INVALID
    Definition: def.h:187
    #define SCIP_Bool
    Definition: def.h:100
    #define MIN(x, y)
    Definition: def.h:233
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define MAX(x, y)
    Definition: def.h:229
    #define SCIP_REAL_MIN
    Definition: def.h:168
    #define SCIP_LONGINT_MAX
    Definition: def.h:151
    #define SCIP_CALL(x)
    Definition: def.h:364
    SCIP_STATUS SCIPgetStatus(SCIP *scip)
    Definition: scip_general.c:562
    SCIP_STAGE SCIPgetStage(SCIP *scip)
    Definition: scip_general.c:444
    int SCIPgetNOrigConss(SCIP *scip)
    Definition: scip_prob.c:3712
    SCIP_VAR ** SCIPgetOrigVars(SCIP *scip)
    Definition: scip_prob.c:2811
    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 SCIPgetNOrigVars(SCIP *scip)
    Definition: scip_prob.c:2838
    SCIP_CONS ** SCIPgetOrigConss(SCIP *scip)
    Definition: scip_prob.c:3739
    void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
    Definition: misc.c:3095
    void * SCIPhashmapEntryGetImage(SCIP_HASHMAPENTRY *entry)
    Definition: misc.c:3613
    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
    int SCIPhashmapGetNElements(SCIP_HASHMAP *hashmap)
    Definition: misc.c:3576
    int SCIPhashmapGetNEntries(SCIP_HASHMAP *hashmap)
    Definition: misc.c:3584
    SCIP_HASHMAPENTRY * SCIPhashmapGetEntry(SCIP_HASHMAP *hashmap, int entryidx)
    Definition: misc.c:3592
    SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
    Definition: misc.c:3061
    void * SCIPhashmapEntryGetOrigin(SCIP_HASHMAPENTRY *entry)
    Definition: misc.c:3603
    SCIP_Bool SCIPhashmapIsEmpty(SCIP_HASHMAP *hashmap)
    Definition: misc.c:3566
    SCIP_RETCODE SCIPhashmapRemoveAll(SCIP_HASHMAP *hashmap)
    Definition: misc.c:3676
    SCIP_RETCODE SCIPiisGreedyMakeIrreducible(SCIP_IIS *iis)
    SCIP_RETCODE SCIPincludeIISfinderGreedy(SCIP *scip)
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
    Definition: scip_param.c:250
    SCIP_RETCODE SCIPaddLongintParam(SCIP *scip, const char *name, const char *desc, SCIP_Longint *valueptr, SCIP_Bool isadvanced, SCIP_Longint defaultvalue, SCIP_Longint minvalue, SCIP_Longint maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:111
    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 SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
    Definition: scip_param.c:545
    SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:139
    SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
    Definition: scip_param.c:307
    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 SCIPgetLongintParam(SCIP *scip, const char *name, SCIP_Longint *value)
    Definition: scip_param.c:288
    SCIP_RETCODE SCIPsetRealParam(SCIP *scip, const char *name, SCIP_Real value)
    Definition: scip_param.c:603
    void SCIPrandomPermuteIntArray(SCIP_RANDNUMGEN *randnumgen, int *array, int begin, int end)
    Definition: misc.c:10264
    const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4320
    SCIP_RETCODE SCIPcheckCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool printreason, SCIP_RESULT *result)
    Definition: scip_cons.c:2135
    SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
    Definition: cons.c:8413
    SCIP_Bool SCIPconsIsInProb(SCIP_CONS *cons)
    Definition: cons.c:8682
    int SCIPconsGetNUses(SCIP_CONS *cons)
    Definition: cons.c:8433
    SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    SCIP_RETCODE SCIPcaptureCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1138
    SCIP_RETCODE SCIPsetIISfinderCopy(SCIP *scip, SCIP_IISFINDER *iisfinder, SCIP_DECL_IISFINDERCOPY((*iisfindercopy)))
    const char * SCIPiisfinderGetName(SCIP_IISFINDER *iisfinder)
    Definition: iisfinder.c:315
    SCIP_IISFINDERDATA * SCIPiisfinderGetData(SCIP_IISFINDER *iisfinder)
    Definition: iisfinder.c:706
    void SCIPiisfinderSetData(SCIP_IISFINDER *iisfinder, SCIP_IISFINDERDATA *iisfinderdata)
    Definition: iisfinder.c:716
    void SCIPiisfinderInfoMessage(SCIP_IIS *iis, SCIP_Bool printheaders)
    Definition: iisfinder.c:794
    SCIP_RETCODE SCIPincludeIISfinderBasic(SCIP *scip, SCIP_IISFINDER **iisfinder, const char *name, const char *desc, int priority, SCIP_DECL_IISFINDEREXEC((*iisfinderexec)), SCIP_IISFINDERDATA *iisfinderdata)
    SCIP_RETCODE SCIPsetIISfinderFree(SCIP *scip, SCIP_IISFINDER *iisfinder, SCIP_DECL_IISFINDERFREE((*iisfinderfree)))
    SCIP_RANDNUMGEN * SCIPiisGetRandnumgen(SCIP_IIS *iis)
    Definition: iisfinder.c:1003
    void SCIPiisAddNNodes(SCIP_IIS *iis, SCIP_Longint nnodes)
    Definition: iisfinder.c:993
    SCIP * SCIPiisGetSubscip(SCIP_IIS *iis)
    Definition: iisfinder.c:1012
    void SCIPiisSetSubscipIrreducible(SCIP_IIS *iis, SCIP_Bool irreducible)
    Definition: iisfinder.c:983
    SCIP_Longint SCIPiisGetNNodes(SCIP_IIS *iis)
    Definition: iisfinder.c:963
    SCIP_Real SCIPiisGetTime(SCIP_IIS *iis)
    Definition: iisfinder.c:933
    SCIP_Bool SCIPiisIsSubscipInfeasible(SCIP_IIS *iis)
    Definition: iisfinder.c:943
    void SCIPiisSetSubscipInfeasible(SCIP_IIS *iis, SCIP_Bool infeasible)
    Definition: iisfinder.c:973
    #define SCIPfreeBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:110
    BMS_BLKMEM * SCIPblkmem(SCIP *scip)
    Definition: scip_mem.c:57
    #define SCIPallocBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:93
    #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_SOL * SCIPgetBestSol(SCIP *scip)
    Definition: scip_sol.c:2986
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1250
    SCIP_RETCODE SCIPunlinkSol(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1504
    SCIP_RETCODE SCIPcreateSolCopyOrig(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
    Definition: scip_sol.c:922
    SCIP_RETCODE SCIPfreeTransform(SCIP *scip)
    Definition: scip_solve.c:3475
    SCIP_RETCODE SCIPsolve(SCIP *scip)
    Definition: scip_solve.c:2611
    SCIP_Longint SCIPgetNTotalNodes(SCIP *scip)
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_RETCODE SCIPchgVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
    Definition: scip_var.c:5697
    SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
    Definition: var.c:24052
    SCIP_RETCODE SCIPchgVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
    Definition: scip_var.c:5875
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23485
    SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
    Definition: var.c:24095
    #define IISFINDER_NAME
    static SCIP_RETCODE deletionFilterBatch(SCIP_IIS *iis, SCIP_Real timelim, SCIP_Longint nodelim, SCIP_Bool removebounds, SCIP_Bool silent, SCIP_Real timelimperiter, SCIP_Longint nodelimperiter, SCIP_Bool conservative, int initbatchsize, int maxbatchsize, SCIP_Real batchingfactor, SCIP_Real batchingoffset, int batchupdateinterval, SCIP_Bool *alldeletionssolved)
    static SCIP_DECL_IISFINDERFREE(iisfinderFreeGreedy)
    #define DEFAULT_INITBATCHSIZE
    static SCIP_RETCODE revertBndChgs(SCIP *scip, SCIP_VAR **vars, SCIP_Real *bounds, int *idxs, int ndelbounds, SCIP_Bool islb)
    #define DEFAULT_MAXRELBATCHSIZE
    #define DEFAULT_INITRELBATCHSIZE
    static SCIP_RETCODE execIISfinderGreedy(SCIP_IIS *iis, SCIP_IISFINDERDATA *iisfinderdata, SCIP_RESULT *result)
    #define DEFAULT_BATCHINGOFFSET
    static SCIP_RETCODE deletionSubproblem(SCIP_IIS *iis, SCIP_CONS **conss, SCIP_VAR **vars, int *idxs, int ndels, SCIP_Real timelim, SCIP_Real timelimperiter, SCIP_Longint nodelim, SCIP_Longint nodelimperiter, SCIP_Bool conservative, SCIP_Bool delbounds, SCIP_Bool islb, SCIP_Bool *deleted, SCIP_Bool *stop, SCIP_Bool *alldeletionssolved)
    static SCIP_RETCODE revertConssDeletions(SCIP *scip, SCIP_CONS **conss, int *idxs, int ndelconss, SCIP_Bool releaseonly)
    static SCIP_DECL_IISFINDERCOPY(iisfinderCopyGreedy)
    static SCIP_DECL_IISFINDEREXEC(iisfinderExecGreedy)
    #define DEFAULT_DELAFTERADD
    #define DEFAULT_TIMELIMPERITER
    #define IISFINDER_PRIORITY
    #define DEFAULT_ADDITIVE
    #define DEFAULT_DYNAMICREORDERING
    #define DEFAULT_BATCHUPDATEINTERVAL
    #define DEFAULT_NODELIMPERITER
    #define DEFAULT_CONSERVATIVE
    static SCIP_RETCODE updateBatchsize(SCIP *scip, int initbatchsize, int maxbatchsize, int iteration, SCIP_Bool resettoinit, SCIP_Real batchingfactor, SCIP_Real batchingoffset, int batchupdateinterval, int *batchsize)
    #define IISFINDER_DESC
    #define DEFAULT_BATCHINGFACTOR
    #define DEFAULT_MAXBATCHSIZE
    static SCIP_RETCODE setLimits(SCIP *scip, SCIP_IIS *iis, SCIP_Real timelim, SCIP_Real timelimperiter, SCIP_Longint nodelim, SCIP_Longint nodelimperiter)
    static SCIP_RETCODE additionFilterBatch(SCIP_IIS *iis, SCIP_Real timelim, SCIP_Longint nodelim, SCIP_Bool silent, SCIP_Real timelimperiter, SCIP_Longint nodelimperiter, SCIP_Bool dynamicreordering, int initbatchsize, int maxbatchsize, SCIP_Real batchingfactor, SCIP_Real batchingoffset, int batchupdateinterval)
    static SCIP_RETCODE additionSubproblem(SCIP_IIS *iis, SCIP_Real timelim, SCIP_Real timelimperiter, SCIP_Longint nodelim, SCIP_Longint nodelimperiter, SCIP_Bool *feasible, SCIP_Bool *stop)
    greedy deletion and addition filter heuristic to compute IISs
    #define BMSclearMemory(ptr)
    Definition: memory.h:129
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    SCIP_HASHMAP * conssmap
    data structures for irreducible infeasible subsystems (IIS)
    struct SCIP_IISfinderData SCIP_IISFINDERDATA
    @ SCIP_FEASIBLE
    Definition: type_result.h:45
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_SUCCESS
    Definition: type_result.h:58
    enum SCIP_Result SCIP_RESULT
    Definition: type_result.h:61
    @ SCIP_INVALIDDATA
    Definition: type_retcode.h:52
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    @ SCIP_ERROR
    Definition: type_retcode.h:43
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_STAGE_PROBLEM
    Definition: type_set.h:45
    @ SCIP_STATUS_OPTIMAL
    Definition: type_stat.h:43
    @ SCIP_STATUS_TOTALNODELIMIT
    Definition: type_stat.h:50
    @ SCIP_STATUS_BESTSOLLIMIT
    Definition: type_stat.h:60
    @ SCIP_STATUS_SOLLIMIT
    Definition: type_stat.h:59
    @ SCIP_STATUS_UNBOUNDED
    Definition: type_stat.h:45
    @ SCIP_STATUS_UNKNOWN
    Definition: type_stat.h:42
    @ SCIP_STATUS_PRIMALLIMIT
    Definition: type_stat.h:57
    @ SCIP_STATUS_GAPLIMIT
    Definition: type_stat.h:56
    @ SCIP_STATUS_USERINTERRUPT
    Definition: type_stat.h:47
    @ SCIP_STATUS_TERMINATE
    Definition: type_stat.h:48
    @ SCIP_STATUS_INFORUNBD
    Definition: type_stat.h:46
    @ SCIP_STATUS_STALLNODELIMIT
    Definition: type_stat.h:52
    @ SCIP_STATUS_TIMELIMIT
    Definition: type_stat.h:54
    @ SCIP_STATUS_INFEASIBLE
    Definition: type_stat.h:44
    @ SCIP_STATUS_NODELIMIT
    Definition: type_stat.h:49
    @ SCIP_STATUS_DUALLIMIT
    Definition: type_stat.h:58
    @ SCIP_STATUS_MEMLIMIT
    Definition: type_stat.h:55
    @ SCIP_STATUS_RESTARTLIMIT
    Definition: type_stat.h:62
    enum SCIP_Status SCIP_STATUS
    Definition: type_stat.h:64
    @ SCIP_VARTYPE_BINARY
    Definition: type_var.h:64