Scippy

    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-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 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
    32#include <assert.h>
    33
    35
    36#define IISFINDER_NAME "greedy"
    37#define IISFINDER_DESC "greedy deletion or addition constraint deletion"
    38#define IISFINDER_PRIORITY 8000
    39
    40#define DEFAULT_TIMELIMPERITER 1e+20 /**< time limit of optimization process for each individual subproblem */
    41#define DEFAULT_NODELIMPERITER -1L /**< node limit of optimization process for each individual subproblem */
    42
    43#define DEFAULT_ADDITIVE TRUE /**< should an additive constraint approach be used instead of deletion */
    44#define DEFAULT_CONSERVATIVE TRUE /**< should an unsolved problem (by e.g. user interrupt, node limit, time limit) be considered feasible when deleting constraints */
    45#define DEFAULT_DELAFTERADD TRUE /**< should the deletion routine be performed after the addition routine (in the case of additive) */
    46#define DEFAULT_DYNAMICREORDERING TRUE /**< should satisfied constraints outside the batch of an intermediate solve be added during the additive method */
    47
    48#define DEFAULT_INITBATCHSIZE 16 /**< the initial batchsize for the first iteration, ignored if initrelbatchsize is positive */
    49#define DEFAULT_INITRELBATCHSIZE 0.03125 /**< the initial batchsize relative to the original problem for the first iteration (0.0: use initbatchsize) */
    50#define DEFAULT_MAXBATCHSIZE INT_MAX /**< the maximum batchsize per iteration */
    51#define DEFAULT_MAXRELBATCHSIZE 0.5 /**< the maximum batchsize relative to the original problem per iteration */
    52#define DEFAULT_BATCHINGFACTOR 2.0 /**< the factor with which the batchsize is multiplied in every update */
    53#define DEFAULT_BATCHINGOFFSET 0.0 /**< the offset which is added to the multiplied batchsize in every update */
    54#define DEFAULT_BATCHUPDATEINTERVAL 1 /**< the number of iterations to run with a constant batchsize before updating (1: always update) */
    55
    56
    57/*
    58 * Data structures
    59 */
    60
    61/** IIS finder data */
    62struct SCIP_IISfinderData
    63{
    64 SCIP_Real timelimperiter; /**< time limit of optimization process for each individual subproblem */
    65 SCIP_Longint nodelimperiter; /**< node limit of optimization process for each individual subproblem */
    66
    67 SCIP_Bool additive; /**< should an additive constraint approach be used instead of deletion */
    68 SCIP_Bool conservative; /**< should an unsolved problem (by e.g. user interrupt, node limit, time limit) be considered feasible when deleting constraints */
    69 SCIP_Bool delafteradd; /**< should the deletion routine be performed after the addition routine (in the case of additive) */
    70 SCIP_Bool dynamicreordering; /**< should satisfied constraints outside the batch of an intermediate solve be added during the additive method */
    71
    72 int initbatchsize; /**< the initial batchsize for the first iteration, ignored if initrelbatchsize is positive */
    73 SCIP_Real initrelbatchsize; /**< the initial batchsize relative to the original problem for the first iteration (0.0: use initbatchsize) */
    74 int maxbatchsize; /**< the maximum batchsize per iteration */
    75 SCIP_Real maxrelbatchsize; /**< the maximum batchsize relative to the original problem per iteration */
    76 SCIP_Real batchingfactor; /**< the factor with which the batchsize is multiplied in every update */
    77 SCIP_Real batchingoffset; /**< the offset which is added to the multiplied batchsize in every update */
    78 int batchupdateinterval; /**< the number of iterations to run with a constant batchsize before updating (1: always update) */
    79};
    80
    81/*
    82 * Local methods
    83 */
    84
    85/* Set time and node limits on the subproblem */
    86static
    88 SCIP* scip, /**< SCIP instance to analyze */
    89 SCIP_IIS* iis, /**< IIS data structure containing subscip */
    90 SCIP_Real timelim, /**< total time limit allowed of the whole call */
    91 SCIP_Real timelimperiter, /**< time limit per individual solve call */
    92 SCIP_Longint nodelim, /**< node limit allowed for the whole call */
    93 SCIP_Longint nodelimperiter /**< maximum number of nodes per individual solve call */
    94 )
    95{
    96 SCIP_Real currtime;
    97 SCIP_Real mintimelim;
    98 SCIP_Longint globalnodelim;
    99
    100 /* 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 */
    101 currtime = SCIPiisGetTime(iis);
    102 mintimelim = MIN(timelim - currtime, timelimperiter);
    103 mintimelim = MAX(mintimelim, 0);
    104 SCIP_CALL( SCIPsetRealParam(scip, "limits/time", mintimelim) );
    105
    106 /* 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 */
    107 if( nodelim == -1 )
    108 globalnodelim = -1;
    109 else
    110 {
    111 globalnodelim = nodelim - SCIPiisGetNNodes(iis);
    112 assert( globalnodelim >= 0 );
    113 }
    114 if( globalnodelim == -1 && nodelimperiter == -1 )
    115 {
    116 SCIP_CALL( SCIPsetLongintParam(scip, "limits/nodes", nodelim) );
    117 }
    118 else if( globalnodelim == -1 || nodelimperiter == -1 )
    119 {
    120 SCIP_CALL( SCIPsetLongintParam(scip, "limits/nodes", MAX(globalnodelim, nodelimperiter)) );
    121 }
    122 else
    123 {
    124 SCIP_CALL( SCIPsetLongintParam(scip, "limits/nodes", MIN(globalnodelim, nodelimperiter)) );
    125 }
    126 return SCIP_OKAY;
    127}
    128
    129/* Revert bound changes made in the subproblem */
    130static
    132 SCIP* scip, /**< SCIP instance to analyze */
    133 SCIP_VAR** vars, /**< the array of variables whose bounds are changed */
    134 SCIP_Real* bounds, /**< the array of original bounds for the variables */
    135 int* idxs, /**< the indices of the vars (in the vars array) that have been deleted */
    136 int ndelbounds, /**< the number of bounds that will be deleted */
    137 SCIP_Bool islb /**< are the bounds that are being deleted LBs? */
    138 )
    139{
    140 int i;
    141
    142 /* Iterate over the affected variables and restore the bounds back to their original values */
    143 for (i = 0; i < ndelbounds; ++i)
    144 {
    145 if( islb )
    146 {
    147 if( !SCIPisInfinity(scip, -bounds[i]) )
    148 SCIP_CALL( SCIPchgVarLb(scip, vars[idxs[i]], bounds[i]) );
    149 }
    150 else
    151 {
    152 if( !SCIPisInfinity(scip, bounds[i]) )
    153 SCIP_CALL( SCIPchgVarUb(scip, vars[idxs[i]], bounds[i]) );
    154 }
    155 }
    156 return SCIP_OKAY;
    157}
    158
    159/* Revert deleted constraint changes made in the subproblem */
    160static
    162 SCIP* scip, /**< SCIP instance to analyze */
    163 SCIP_CONS** conss, /**< the array of constraints where some have been deleted */
    164 int* idxs, /**< the indices of the cons (in the conss array) that have been deleted */
    165 int ndelconss, /**< the number of constraints that have been deleted */
    166 SCIP_Bool releaseonly /**< Should the constraints just be released instead of added back */
    167 )
    168{
    169 int i;
    170 SCIP_CONS* copycons;
    171
    172 for( i = 0; i < ndelconss; ++i )
    173 {
    174 if( releaseonly )
    175 {
    176 SCIP_CALL( SCIPreleaseCons(scip, &conss[idxs[i]]) );
    177 }
    178 else
    179 {
    180 SCIP_CALL( SCIPaddCons(scip, conss[idxs[i]]) );
    181 copycons = conss[idxs[i]];
    182 assert(SCIPconsGetNUses(copycons) > 1);
    183 SCIP_CALL( SCIPreleaseCons(scip, &copycons) );
    184 }
    185 }
    186
    187 return SCIP_OKAY;
    188}
    189
    190/* Update the batchsize accoring to the chosen rule */
    191static
    193 SCIP* scip, /**< SCIP data structure */
    194 int initbatchsize, /**< the initial batchsize */
    195 int maxbatchsize, /**< the maximum batchsize per iteration */
    196 int iteration, /**< the current iteration */
    197 SCIP_Bool resettoinit, /**< should the batchsize be reset to the initial batchsize? */
    198 SCIP_Real batchingfactor, /**< the factor with which the batchsize is multiplied in every update */
    199 SCIP_Real batchingoffset, /**< the offset which is added to the multiplied batchsize in every update */
    200 int batchupdateinterval, /**< the number of iterations to run with a constant batchsize before updating (1: always update) */
    201 int* batchsize /**< the batchsize to be updated */
    202 )
    203{
    204 if( resettoinit )
    205 *batchsize = initbatchsize;
    206 else if( iteration % batchupdateinterval == 0 )
    207 *batchsize = (int)ceil(batchingfactor * (*batchsize) + batchingoffset);
    208
    209 /* respect limits and maximum */
    210 *batchsize = MIN(*batchsize, maxbatchsize);
    211 *batchsize = MAX(*batchsize, 1);
    212 SCIPdebugMsg(scip, "Updated batchsize to %d\n", *batchsize);
    213
    214 return SCIP_OKAY;
    215}
    216
    217/** solve subproblem for deletionFilter */
    218static
    220 SCIP_IIS* iis, /**< IIS data structure containing subscip */
    221 SCIP_CONS** conss, /**< The array of constraints (may be a superset of the current constraints) */
    222 SCIP_VAR** vars, /**< the array of vars */
    223 int* idxs, /**< the indices of the constraints / vars that will be deleted / bounds removed */
    224 int ndels, /**< the number of bounds that will be deleted */
    225 SCIP_Real timelim, /**< The global time limit on the IIS finder call */
    226 SCIP_Real timelimperiter, /**< time limit per individual solve call */
    227 SCIP_Longint nodelim, /**< The global node limit on the IIS finder call */
    228 SCIP_Longint nodelimperiter, /**< maximum number of nodes per individual solve call */
    229 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 */
    230 SCIP_Bool delbounds, /**< whether bounds should be deleted instead of constraints */
    231 SCIP_Bool islb, /**< are the bounds that are being deleted LBs? */
    232 SCIP_Bool* deleted, /**< have the deleted bounds or constraints stayed deleted */
    233 SCIP_Bool* stop, /**< pointer to store whether we have to stop */
    234 SCIP_Bool* alldeletionssolved /**< pointer to store whether all the subscips solved */
    235 )
    236{
    237 SCIP* scip;
    238 SCIP_Real* bounds = NULL;
    239 SCIP_RETCODE retcode;
    240 SCIP_STATUS status;
    241 SCIP_Bool chgmade = FALSE;
    242 int i;
    243
    244 *deleted = FALSE;
    245 *stop = FALSE;
    246 scip = SCIPiisGetSubscip(iis);
    247
    248 /* remove bounds or constraints */
    249 if( delbounds )
    250 {
    251 assert(vars != NULL);
    252 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &bounds, ndels) );
    253 for (i = 0; i < ndels; ++i)
    254 {
    255 if( islb )
    256 {
    257 bounds[i] = SCIPvarGetLbOriginal(vars[idxs[i]]);
    258 if( !SCIPisInfinity(scip, -bounds[i]) )
    259 {
    260 SCIP_CALL( SCIPchgVarLb(scip, vars[idxs[i]], -SCIPinfinity(scip)) );
    261 chgmade = TRUE;
    262 }
    263 }
    264 else
    265 {
    266 bounds[i] = SCIPvarGetUbOriginal(vars[idxs[i]]);
    267 if( !SCIPisInfinity(scip, bounds[i]) )
    268 {
    269 SCIP_CALL( SCIPchgVarUb(scip, vars[idxs[i]], SCIPinfinity(scip)) );
    270 chgmade = TRUE;
    271 }
    272 }
    273 }
    274 }
    275 else
    276 {
    277 assert(conss != NULL);
    278
    279 if( ndels > 0 )
    280 chgmade = TRUE;
    281 for (i = 0; i < ndels; ++i)
    282 {
    283 assert( SCIPconsIsInProb(conss[idxs[i]]) );
    284 SCIP_CALL( SCIPcaptureCons(scip, conss[idxs[i]]) );
    285 SCIP_CALL( SCIPdelCons(scip, conss[idxs[i]]) );
    286 }
    287 }
    288
    289 if( !chgmade )
    290 {
    291 if( delbounds )
    292 SCIPfreeBlockMemoryArray(scip, &bounds, ndels);
    293 return SCIP_OKAY;
    294 }
    295
    296 /* solve problem until first solution is found or infeasibility has been proven */
    297 SCIP_CALL( setLimits(scip, iis, timelim, timelimperiter, nodelim, nodelimperiter) );
    298 retcode = SCIPsolve(scip);
    300
    301 if( retcode != SCIP_OKAY )
    302 {
    304 SCIPdebugMsg(scip, "Error in sub-scip with deleted constraints / bounds. Re-adding them.\n");
    305 if( delbounds )
    306 {
    307 SCIP_CALL( revertBndChgs(scip, vars, bounds, idxs, ndels, islb) );
    308 SCIPfreeBlockMemoryArray(scip, &bounds, ndels);
    309 }
    310 else
    311 {
    312 SCIP_CALL( revertConssDeletions(scip, conss, idxs, ndels, FALSE) );
    313 }
    314 *alldeletionssolved = FALSE;
    315 return SCIP_OKAY;
    316 }
    317
    318 status = SCIPgetStatus(scip);
    320
    321 /* check status and handle accordingly */
    322 switch ( status )
    323 {
    324 case SCIP_STATUS_USERINTERRUPT: /* if a user interrupt occurred, just stop */
    326 SCIPdebugMsg(scip, "User interrupt. Stopping.\n");
    327 if( delbounds )
    328 {
    329 SCIP_CALL( revertBndChgs(scip, vars, bounds, idxs, ndels, islb) );
    330 }
    331 else
    332 {
    333 SCIP_CALL( revertConssDeletions(scip, conss, idxs, ndels, !conservative) );
    334 }
    335 *stop = TRUE;
    336 *alldeletionssolved = FALSE;
    337 break;
    338
    339 case SCIP_STATUS_TIMELIMIT: /* if we reached some status that may have ended up in an infeasible problem */
    348 *alldeletionssolved = FALSE;
    349 SCIPdebugMsg(scip, "Some limit reached. Keeping bounds / constraints removed if non-conservative.\n");
    350 if( !conservative )
    351 {
    353 *deleted = TRUE;
    354 }
    355 if( conservative && delbounds )
    356 {
    357 SCIP_CALL( revertBndChgs(scip, vars, bounds, idxs, ndels, islb) );
    358 }
    359 if( !delbounds )
    360 {
    361 SCIP_CALL( revertConssDeletions(scip, conss, idxs, ndels, !conservative) );
    362 }
    363 break;
    364
    365 case SCIP_STATUS_INFEASIBLE: /* if the problem is infeasible */
    366 SCIPdebugMsg(scip, "Subproblem with bounds / constraints removed infeasible. Keep them removed.\n");
    368 if( !delbounds )
    369 {
    370 SCIP_CALL( revertConssDeletions(scip, conss, idxs, ndels, TRUE) );
    371 }
    372 *deleted = TRUE;
    373 break;
    374
    375 case SCIP_STATUS_BESTSOLLIMIT: /* we found a solution */
    380 SCIPdebugMsg(scip, "Found solution to subproblem with bounds / constraints removed. Add them back.\n");
    381 if( delbounds )
    382 {
    383 SCIP_CALL( revertBndChgs(scip, vars, bounds, idxs, ndels, islb) );
    384 }
    385 else
    386 {
    387 SCIP_CALL( revertConssDeletions(scip, conss, idxs, ndels, FALSE) );
    388 }
    389 break;
    390
    392 default:
    393 *alldeletionssolved = FALSE;
    394 SCIPerrorMessage("Unexpected return status %d in removed bounds subproblem. Exiting...\n", status);
    395 if( delbounds )
    396 SCIPfreeBlockMemoryArray(scip, &bounds, ndels);
    397 return SCIP_ERROR;
    398 }
    399
    400 if( delbounds )
    401 SCIPfreeBlockMemoryArray(scip, &bounds, ndels);
    402
    403 return SCIP_OKAY;
    404}
    405
    406/** solve subproblem for additionFilter */
    407static
    409 SCIP_IIS* iis, /**< IIS data structure containing subscip */
    410 SCIP_Real timelim, /**< The global time limit on the IIS finder call */
    411 SCIP_Real timelimperiter, /**< time limit per individual solve call */
    412 SCIP_Longint nodelim, /**< The global node limit on the IIS finder call */
    413 SCIP_Longint nodelimperiter, /**< maximum number of nodes per individual solve call */
    414 SCIP_Bool* feasible, /**< pointer to store whether the problem is feasible */
    415 SCIP_Bool* stop /**< pointer to store whether we have to stop */
    416 )
    417{
    418 SCIP* scip;
    419 SCIP_RETCODE retcode;
    420 SCIP_STATUS status;
    421
    422 assert( stop != NULL );
    423 scip = SCIPiisGetSubscip(iis);
    424
    425 *stop = FALSE;
    426
    427 /* solve problem until first solution is found or infeasibility has been proven */
    428 SCIP_CALL( setLimits(scip, iis, timelim, timelimperiter, nodelim, nodelimperiter) );
    429 retcode = SCIPsolve(scip);
    430
    431 if( retcode != SCIP_OKAY )
    432 {
    433 SCIPdebugMsg(scip, "Error in sub-scip with added constraints. Keep added constraints.\n");
    434 return SCIP_ERROR;
    435 }
    436
    438 status = SCIPgetStatus(scip);
    439
    440 /* check status */
    441 switch ( status )
    442 {
    443 case SCIP_STATUS_USERINTERRUPT: /* if an user interrupt occurred, just stop */
    445 SCIPdebugMsg(scip, "User interrupt. Stopping.\n");
    446 *stop = TRUE;
    447 break;
    448
    449 case SCIP_STATUS_NODELIMIT: /* if we reached some limit */
    459 SCIPdebugMsg(scip, "Some limit reached. Added constraint batch failed to induce infeasibility. Continue adding.\n");
    460 break;
    461
    462 case SCIP_STATUS_INFEASIBLE: /* if the problem is infeasible */
    463 SCIPdebugMsg(scip, "Subproblem with added constraints infeasible. Final batch of constraints added.\n");
    464 *feasible = FALSE;
    465 break;
    466
    467 case SCIP_STATUS_BESTSOLLIMIT: /* we found a solution */
    471 SCIPdebugMsg(scip, "Found solution of subproblem with added constraints. Keep adding constraint batches.\n");
    472 *feasible = TRUE;
    473 break;
    474
    476 default:
    477 SCIPerrorMessage("Unexpected return status %d. Exiting ...\n", status);
    478 return SCIP_ERROR;
    479 }
    480
    481 return SCIP_OKAY;
    482}
    483
    484
    485/** Deletion filter to greedily remove constraints to obtain an (I)IS */
    486static
    488 SCIP_IIS* iis, /**< IIS data structure containing subscip */
    489 SCIP_Real timelim, /**< The global time limit on the IIS finder call */
    490 SCIP_Longint nodelim, /**< The global node limit on the IIS finder call */
    491 SCIP_Bool removebounds, /**< Whether the algorithm should remove bounds as well as constraints */
    492 SCIP_Bool silent, /**< should the run be performed silently without printing progress information */
    493
    494 SCIP_Real timelimperiter, /**< time limit per individual solve call */
    495 SCIP_Longint nodelimperiter, /**< maximum number of nodes per individual solve call */
    496 SCIP_Bool conservative, /**< should a node or time limit solve be counted as feasible when deleting constraints */
    497
    498 int initbatchsize, /**< the initial batchsize for the first iteration */
    499 int maxbatchsize, /**< the maximum batchsize per iteration */
    500 SCIP_Real batchingfactor, /**< the factor with which the batchsize is multiplied in every update */
    501 SCIP_Real batchingoffset, /**< the offset which is added to the multiplied batchsize in every update */
    502 int batchupdateinterval, /**< the number of iterations to run with a constant batchsize before updating (1: always update) */
    503
    504 SCIP_Bool* alldeletionssolved /**< pointer to store whether all the subscips solved */
    505 )
    506{
    507 SCIP* scip;
    508 SCIP_CONS** origconss;
    509 SCIP_CONS** conss;
    510 SCIP_VAR** origvars;
    511 SCIP_VAR** vars;
    512 SCIP_RANDNUMGEN* randnumgen;
    513 int* order;
    514 int* idxs;
    515 SCIP_Bool stopiter;
    516 SCIP_Bool deleted;
    517 int nconss;
    518 int nvars;
    519 int batchindex;
    520 int batchsize;
    521 int iteration;
    522 int i;
    523 int k;
    524
    525 /* get current subscip */
    526 scip = SCIPiisGetSubscip(iis);
    527 assert( scip != NULL );
    528 assert( SCIPiisIsSubscipInfeasible(iis) );
    529
    530 /* get random generator */
    531 randnumgen = SCIPiisGetRandnumgen(iis);
    532 assert( randnumgen != NULL );
    533
    534 /* get batch size */
    535 assert( initbatchsize >= 1 );
    536 assert( maxbatchsize >= 1 );
    537 initbatchsize = MIN(initbatchsize, maxbatchsize);
    538
    539 /* allocate indices array */
    540 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &idxs, maxbatchsize) );
    541
    542 /* get constraint information */
    543 nconss = SCIPgetNOrigConss(scip);
    544 origconss = SCIPgetOrigConss(scip);
    545 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &conss, origconss, nconss) );
    546
    547 /* reset problem */
    550
    551 /* prepare random order for constraints */
    552 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &order, nconss) );
    553 for (i = 0; i < nconss; ++i)
    554 order[i] = i;
    555 SCIPrandomPermuteIntArray(randnumgen, order, 0, nconss);
    556
    557 /* Loop through all batches of constraints in random order */
    558 i = 0;
    559 iteration = 0;
    560 deleted = FALSE;
    561 stopiter = FALSE;
    562 while( i < nconss )
    563 {
    564 /* update batchsize */
    565 SCIP_CALL( updateBatchsize(scip, initbatchsize, maxbatchsize, iteration, !deleted, batchingfactor, batchingoffset, batchupdateinterval, &batchsize) );
    566
    567 k = 0;
    568 batchindex = i;
    569 while( i < nconss && k < batchsize )
    570 {
    571 assert( conss[order[i]] != NULL );
    572 if( SCIPconsGetNUses(conss[order[i]]) == 1 )
    573 {
    574 idxs[k] = order[i];
    575 k++;
    576 }
    577 i++;
    578 }
    579
    580 /* treat subproblem */
    581 SCIP_CALL( deletionSubproblem(iis, conss, NULL, idxs, k, timelim, timelimperiter, nodelim, nodelimperiter,
    582 conservative, FALSE, FALSE, &deleted, &stopiter, alldeletionssolved) );
    583 if( !silent && deleted )
    585
    586 if( timelim - SCIPiisGetTime(iis) <= 0 || ( nodelim != -1 && SCIPiisGetNNodes(iis) >= nodelim ) || stopiter )
    587 break;
    588
    589 /* reset i to beginning of current batch if batch has not been deleted and k was large */
    590 if( !deleted && k > initbatchsize )
    591 i = batchindex;
    592
    593 ++iteration;
    594
    596 }
    597
    598 SCIPfreeBlockMemoryArray(scip, &order, nconss);
    599 SCIPfreeBlockMemoryArray(scip, &conss, nconss);
    600 SCIPfreeBlockMemoryArray(scip, &idxs, maxbatchsize);
    601
    602 if( timelim - SCIPiisGetTime(iis) <= 0 || ( nodelim != -1 && SCIPiisGetNNodes(iis) >= nodelim ) || stopiter )
    603 return SCIP_OKAY;
    604
    605 /* Repeat the above procedure but for bounds instead of constraints */
    606 if( removebounds )
    607 {
    608 /* allocate indices array */
    609 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &idxs, maxbatchsize) );
    610
    611 nvars = SCIPgetNOrigVars(scip);
    612 origvars = SCIPgetOrigVars(scip);
    613 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &vars, origvars, nvars) );
    614
    615 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &order, nvars) );
    616 for (i = 0; i < nvars; ++i)
    617 order[i] = i;
    618 SCIPrandomPermuteIntArray(randnumgen, order, 0, nvars);
    619
    620 i = 0;
    621 iteration = 0;
    622 deleted = FALSE;
    623 while( i < nvars )
    624 {
    625 /* update batchsize */
    626 SCIP_CALL( updateBatchsize(scip, initbatchsize, maxbatchsize, iteration, !deleted, batchingfactor, batchingoffset, batchupdateinterval, &batchsize) );
    627
    628 k = 0;
    629 batchindex = i;
    630 /* Do not delete bounds of binary variables or bother with calculations of free variables */
    631 while( i < nvars && k < batchsize )
    632 {
    633 if( (SCIPvarGetType(vars[order[i]]) != SCIP_VARTYPE_BINARY) && (!SCIPisInfinity(scip, -SCIPvarGetLbOriginal(vars[order[i]])) || !SCIPisInfinity(scip, SCIPvarGetUbOriginal(vars[order[i]]))) )
    634 {
    635 idxs[k] = order[i];
    636 k++;
    637 }
    638 i++;
    639 }
    640 if( k == 0 )
    641 break;
    642
    643 /* treat subproblem with LB deletions */
    644 SCIP_CALL( deletionSubproblem(iis, NULL, vars, idxs, k, timelim, timelimperiter, nodelim, nodelimperiter,
    645 conservative, TRUE, TRUE, &deleted, &stopiter, alldeletionssolved) );
    646 if( timelim - SCIPiisGetTime(iis) <= 0 || ( nodelim != -1 && SCIPiisGetNNodes(iis) >= nodelim ) || stopiter )
    647 break;
    648 if( !silent && deleted )
    650
    651 /* treat subproblem with UB deletions */
    652 SCIP_CALL( deletionSubproblem(iis, NULL, vars, idxs, k, timelim, timelimperiter, nodelim, nodelimperiter,
    653 conservative, TRUE, FALSE, &deleted, &stopiter, alldeletionssolved) );
    654
    655 if( timelim - SCIPiisGetTime(iis) <= 0 || ( nodelim != -1 && SCIPiisGetNNodes(iis) >= nodelim ) || stopiter )
    656 break;
    657 if( !silent && deleted )
    659
    660 /* reset i to beginning of current batch if batch has not been deleted and k was large */
    661 if( !deleted && k > initbatchsize )
    662 i = batchindex;
    663
    664 ++iteration;
    665 }
    666
    667 SCIPfreeBlockMemoryArray(scip, &order, nvars);
    668 SCIPfreeBlockMemoryArray(scip, &vars, nvars);
    669 SCIPfreeBlockMemoryArray(scip, &idxs, maxbatchsize);
    670 }
    671
    672 return SCIP_OKAY;
    673}
    674
    675/** Addition filter to greedily add constraints to obtain an (I)IS */
    676static
    678 SCIP_IIS* iis, /**< IIS data structure containing subscip */
    679 SCIP_Real timelim, /**< The global time limit on the IIS finder call */
    680 SCIP_Longint nodelim, /**< The global node limit on the IIS finder call */
    681 SCIP_Bool silent, /**< should the run be performed silently without printing progress information */
    682
    683 SCIP_Real timelimperiter, /**< time limit per individual solve call */
    684 SCIP_Longint nodelimperiter, /**< maximum number of nodes per individual solve call */
    685 SCIP_Bool dynamicreordering, /**< should satisfied constraints outside the batch of an intermediate solve be added during the additive method */
    686
    687 int initbatchsize, /**< the initial batchsize for the first iteration */
    688 int maxbatchsize, /**< the maximum batchsize per iteration */
    689 SCIP_Real batchingfactor, /**< the factor with which the batchsize is multiplied in every update */
    690 SCIP_Real batchingoffset, /**< the offset which is added to the multiplied batchsize in every update */
    691 int batchupdateinterval /**< the number of iterations to run with a constant batchsize before updating (1: always update) */
    692 )
    693{
    694 SCIP* scip;
    695 SCIP_CONS** origconss;
    696 SCIP_CONS** conss;
    697 SCIP_RANDNUMGEN* randnumgen;
    698 SCIP_SOL* sol;
    699 SCIP_SOL* copysol;
    700 SCIP_Bool* inIS;
    701 int* order;
    702 SCIP_Bool feasible;
    703 SCIP_Bool stopiter;
    704 SCIP_RETCODE retcode;
    705 SCIP_RESULT result;
    706 int nconss;
    707 int batchsize;
    708 int iteration;
    709 int i;
    710 int j;
    711 int k;
    712
    713 /* get current subscip */
    714 scip = SCIPiisGetSubscip(iis);
    715 assert( scip != NULL );
    716 assert( SCIPiisIsSubscipInfeasible(iis) );
    717
    718 /* get random generator */
    719 randnumgen = SCIPiisGetRandnumgen(iis);
    720 assert( randnumgen != NULL );
    721
    722 /* get batch size */
    723 assert( initbatchsize >= 1 );
    724 assert( maxbatchsize >= 1 );
    725 initbatchsize = MIN(initbatchsize, maxbatchsize);
    726 batchsize = initbatchsize;
    727
    728 /* get constraint information */
    729 nconss = SCIPgetNOrigConss(scip);
    730 origconss = SCIPgetOrigConss(scip);
    731 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &conss, origconss, nconss) );
    732
    733 /* Initialise information for whether a constraint is in the final infeasible system */
    734 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &inIS, nconss) );
    735
    736 /* First capture and then delete all constraints */
    738 for( i = 0; i < nconss; ++i )
    739 {
    740 assert( SCIPconsIsInProb(conss[i]) );
    741 if( SCIPconsGetNUses(conss[i]) > 1 )
    742 {
    743 inIS[i] = TRUE;
    744 }
    745 else
    746 {
    747 SCIP_CALL( SCIPcaptureCons(scip, conss[i]) );
    748 SCIP_CALL( SCIPdelCons(scip, conss[i]) );
    749 inIS[i] = FALSE;
    750 }
    751 }
    753
    754 /* Prepare random order in which the constraints will be added back */
    755 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &order, nconss) );
    756 for (i = 0; i < nconss; ++i)
    757 order[i] = i;
    758 SCIPrandomPermuteIntArray(randnumgen, order, 0, nconss);
    759
    760 /* Continue to add constraints until an infeasible status is reached */
    761 i = 0;
    762 iteration = 0;
    763 feasible = TRUE;
    764 stopiter = FALSE;
    765 while( i < nconss )
    766 {
    767 /* Add the next batch of constraints */
    768 k = 0;
    769 while( i < nconss && k < batchsize )
    770 {
    771 if( !inIS[order[i]] )
    772 {
    773 SCIP_CALL( SCIPaddCons(scip, conss[order[i]]) );
    774 SCIP_CALL( SCIPreleaseCons(scip, &conss[order[i]]) );
    775 inIS[order[i]] = TRUE;
    776 ++k;
    777 }
    778 i++;
    779 }
    780
    781 /* We have the full infeasible problem again */
    782 if( i == nconss )
    783 {
    784 feasible = FALSE;
    785 break;
    786 }
    787
    788 /* Solve the reduced problem */
    789 retcode = additionSubproblem(iis, timelim, timelimperiter, nodelim, nodelimperiter, &feasible, &stopiter);
    790 if( !silent )
    792 if( !feasible || stopiter || timelim - SCIPiisGetTime(iis) <= 0 || ( nodelim != -1 && SCIPiisGetNNodes(iis) >= nodelim ) )
    793 {
    795 break;
    796 }
    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 if( k > 0 )
    832 {
    833 SCIPdebugMsg(scip, "Added %d constraints by reordering dynamically.\n", k);
    834 if( ! silent )
    836 }
    837 SCIP_CALL( SCIPfreeSol(scip, &copysol) );
    838 }
    839 }
    840 else
    841 {
    844 }
    845
    846 ++iteration;
    847
    848 /* update batchsize */
    849 SCIP_CALL( updateBatchsize(scip, initbatchsize, maxbatchsize, iteration, FALSE, batchingfactor, batchingoffset, batchupdateinterval, &batchsize) );
    850 }
    851
    852 /* Release any cons not in the IS */
    853 for( i = 0; i < nconss; ++i )
    854 {
    855 if( !inIS[order[i]] )
    856 {
    857 SCIP_CALL( SCIPreleaseCons(scip, &conss[order[i]]) );
    858 }
    859 }
    860
    861 SCIPfreeBlockMemoryArray(scip, &order, nconss);
    862 SCIPfreeBlockMemoryArray(scip, &inIS, nconss);
    863 SCIPfreeBlockMemoryArray(scip, &conss, nconss);
    864 if( feasible )
    866 else
    868
    869 return SCIP_OKAY;
    870}
    871
    872/** perform a greedy addition or deletion algorithm to obtain an infeasible subsystem (IS).
    873 *
    874 * This is the generation method for the greedy IIS finder rule.
    875 * Depending on the parameter choices, constraints are either greedily added from an empty problem,
    876 * or deleted from a complete problem. In the case of constraints being added, this is done until the problem
    877 * becomes infeasible, after which one can then begin deleting constraints. In the case of deleting constraints,
    878 * this is done until no more constraints (or batches of constraints) can be deleted without making
    879 * the problem feasible.
    880 */
    881static
    883 SCIP_IIS* iis, /**< IIS data structure */
    884 SCIP_IISFINDERDATA* iisfinderdata, /**< IIS finder data */
    885 SCIP_RESULT* result /**< pointer to store the result of the IIS finder run. SCIP_DIDNOTFIND if the algorithm failed, otherwise SCIP_SUCCESS. */
    886 )
    887{
    889 SCIP_Real timelim;
    890 SCIP_Longint nodelim;
    891 SCIP_Bool removebounds;
    892 SCIP_Bool silent;
    893 SCIP_Bool alldeletionssolved = TRUE;
    894 int nvars;
    895 int nconss;
    896 int maxbatchsize;
    897 int initbatchsize;
    898
    899 assert( scip != NULL );
    900 assert( iisfinderdata != NULL );
    901 assert( result != NULL );
    902
    903 SCIP_CALL( SCIPgetRealParam(scip, "iis/time", &timelim) );
    904 SCIP_CALL( SCIPgetLongintParam(scip, "iis/nodes", &nodelim) );
    905 SCIP_CALL( SCIPgetBoolParam(scip, "iis/removebounds", &removebounds) );
    906 SCIP_CALL( SCIPgetBoolParam(scip, "iis/silent", &silent) );
    907
    908 nvars = SCIPgetNOrigVars(scip);
    909 nconss = SCIPgetNOrigConss(scip);
    910 maxbatchsize = MAX(nvars, nconss);
    911 initbatchsize = iisfinderdata->initrelbatchsize > 0.0
    912 ? (int)ceil(iisfinderdata->initrelbatchsize * maxbatchsize) : MIN(iisfinderdata->initbatchsize, maxbatchsize);
    913 maxbatchsize = (int)ceil(iisfinderdata->maxrelbatchsize * maxbatchsize);
    914 maxbatchsize = MIN(iisfinderdata->maxbatchsize, maxbatchsize);
    915 initbatchsize = MAX(initbatchsize, 1);
    916 maxbatchsize = MAX(maxbatchsize, 1);
    917
    918 *result = SCIP_SUCCESS;
    919
    920 if( iisfinderdata->additive )
    921 {
    922 if( !silent )
    923 {
    924 SCIPdebugMsg(scip, "----- STARTING GREEDY ADDITION ALGORITHM -----\n");
    925 }
    926 SCIP_CALL( additionFilterBatch(iis, timelim, nodelim, silent, iisfinderdata->timelimperiter,
    927 iisfinderdata->nodelimperiter, iisfinderdata->dynamicreordering, initbatchsize, maxbatchsize,
    928 iisfinderdata->batchingfactor, iisfinderdata->batchingoffset, iisfinderdata->batchupdateinterval) );
    930 if( timelim - SCIPiisGetTime(iis) <= 0 || ( nodelim != -1 && SCIPiisGetNNodes(iis) >= nodelim ) )
    931 return SCIP_OKAY;
    932 }
    933 else
    934 {
    935 if( !silent )
    936 {
    937 SCIPdebugMsg(scip, "----- STARTING GREEDY DELETION ALGORITHM -----\n");
    938 }
    939 SCIP_CALL( deletionFilterBatch(iis, timelim, nodelim, removebounds, silent, iisfinderdata->timelimperiter,
    940 iisfinderdata->nodelimperiter, iisfinderdata->conservative, initbatchsize, maxbatchsize,
    941 iisfinderdata->batchingfactor, iisfinderdata->batchingoffset, iisfinderdata->batchupdateinterval,
    942 &alldeletionssolved) );
    943 if( timelim - SCIPiisGetTime(iis) <= 0 || ( nodelim != -1 && SCIPiisGetNNodes(iis) >= nodelim ) )
    944 return SCIP_OKAY;
    945 if( alldeletionssolved && initbatchsize == 1 )
    947 }
    948
    949 if( iisfinderdata->delafteradd && iisfinderdata->additive )
    950 {
    951 if( !silent )
    952 {
    953 SCIPdebugMsg(scip, "----- STARTING GREEDY DELETION ALGORITHM FOLLOWING COMPLETED ADDITION ALGORITHM -----\n");
    954 }
    955 SCIP_CALL( deletionFilterBatch(iis, timelim, nodelim, removebounds, silent, iisfinderdata->timelimperiter,
    956 iisfinderdata->nodelimperiter, iisfinderdata->conservative, initbatchsize, maxbatchsize,
    957 iisfinderdata->batchingfactor, iisfinderdata->batchingoffset, iisfinderdata->batchupdateinterval,
    958 &alldeletionssolved) );
    959 if( timelim - SCIPiisGetTime(iis) <= 0 || ( nodelim != -1 && SCIPiisGetNNodes(iis) >= nodelim ) )
    960 return SCIP_OKAY;
    961 if( alldeletionssolved && initbatchsize == 1 )
    963 }
    964
    965 return SCIP_OKAY;
    966}
    967
    968
    969/*
    970 * Callback methods of IIS finder
    971 */
    972
    973
    974/** copy method for IIS finder plugin (called when SCIP copies plugins) */
    975static
    976SCIP_DECL_IISFINDERCOPY(iisfinderCopyGreedy)
    977{ /*lint --e{715}*/
    978 assert(scip != NULL);
    979 assert(iisfinder != NULL);
    980 assert(strcmp(SCIPiisfinderGetName(iisfinder), IISFINDER_NAME) == 0);
    981
    982 /* call inclusion method of IIS finder */
    984
    985 return SCIP_OKAY;
    986}
    987
    988/** destructor of IIS finder to free user data (called when SCIP is exiting) */
    989/**! [SnippetIISfinderFreeGreedy] */
    990static
    991SCIP_DECL_IISFINDERFREE(iisfinderFreeGreedy)
    992{ /*lint --e{715}*/
    993 SCIP_IISFINDERDATA* iisfinderdata;
    994
    995 iisfinderdata = SCIPiisfinderGetData(iisfinder);
    996
    997 SCIPfreeBlockMemory(scip, &iisfinderdata);
    998
    999 SCIPiisfinderSetData(iisfinder, NULL);
    1000
    1001 return SCIP_OKAY;
    1002}
    1003/**! [SnippetIISfinderFreeGreedy] */
    1004
    1005/** IIS finder generation method of IIS */
    1006static
    1007SCIP_DECL_IISFINDEREXEC(iisfinderExecGreedy)
    1008{ /*lint --e{715}*/
    1009 SCIP_IISFINDERDATA* iisfinderdata;
    1010
    1011 assert(iisfinder != NULL);
    1012 assert(result != NULL);
    1013
    1014 *result = SCIP_DIDNOTFIND;
    1015
    1016 iisfinderdata = SCIPiisfinderGetData(iisfinder);
    1017 assert(iisfinderdata != NULL);
    1018
    1019 SCIP_CALL( execIISfinderGreedy(iis, iisfinderdata, result) );
    1020
    1021 return SCIP_OKAY;
    1022}
    1023
    1024
    1025/*
    1026 * IIS finder specific interface methods
    1027 */
    1028
    1029/** creates the greedy IIS finder and includes it in SCIP */
    1031 SCIP* scip /**< SCIP data structure */
    1032 )
    1033{
    1034 SCIP_IISFINDERDATA* iisfinderdata;
    1035 SCIP_IISFINDER* iisfinder;
    1036
    1037 /* create greedy IIS finder data */
    1038 SCIP_CALL( SCIPallocBlockMemory(scip, &iisfinderdata) );
    1039 BMSclearMemory(iisfinderdata);
    1040
    1042 iisfinderExecGreedy, iisfinderdata) );
    1043
    1044 assert(iisfinder != NULL);
    1045
    1046 /* set non fundamental callbacks via setter functions */
    1047 SCIP_CALL( SCIPsetIISfinderCopy(scip, iisfinder, iisfinderCopyGreedy) );
    1048 SCIP_CALL( SCIPsetIISfinderFree(scip, iisfinder, iisfinderFreeGreedy) );
    1049
    1050 /* add greedy IIS finder parameters */
    1052 "iis/" IISFINDER_NAME "/timelimperiter",
    1053 "time limit of optimization process for each individual subproblem",
    1054 &iisfinderdata->timelimperiter, FALSE, DEFAULT_TIMELIMPERITER, 0.0, SCIP_INVALID/10.0, NULL, NULL) );
    1055
    1057 "iis/" IISFINDER_NAME "/nodelimperiter",
    1058 "node limit of optimization process for each individual subproblem",
    1059 &iisfinderdata->nodelimperiter, FALSE, DEFAULT_NODELIMPERITER, -1L, SCIP_LONGINT_MAX, NULL, NULL) );
    1060
    1062 "iis/" IISFINDER_NAME "/additive",
    1063 "should an additive constraint approach be used instead of deletion",
    1064 &iisfinderdata->additive, FALSE, DEFAULT_ADDITIVE, NULL, NULL) );
    1065
    1067 "iis/" IISFINDER_NAME "/conservative",
    1068 "should an unsolved problem (by e.g. user interrupt, node limit, time limit) be considered feasible when deleting constraints",
    1069 &iisfinderdata->conservative, TRUE, DEFAULT_CONSERVATIVE, NULL, NULL) );
    1070
    1072 "iis/" IISFINDER_NAME "/delafteradd",
    1073 "should the deletion routine be performed after the addition routine (in the case of additive)",
    1074 &iisfinderdata->delafteradd, TRUE, DEFAULT_DELAFTERADD, NULL, NULL) );
    1075
    1077 "iis/" IISFINDER_NAME "/dynamicreordering",
    1078 "should satisfied constraints outside the batch of an intermediate solve be added during the additive method",
    1079 &iisfinderdata->dynamicreordering, TRUE, DEFAULT_DYNAMICREORDERING, NULL, NULL) );
    1080
    1082 "iis/" IISFINDER_NAME "/initbatchsize",
    1083 "the initial batchsize for the first iteration, ignored if initrelbatchsize is positive",
    1084 &iisfinderdata->initbatchsize, FALSE, DEFAULT_INITBATCHSIZE, 1, INT_MAX, NULL, NULL) );
    1085
    1087 "iis/" IISFINDER_NAME "/initrelbatchsize",
    1088 "the initial batchsize relative to the original problem for the first iteration (0.0: use initbatchsize)",
    1089 &iisfinderdata->initrelbatchsize, FALSE, DEFAULT_INITRELBATCHSIZE, 0.0, 1.0, NULL, NULL) );
    1090
    1092 "iis/" IISFINDER_NAME "/maxbatchsize",
    1093 "the maximum batchsize per iteration",
    1094 &iisfinderdata->maxbatchsize, TRUE, DEFAULT_MAXBATCHSIZE, 1, INT_MAX, NULL, NULL) );
    1095
    1097 "iis/" IISFINDER_NAME "/maxrelbatchsize",
    1098 "the maximum batchsize relative to the original problem per iteration",
    1099 &iisfinderdata->maxrelbatchsize, TRUE, DEFAULT_MAXRELBATCHSIZE, 0.0, 1.0, NULL, NULL) );
    1100
    1102 "iis/" IISFINDER_NAME "/batchingfactor",
    1103 "the factor with which the batchsize is multiplied in every update",
    1104 &iisfinderdata->batchingfactor, TRUE, DEFAULT_BATCHINGFACTOR, SCIP_REAL_MIN, SCIP_REAL_MAX, NULL, NULL) );
    1105
    1107 "iis/" IISFINDER_NAME "/batchingoffset",
    1108 "the offset which is added to the multiplied batchsize in every update",
    1109 &iisfinderdata->batchingoffset, TRUE, DEFAULT_BATCHINGOFFSET, SCIP_REAL_MIN, SCIP_REAL_MAX, NULL, NULL) );
    1110
    1112 "iis/" IISFINDER_NAME "/batchupdateinterval",
    1113 "the number of iterations to run with a constant batchsize before updating (1: always update)",
    1114 &iisfinderdata->batchupdateinterval, TRUE, DEFAULT_BATCHUPDATEINTERVAL, 1, INT_MAX, NULL, NULL) );
    1115
    1116 return SCIP_OKAY;
    1117}
    1118
    1119/** perform the greedy deletion algorithm with singleton batches to obtain an irreducible infeasible subsystem (IIS) */
    1121 SCIP_IIS* iis /**< IIS data structure */
    1122 )
    1123{
    1124 SCIP* scip = SCIPiisGetSubscip(iis);
    1125 SCIP_Real timelim;
    1126 SCIP_Longint nodelim;
    1127 SCIP_Bool removebounds;
    1128 SCIP_Bool silent;
    1129 SCIP_Bool alldeletionssolved = TRUE;
    1130 int nvars;
    1131 int nconss;
    1132 int maxbatchsize;
    1133
    1134 assert( scip != NULL );
    1135
    1136 if( !SCIPiisIsSubscipInfeasible(iis) )
    1137 {
    1138 SCIPerrorMessage("infeasible problem required\n");
    1139 return SCIP_INVALIDDATA;
    1140 }
    1141
    1142 nvars = SCIPgetNOrigVars(scip);
    1143 nconss = SCIPgetNOrigConss(scip);
    1144 maxbatchsize = MAX(nvars, nconss);
    1145
    1146 SCIP_CALL( SCIPgetRealParam(scip, "iis/time", &timelim) );
    1147 SCIP_CALL( SCIPgetLongintParam(scip, "iis/nodes", &nodelim) );
    1148 SCIP_CALL( SCIPgetBoolParam(scip, "iis/removebounds", &removebounds) );
    1149 SCIP_CALL( SCIPgetBoolParam(scip, "iis/silent", &silent) );
    1150
    1151 SCIP_CALL( deletionFilterBatch(iis, timelim, nodelim, removebounds, silent,
    1154 if( alldeletionssolved && SCIPiisGetTime(iis) < timelim && ( nodelim == -1 || SCIPiisGetNNodes(iis) < nodelim ) )
    1156
    1157 return SCIP_OKAY;
    1158}
    #define NULL
    Definition: def.h:248
    #define SCIP_Longint
    Definition: def.h:141
    #define SCIP_REAL_MAX
    Definition: def.h:158
    #define SCIP_INVALID
    Definition: def.h:178
    #define SCIP_Bool
    Definition: def.h:91
    #define MIN(x, y)
    Definition: def.h:224
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define SCIP_REAL_MIN
    Definition: def.h:159
    #define SCIP_LONGINT_MAX
    Definition: def.h:142
    #define SCIP_CALL(x)
    Definition: def.h:355
    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
    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:4316
    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:8409
    SCIP_Bool SCIPconsIsInProb(SCIP_CONS *cons)
    Definition: cons.c:8678
    int SCIPconsGetNUses(SCIP_CONS *cons)
    Definition: cons.c:8429
    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_RANDNUMGEN * SCIPiisGetRandnumgen(SCIP_IIS *iis)
    Definition: iisfinder.c:922
    SCIP_RETCODE SCIPsetIISfinderCopy(SCIP *scip, SCIP_IISFINDER *iisfinder, SCIP_DECL_IISFINDERCOPY((*iisfindercopy)))
    void SCIPiisAddNNodes(SCIP_IIS *iis, SCIP_Longint nnodes)
    Definition: iisfinder.c:912
    SCIP * SCIPiisGetSubscip(SCIP_IIS *iis)
    Definition: iisfinder.c:931
    const char * SCIPiisfinderGetName(SCIP_IISFINDER *iisfinder)
    Definition: iisfinder.c:311
    void SCIPiisSetSubscipIrreducible(SCIP_IIS *iis, SCIP_Bool irreducible)
    Definition: iisfinder.c:902
    SCIP_Longint SCIPiisGetNNodes(SCIP_IIS *iis)
    Definition: iisfinder.c:882
    SCIP_IISFINDERDATA * SCIPiisfinderGetData(SCIP_IISFINDER *iisfinder)
    Definition: iisfinder.c:625
    void SCIPiisfinderSetData(SCIP_IISFINDER *iisfinder, SCIP_IISFINDERDATA *iisfinderdata)
    Definition: iisfinder.c:635
    SCIP_Real SCIPiisGetTime(SCIP_IIS *iis)
    Definition: iisfinder.c:852
    void SCIPiisfinderInfoMessage(SCIP_IIS *iis, SCIP_Bool printheaders)
    Definition: iisfinder.c:713
    SCIP_Bool SCIPiisIsSubscipInfeasible(SCIP_IIS *iis)
    Definition: iisfinder.c:862
    void SCIPiisSetSubscipInfeasible(SCIP_IIS *iis, SCIP_Bool infeasible)
    Definition: iisfinder.c:892
    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)))
    #define SCIPfreeBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:110
    #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:2981
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1252
    SCIP_RETCODE SCIPunlinkSol(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1506
    SCIP_RETCODE SCIPcreateSolCopyOrig(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
    Definition: scip_sol.c:924
    SCIP_RETCODE SCIPfreeTransform(SCIP *scip)
    Definition: scip_solve.c:3462
    SCIP_RETCODE SCIPsolve(SCIP *scip)
    Definition: scip_solve.c:2635
    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:24020
    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:23453
    SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
    Definition: var.c:24063
    #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
    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_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