Scippy

    SCIP

    Solving Constraint Integer Programs

    conflict_resolution.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 conflict_resolution.c
    26 * @ingroup OTHER_CFILES
    27 * @brief Methods for generalized resolution conflict analysis.
    28 * @author Gioni Mexi
    29 *
    30 * This file implements a conflict analysis method based on generalized resolution,
    31 * as detailed in the paper:
    32 *
    33 * Gioni Mexi, et al. "Cut-based Conflict Analysis in Mixed Integer Programming."
    34 * arXiv preprint arXiv:2410.15110 (2024).
    35 *
    36 * The generalized resolution conflict analysis procedure starts with an initial
    37 * conflict row and it iteratively aggregates this row with a reason row—the row
    38 * that propagated the bound change causing the conflict. The aggregation
    39 * cancels the coefficient of the resolving variable. This process continues
    40 * until a first unique implication point (FUIP) is reached. If the aggregation
    41 * does not yield a valid (infeasible) row, the algorithm attempts to reduce the
    42 * reason row (e.g., using MIR reduction) and retries the aggregation. Once a
    43 * valid conflict row with negative slack is generated, a conflict constraint is
    44 * constructed and added to the problem.
    45 *
    46 */
    47/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    48
    50#include "scip/clock.h"
    51#include "scip/conflict.h"
    53#include "scip/cons.h"
    54#include "scip/cons_linear.h"
    55#include "scip/cuts.h"
    56#include "scip/history.h"
    57#include "scip/prob.h"
    58#include "scip/prop.h"
    59#include "scip/pub_cons.h"
    60#include "scip/pub_conflict.h"
    61#include "scip/pub_lp.h"
    62#include "scip/pub_message.h"
    63#include "scip/pub_misc.h"
    64#include "scip/pub_var.h"
    65#include "scip/scip_conflict.h"
    66#include "scip/scip_cons.h"
    67#include "scip/scip_mem.h"
    68#include "scip/scip_prob.h"
    69#include "scip/scip_sol.h"
    70#include "scip/scip_var.h"
    71#include "scip/set.h"
    72#include "scip/sol.h"
    74#include "scip/struct_lp.h"
    75#include "scip/struct_prob.h"
    76#include "scip/struct_set.h"
    77#include "scip/struct_stat.h"
    78#include "scip/tree.h"
    79#include "scip/var.h"
    80
    81#include <string.h>
    82#ifndef _WIN32
    83#include <strings.h> /*lint --e{766}*/
    84#endif
    85
    86/* parameters for MIR cuts*/
    87#define BOUNDSWITCH 0.51 /**< threshold for bound switching - see cuts.c */
    88#define POSTPROCESS FALSE /**< apply postprocessing after MIR calculation - see SCIPcalcMIR() */
    89#define USEVBDS FALSE /**< use variable bounds - see SCIPcalcMIR() */
    90#define FIXINTEGRALRHS FALSE /**< try to generate an integral rhs - see SCIPcalcMIR() */
    91#define MINFRAC 0.05 /**< minimal fractionality of floor(rhs) - see cuts.c */
    92#define MAXFRAC 0.999 /**< maximal fractionality of floor(rhs) - see cuts.c */
    93
    94#define EPS 1e-06
    95
    96/** creates a copy of the given generalized resolution row, allocating an additional amount of memory */
    97static
    99 SCIP_CONFLICTROW** targetrow, /**< pointer to store the generalized resolution row */
    100 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
    101 SCIP_CONFLICTROW* sourcerow /**< source generalized resolution row */
    102 )
    103{
    104 int targetsize;
    105 int nvars;
    106
    107 assert(targetrow != NULL);
    108 assert(sourcerow != NULL);
    109
    110 targetsize = sourcerow->nnz;
    111 nvars = sourcerow->nvars;
    112 SCIP_ALLOC( BMSallocBlockMemory(blkmem, targetrow) );
    113 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*targetrow)->inds, targetsize) );
    114 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*targetrow)->vals, nvars) );
    115
    116 /* copy all data from source to target */
    117 BMScopyMemoryArray((*targetrow)->inds, sourcerow->inds, targetsize);
    118 BMScopyMemoryArray((*targetrow)->vals, sourcerow->vals, nvars);
    119
    120 /* copy all other data */
    121 (*targetrow)->lhs = sourcerow->lhs;
    122 (*targetrow)->slack = sourcerow->slack;
    123 (*targetrow)->coefquotient = sourcerow->coefquotient;
    124 (*targetrow)->nvars = nvars;
    125 (*targetrow)->nnz = targetsize;
    126 (*targetrow)->size = targetsize;
    127 (*targetrow)->validdepth = sourcerow->validdepth;
    128 (*targetrow)->conflictdepth = sourcerow->conflictdepth;
    129 (*targetrow)->repropdepth = sourcerow->repropdepth;
    130 (*targetrow)->insertdepth = sourcerow->insertdepth;
    131 (*targetrow)->usescutoffbound = sourcerow->usescutoffbound;
    132 (*targetrow)->isbinary = sourcerow->isbinary;
    133 (*targetrow)->conflicttype = sourcerow->conflicttype;
    134
    135 return SCIP_OKAY;
    136}
    137
    138/** replaces a generalized resolution row by another; allocate an additional amount of memory if needed */
    139static
    141 SCIP_CONFLICTROW* targetrow, /**< pointer to store the generalized resolution row */
    142 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
    143 SCIP_CONFLICTROW* sourcerow /**< source generalized resolution row */
    144 )
    145{
    146 int sourcennzs;
    147 int targetsize;
    148 int nvars;
    149
    150 assert(targetrow != NULL);
    151 assert(sourcerow != NULL);
    152
    153 nvars = sourcerow->nvars;
    154 sourcennzs = sourcerow->nnz;
    155 targetsize = targetrow->size;
    156
    157 /* allocate additional memory for the indices array if needed */
    158 if( targetsize < sourcennzs )
    159 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &targetrow->inds, targetsize, sourcennzs) );
    160
    161 /* copy all data from source to target */
    162 BMScopyMemoryArray(targetrow->inds, sourcerow->inds, sourcennzs);
    163 BMScopyMemoryArray(targetrow->vals, sourcerow->vals, nvars);
    164
    165 targetrow->lhs = sourcerow->lhs;
    166 targetrow->slack = sourcerow->slack;
    167 targetrow->coefquotient = sourcerow->coefquotient;
    168 targetrow->nvars = sourcerow->nvars;
    169 targetrow->nnz = sourcennzs;
    170 targetrow->size = MAX(sourcennzs, targetsize);
    171 targetrow->validdepth = sourcerow->validdepth;
    172 targetrow->conflictdepth = sourcerow->conflictdepth;
    173 targetrow->repropdepth = sourcerow->repropdepth;
    174 targetrow->insertdepth = sourcerow->insertdepth;
    175 targetrow->usescutoffbound = sourcerow->usescutoffbound;
    176 targetrow->isbinary = sourcerow->isbinary;
    177 targetrow->conflicttype = sourcerow->conflicttype;
    178
    179 return SCIP_OKAY;
    180}
    181
    182/** resizes conflict rows array to be able to store at least num entries */
    183static
    185 SCIP_CONFLICT* conflict, /**< conflict analysis data */
    186 SCIP_SET* set, /**< global SCIP settings */
    187 int num /**< minimal number of slots in array */
    188 )
    189{
    190 assert(conflict != NULL);
    191 assert(set != NULL);
    192
    193 if( num > conflict->conflictrowssize )
    194 {
    195 int newsize;
    196
    197 newsize = SCIPsetCalcMemGrowSize(set, num);
    198 SCIP_ALLOC( BMSreallocMemoryArray(&conflict->conflictrows, newsize) );
    199 conflict->conflictrowssize = newsize;
    200 }
    201 assert(num <= conflict->conflictrowssize);
    202
    203 return SCIP_OKAY;
    204}
    205
    206/** add conflict row to the array of all conflicts rows */
    207static
    209 SCIP_CONFLICT* conflict, /**< conflict analysis data */
    210 SCIP_SET* set, /**< global SCIP settings */
    211 SCIP_CONFLICTROW** conflictrow /**< conflict row to add */
    212 )
    213{
    214 assert(conflict != NULL);
    215 assert(conflictrow != NULL);
    216
    217 /* insert resolution into the conflictrows array */
    218 SCIP_CALL( conflictEnsureConflictRowsMem(conflict, set, conflict->nconflictrows + 1) );
    219
    220 SCIPsetDebugMsgPrint(set, "inserting conflict row (valid depth: %d, conf depth: %d, reprop depth: %d):\n",
    221 (*conflictrow)->validdepth, (*conflictrow)->conflictdepth, (*conflictrow)->repropdepth);
    222
    223 conflict->conflictrows[conflict->nconflictrows] = *conflictrow;
    224 ++conflict->nconflictrows;
    225
    226 /* ownership of pointer is now in the conflictrows array */
    227 *conflictrow = NULL;
    228
    229 return SCIP_OKAY;
    230}
    231
    232/** gets number of conflict constraints found during propagation with the generalized resolution conflict analysis */
    234 SCIP_CONFLICT* conflict /**< conflict analysis data */
    235 )
    236{
    237 assert(conflict != NULL);
    238
    239 return conflict->nresconfconss;
    240}
    241
    242/** gets number of calls to generalized resolution conflict analysis that yield at least one conflict constraint */
    244 SCIP_CONFLICT* conflict /**< conflict analysis data */
    245 )
    246{
    247 assert(conflict != NULL);
    248
    249 return conflict->nressuccess;
    250}
    251
    252
    253/** gets number of calls to generalized resolution conflict analysis terminating because of large coefficients */
    255 SCIP_CONFLICT* conflict /**< conflict analysis data */
    256 )
    257{
    258 assert(conflict != NULL);
    259
    260 return conflict->nreslargecoefs;
    261}
    262
    263/** gets number of calls to generalized resolution conflict analysis terminating because of long conflicts */
    265 SCIP_CONFLICT* conflict /**< conflict analysis data */
    266 )
    267{
    268 assert(conflict != NULL);
    269
    270 return conflict->nreslongconfs;
    271}
    272
    273/** gets number of calls to generalized resolution conflict analysis */
    275 SCIP_CONFLICT* conflict /**< conflict analysis data */
    276 )
    277{
    278 assert(conflict != NULL);
    279
    280 return conflict->nrescalls;
    281}
    282
    283
    284#ifdef SCIP_DEBUG
    285/* Enum definition for the types of rows */
    286typedef enum {
    287 CONFLICT_ROWTYPE, /**< infeasible row at the current state */
    288 REASON_ROWTYPE, /**< reason row for the bound change that led to the infeasibility */
    289 REDUCED_REASON_ROWTYPE, /**< reason row after applying reason reduction */
    290 RESOLVED_CONFLICT_ROWTYPE, /**< resolved infeasible row (after adding the conflict and reason rows) */
    291 CONTINUOUS_REASON_ROWTYPE /**< reason row for a bound change on a continuous variable */
    292} ConflictRowType;
    293
    294/** prints a generalized resolution row */
    295static
    296void printConflictRow(
    297 SCIP_CONFLICTROW* row, /**< generalized resolution row to print */
    298 SCIP_SET* set, /**< global SCIP settings */
    299 SCIP_VAR** vars, /**< array of variables */
    300 int type /**< row type */
    301 )
    302{
    303 int nnzs;
    304 int v;
    305 int i;
    306
    307 assert(vars != NULL);
    308
    309 switch(type)
    310 {
    311 case CONFLICT_ROWTYPE:
    312 SCIPsetDebugMsgPrint(set, "Conflict Row: \n");
    313 break;
    314 case RESOLVED_CONFLICT_ROWTYPE:
    315 SCIPsetDebugMsgPrint(set, "Resolved Conflict Row: \n");
    316 break;
    317 case REASON_ROWTYPE:
    318 SCIPsetDebugMsgPrint(set, "Reason Row: \n");
    319 break;
    320 case REDUCED_REASON_ROWTYPE:
    321 SCIPsetDebugMsgPrint(set, "Reduced Reason Row: \n");
    322 break;
    323 case CONTINUOUS_REASON_ROWTYPE:
    324 SCIPsetDebugMsgPrint(set, "Continuous Reason Row: \n");
    325 break;
    326 default:
    327 break;
    328 }
    329 for( i = 0; i < row->nnz; i++ )
    330 {
    331 v = row->inds[i];
    332 assert(SCIPvarGetProbindex(vars[v]) == v);
    333 if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
    334 SCIPsetDebugMsgPrint(set, " %f<%s>[B]", row->vals[v], SCIPvarGetName(vars[v]));
    335 else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_INTEGER )
    336 SCIPsetDebugMsgPrint(set, " %f<%s>[I]", row->vals[v], SCIPvarGetName(vars[v]));
    337 else
    338 SCIPsetDebugMsgPrint(set, " %f<%s>[C]", row->vals[v], SCIPvarGetName(vars[v]));
    339 /* print the row in a readable way */
    340 if ((i + 1) % 5 == 0)
    342 }
    343 SCIPsetDebugMsgPrint(set, " >= %f\n", row->lhs);
    344
    345 /* just to check there are no other nonzeros in the dense array */
    346 nnzs = 0;
    347 for( i = 0; i < row->nvars; i++ )
    348 {
    349 if( !SCIPsetIsZero(set, row->vals[i]) )
    350 nnzs++;
    351 }
    352 assert(nnzs == row->nnz);
    353}
    354
    355/** print aggregated row */
    356static
    357void printAggrrow(
    358 SCIP_AGGRROW* aggrrow,
    359 SCIP_SET* set,
    360 SCIP_VAR** vars /**< array of variables */
    361 )
    362{
    363 int i;
    364 SCIP_Real QUAD(rhs);
    365 SCIP_Real QUAD(val);
    366 assert(aggrrow != NULL);
    367
    368 assert(vars != NULL);
    369 SCIPquadprecProdQD(rhs, aggrrow->rhs, 1.0);
    370
    371 SCIPsetDebugMsgPrint(set, "Aggregated Row: ");
    372 for( i = 0; i < aggrrow->nnz; i++ )
    373 {
    374 QUAD_ARRAY_LOAD(val, aggrrow->vals, aggrrow->inds[i]);
    375 if( SCIPvarGetType(vars[aggrrow->inds[i]]) == SCIP_VARTYPE_BINARY )
    376 SCIPsetDebugMsgPrint(set, " %+g<%s>[B]", QUAD_TO_DBL(val), SCIPvarGetName(vars[aggrrow->inds[i]]));
    377 else if( SCIPvarGetType(vars[aggrrow->inds[i]]) == SCIP_VARTYPE_INTEGER )
    378 SCIPsetDebugMsgPrint(set, " %+g<%s>[I]", QUAD_TO_DBL(val), SCIPvarGetName(vars[aggrrow->inds[i]]));
    379 else
    380 SCIPsetDebugMsgPrint(set, " %+g<%s>[C]", QUAD_TO_DBL(val), SCIPvarGetName(vars[aggrrow->inds[i]]));
    381 }
    382 SCIPsetDebugMsgPrint(set, " <= %+.15g\n", QUAD_TO_DBL(rhs));
    383}
    384
    385/** print a single bound change */
    386static
    387void printSingleBoundChange(
    388 SCIP_SET* set, /**< global SCIP settings */
    389 SCIP_BDCHGINFO* bdchginfo /**< bound change to print */
    390 )
    391{
    392 SCIP_VAR* var;
    393 var = SCIPbdchginfoGetVar(bdchginfo);
    394 SCIPsetDebugMsgPrint(set, " \t -> Bound change <%s> %s %.15g [status:%d, type:%d, depth:%d, pos:%d, reason:<%s>, global bounds:[%.15g,%.15g], local bounds:[%.15g,%.15g]] \n",
    395 SCIPvarGetName(var),
    396 SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
    397 SCIPbdchginfoGetNewbound(bdchginfo),
    399 SCIPbdchginfoGetDepth(bdchginfo), SCIPbdchginfoGetPos(bdchginfo),
    405}
    406
    407/** prints all bound changes in the queue in debug mode
    408 */
    409static
    410void printAllBoundChanges(
    411 SCIP_CONFLICT* conflict, /**< conflict analysis data */
    412 SCIP_SET* set, /**< global SCIP settings */
    413 SCIP_Bool continuousbdchgqueue/**< print the continuous bdchg queue */
    414 )
    415{
    416 SCIP_PQUEUE* bdchgqueue;
    417 SCIP_BDCHGINFO* bdchginfo;
    418 SCIP_VAR* var;
    419 int i;
    420
    421 assert(conflict != NULL);
    422
    423 bdchgqueue = continuousbdchgqueue ? conflict->continuousbdchgqueue : conflict->resbdchgqueue;
    424
    425 SCIPsetDebugMsgPrint(set, "Bound changes in %s bound change queue: \n", continuousbdchgqueue ? "continuous" : "resolution");
    426
    427 if( SCIPpqueueNElems(bdchgqueue) == 0 )
    428 {
    429 SCIPsetDebugMsgPrint(set, " \t -> The bound change queue is empty\n");
    430 return;
    431 }
    432
    433 for( i = 0; i < SCIPpqueueNElems(bdchgqueue); ++i )
    434 {
    435 bdchginfo = (SCIP_BDCHGINFO*)(SCIPpqueueElems(bdchgqueue)[i]);
    436 var = bdchginfo->var;
    437 SCIPsetDebugMsgPrint(set, " \t -> Bound change %d: <%s> %s %.15g [status:%d, type:%d, depth:%d, pos:%d, reason:<%s>, global bounds:[%.15g,%.15g], local bounds:[%.15g,%.15g]] \n",
    438 i, SCIPvarGetName(var),
    439 SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
    440 SCIPbdchginfoGetNewbound(bdchginfo),
    442 SCIPbdchginfoGetDepth(bdchginfo), SCIPbdchginfoGetPos(bdchginfo),
    447 : "none")),
    450 }
    451 SCIPsetDebugMsgPrint(set, "End of bound changes in queue. \n");
    452}
    453
    454/** print the type of the non resolvable reason */
    455static
    456void printNonResolvableReasonType(
    457 SCIP_SET* set, /**< global SCIP settings */
    458 SCIP_BDCHGINFO* bdchginfo /**< bound change to check */
    459 )
    460{
    461 SCIP_BOUNDCHGTYPE bdchgtype;
    462
    463 bdchgtype = SCIPbdchginfoGetChgtype(bdchginfo);
    464 if( bdchgtype == SCIP_BOUNDCHGTYPE_BRANCHING )
    465 {
    466 SCIPsetDebugMsgPrint(set, " \t -> Not resolvable bound change: branching \n");
    467 }
    468 else if( bdchgtype == SCIP_BOUNDCHGTYPE_PROPINFER )
    469 {
    470 SCIP_PROP* reasonprop;
    471 reasonprop = SCIPbdchginfoGetInferProp(bdchginfo);
    472
    473 SCIPsetDebugMsgPrint(set, " \t -> Not resolvable bound change: propagation %s \n",
    474 reasonprop != NULL ? SCIPpropGetName(reasonprop) : "none");
    475 }
    476 else
    477 {
    478 assert(bdchgtype == SCIP_BOUNDCHGTYPE_CONSINFER);
    479 SCIPsetDebugMsgPrint(set, " \t -> Not resolvable bound change: constraint %s \n", SCIPconsGetName(SCIPbdchginfoGetInferCons(bdchginfo)));
    480 }
    481}
    482
    483#endif
    484
    485/** calculates the maximal size of conflict sets to be used */
    486static
    488 SCIP_SET* set, /**< global SCIP settings */
    489 SCIP_PROB* prob /**< problem data */
    490 )
    491{
    492 int maxsize;
    493
    494 assert(set != NULL);
    495 assert(prob != NULL);
    496
    497 maxsize = (int)(set->conf_maxvarsfracres * (prob->nvars - prob->ncontvars));
    498 maxsize = MAX(maxsize, set->conf_minmaxvars);
    499 return maxsize;
    500}
    501
    502/** perform activity based coefficient tightening on a semi-sparse or sparse row defined with a left hand side */
    503static
    505 SCIP_SET* set, /**< global SCIP settings */
    506 SCIP_VAR** vars, /**< array of variables */
    507 SCIP_Bool localbounds, /**< do we use local bounds? */
    508 SCIP_Real* rowcoefs, /**< dense row of coefficients */
    509 int* rowinds, /**< indices of the variables in the row */
    510 int* rownnz, /**< number of non-zeros in the row */
    511 SCIP_Real* rowlhs, /**< left hand side of the row */
    512 int* nchgcoefs, /**< number of changed coefficients */
    513 SCIP_Bool* redundant /**< pointer to store whether the row is redundant */
    514 )
    515{
    516 int i;
    517 int nintegralvars;
    518 SCIP_Real* absvals;
    519 SCIP_Real QUAD(minacttmp);
    520 SCIP_Real minact;
    521 SCIP_Real maxabsval;
    522
    523 assert(nchgcoefs != NULL);
    524
    525 maxabsval = 0.0;
    526 QUAD_ASSIGN(minacttmp, 0.0);
    527
    528 assert(vars != NULL);
    529 nintegralvars = SCIPgetNVars(set->scip) - SCIPgetNContVars(set->scip);
    530 SCIP_CALL_ABORT( SCIPallocBufferArray(set->scip, &absvals, *rownnz) );
    531
    532 assert(nchgcoefs != NULL);
    533 *nchgcoefs = 0;
    534
    535 if( redundant != NULL )
    536 *redundant = FALSE;
    537
    538 /* compute activity of the row and get the absolute values of the coefficients */
    539 for( i = 0; i < *rownnz; ++i )
    540 {
    541 SCIP_VAR* var;
    542 int idx;
    543 int coefidx;
    544
    545 idx = rowinds[i];
    546 var = vars[idx];
    547 coefidx = idx;
    548
    549 assert(idx >= 0 && idx < SCIPgetNVars(set->scip));
    550 assert(var != NULL);
    551
    552 if( rowcoefs[coefidx] > 0.0 )
    553 {
    554 SCIP_Real lb = localbounds ? SCIPvarGetLbLocal(var) : SCIPvarGetLbGlobal(var);
    555
    556 if( SCIPsetIsInfinity(set, -lb) )
    557 goto TERMINATE_TIGHTENING;
    558
    559 if( idx < nintegralvars )
    560 {
    561 maxabsval = MAX(maxabsval, rowcoefs[coefidx]);
    562 absvals[i] = rowcoefs[coefidx];
    563 }
    564 else
    565 absvals[i] = 0.0;
    566
    567 SCIPquadprecSumQD(minacttmp, minacttmp, lb * rowcoefs[coefidx]);
    568 }
    569 else
    570 {
    571 SCIP_Real ub = localbounds ? SCIPvarGetUbLocal(var) : SCIPvarGetUbGlobal(var);
    572
    573 if( SCIPsetIsInfinity(set, ub) )
    574 goto TERMINATE_TIGHTENING;
    575
    576 if( idx < nintegralvars )
    577 {
    578 maxabsval = MAX(maxabsval, -rowcoefs[coefidx]);
    579 absvals[i] = -rowcoefs[coefidx];
    580 }
    581 else
    582 absvals[i] = 0.0;
    583
    584 SCIPquadprecSumQD(minacttmp, minacttmp, ub * rowcoefs[coefidx]);
    585 }
    586 }
    587
    588 minact = QUAD_TO_DBL(minacttmp);
    589
    590 /* row is redundant if minact is infinity */
    591 if( SCIPsetIsInfinity(set, minact ) )
    592 {
    593 if( redundant != NULL )
    594 *redundant = TRUE;
    595 goto TERMINATE_TIGHTENING;
    596 }
    597 /* no coefficients can be tightened */
    598 if( SCIPsetIsInfinity(set, -minact ) )
    599 {
    600 goto TERMINATE_TIGHTENING;
    601 }
    602
    603 /* propagating constraint cannot be redundant */
    604 assert(!SCIPsetIsGE(set, minact, *rowlhs));
    605
    606 /* terminate, because coefficient tightening cannot be performed; also
    607 excludes the case in which no integral variable is present */
    608 /* for lhs terminate if minact + maxabsval < rowlhs */
    609 if( SCIPsetIsLT(set, minact + maxabsval, *rowlhs) )
    610 goto TERMINATE_TIGHTENING;
    611
    612 SCIPsortDownRealInt(absvals, rowinds, *rownnz);
    613
    614 SCIPfreeBufferArray(set->scip, &absvals);
    615
    616 /* loop over the integral variables and try to tighten the coefficients; see cons_linear for more details */
    617 for( i = 0; i < *rownnz; ++i )
    618 {
    619 SCIP_VAR* var;
    620 int idx;
    621 int coefidx;
    622
    623 idx = rowinds[i];
    624 var = vars[idx];
    625 coefidx = idx;
    626
    627 assert(idx >= 0 && idx < SCIPgetNVars(set->scip));
    628 assert(var != NULL);
    629
    630 /* due to sorting, we can exit if we reached a continuous variable: all further integral variables have 0 coefficents anyway */
    631 if( idx >= nintegralvars )
    632 break;
    633
    634 assert(SCIPvarIsIntegral(var));
    635
    636 if( rowcoefs[coefidx] < 0.0 && SCIPsetIsGE(set, minact - rowcoefs[coefidx], *rowlhs) )
    637 {
    638 SCIP_Real newcoef = minact - (*rowlhs);
    639 SCIP_Real ub = localbounds ? SCIPvarGetUbLocal(var) : SCIPvarGetUbGlobal(var);
    640
    641 assert(SCIPsetIsGE(set, newcoef + EPS, rowcoefs[coefidx]) || SCIPsetIsRelGE(set, newcoef, rowcoefs[coefidx]));
    642 assert(!SCIPsetIsPositive(set, newcoef));
    643
    644 if( newcoef > rowcoefs[coefidx] )
    645 {
    646 SCIP_Real QUAD(delta);
    647 SCIP_Real QUAD(newlhs);
    648
    649 SCIPquadprecSumDD(delta, newcoef, -rowcoefs[coefidx]);
    650 SCIPquadprecProdQD(delta, delta, ub);
    651
    652 SCIPquadprecSumQD(newlhs, delta, *rowlhs);
    653 SCIPdebugPrintf("tightened coefficient from %g to %g; lhs changed from %g to %g; the bounds are [%g,%g]\n",
    654 rowcoefs[coefidx], newcoef, (*rowlhs), QUAD_TO_DBL(newlhs),
    655 localbounds ? SCIPvarGetUbLocal(var) : SCIPvarGetUbGlobal(var), ub);
    656
    657 *rowlhs = QUAD_TO_DBL(newlhs);
    658
    659 ++(*nchgcoefs);
    660
    661 if( SCIPsetIsNegative(set, newcoef) )
    662 {
    663 SCIPquadprecSumQQ(minacttmp, minacttmp, delta);
    664 minact = QUAD_TO_DBL(minacttmp);
    665 rowcoefs[coefidx] = newcoef;
    666 }
    667 else
    668 {
    669 --(*rownnz);
    670 rowcoefs[coefidx] = 0.0;
    671 rowinds[i] = rowinds[*rownnz];
    672 continue;
    673 }
    674 }
    675 }
    676 else if( rowcoefs[coefidx] > 0.0 && SCIPsetIsGE(set, minact + rowcoefs[coefidx], *rowlhs) )
    677 {
    678 SCIP_Real newcoef = (*rowlhs) - minact;
    679 SCIP_Real lb = localbounds ? SCIPvarGetLbLocal(var) : SCIPvarGetLbGlobal(var);
    680
    681 assert(SCIPsetIsLE(set, newcoef, rowcoefs[coefidx] + EPS) || SCIPsetIsRelLE(set, newcoef, rowcoefs[coefidx]));
    682 assert(!SCIPsetIsNegative(set, newcoef));
    683
    684 if( newcoef < rowcoefs[coefidx] )
    685 {
    686 SCIP_Real QUAD(delta);
    687 SCIP_Real QUAD(newlhs);
    688
    689 SCIPquadprecSumDD(delta, newcoef, -rowcoefs[coefidx]);
    690 SCIPquadprecProdQD(delta, delta, lb);
    691
    692 SCIPquadprecSumQD(newlhs, delta, *rowlhs);
    693 SCIPdebugPrintf("tightened coefficient from %g to %g; lhs changed from %g to %g; the bounds are [%g,%g]\n",
    694 rowcoefs[coefidx], newcoef, (*rowlhs), QUAD_TO_DBL(newlhs), lb,
    695 localbounds ? SCIPvarGetUbLocal(var) : SCIPvarGetUbGlobal(var));
    696
    697 *rowlhs = QUAD_TO_DBL(newlhs);
    698
    699 ++(*nchgcoefs);
    700
    701 if( SCIPsetIsPositive(set, newcoef) )
    702 {
    703 SCIPquadprecSumQQ(minacttmp, minacttmp, delta);
    704 minact = QUAD_TO_DBL(minacttmp);
    705 rowcoefs[coefidx] = newcoef;
    706 }
    707 else
    708 {
    709 --(*rownnz);
    710 rowcoefs[coefidx] = 0.0;
    711 rowinds[i] = rowinds[*rownnz];
    712 continue;
    713 }
    714 }
    715 }
    716 else /* due to sorting we can stop completely if the precondition was not fulfilled for this variable */
    717 break;
    718 }
    719
    720 TERMINATE_TIGHTENING:
    721 SCIPfreeBufferArrayNull(set->scip, &absvals);
    722
    723 return SCIP_OKAY;
    724}
    725
    726/** check if the generalized resolution row has a relaxation only variable */
    727static
    729 SCIP_SET* set, /**< global SCIP settings */
    730 SCIP_VAR** vars, /**< array of variables */
    731 SCIP_CONFLICTROW* row /**< generalized resolution row */
    732 )
    733{
    734 int i;
    735
    736 assert(set != NULL);
    737 assert(vars != NULL);
    738 assert(row != NULL);
    739
    740 for( i = 0; i < row->nnz; ++i )
    741 {
    742 SCIP_VAR* var;
    743
    744 var = vars[row->inds[i]];
    745 assert(var != NULL);
    746
    747 if( SCIPvarIsRelaxationOnly(var) )
    748 return TRUE;
    749 }
    750 return FALSE;
    751}
    752
    753/** check if a generalized resolution row has only binary variables */
    754static
    756 SCIP_SET* set, /**< global SCIP settings */
    757 SCIP_VAR** vars, /**< array of variables */
    758 SCIP_CONFLICTROW* row /**< generalized resolution row */
    759 )
    760{
    761 int i;
    762
    763 assert(set != NULL);
    764 assert(vars != NULL);
    765 assert(row != NULL);
    766
    767 for( i = 0; i < row->nnz; ++i )
    768 {
    769 SCIP_VAR* var;
    770
    771 var = vars[row->inds[i]];
    772 assert(var != NULL);
    773
    774 if( !SCIPvarIsBinary(var) )
    775 return FALSE;
    776 }
    777 return TRUE;
    778}
    779
    780/** Removes a variable with zero coefficient in the generalized resolution row */
    781static
    783 SCIP_CONFLICTROW* row, /**< generalized resolution row */
    784 SCIP_SET* set, /**< global SCIP settings */
    785 int pos /**< position of variable in conflict row */
    786 )
    787{
    788 int idx;
    789
    790 idx = row->inds[pos];
    791
    792 assert(row != NULL);
    793 assert(pos >= 0 && pos < row->nnz);
    794 assert(SCIPsetIsZero(set, row->vals[idx]));
    795
    796 --row->nnz;
    797 row->vals[idx] = 0.0;
    798 row->inds[pos] = row->inds[row->nnz];
    799}
    800
    801/** Removes all variables with zero coefficient (< 1e-09) in the generalized resolution row */
    802static
    804 SCIP_CONFLICTROW* row, /**< generalized resolution row */
    805 SCIP_SET* set /**< global SCIP settings */
    806 )
    807{
    808 int idx;
    809 assert(row != NULL);
    810 for( int i = row->nnz - 1; i >= 0; --i )
    811 {
    812 idx = row->inds[i];
    813 if( SCIPsetIsZero(set, row->vals[idx]) )
    815 }
    816}
    817
    818
    819/** complement and apply MIR to a 0-1 reason constraint lhs <= a^T x */
    820static
    822 SCIP_SET* set, /**< global SCIP settings */
    823 SCIP_VAR** vars, /**< array of variables */
    824 SCIP_CONFLICTROW* reasonrow, /**< reason row */
    825 int* fixsides, /**< dense array of variables fixed to a bound */
    826 SCIP_BDCHGIDX* currbdchgidx, /**< current bound change index */
    827 int idxreason, /**< index in the reason */
    828 SCIP_Real divisor /**< the divisor of the row */
    829 )
    830{
    831 SCIP_Real deltaoldlhs;
    832 SCIP_Real deltanewlhs;
    833 SCIP_Real oldlhs;
    834 SCIP_Real newlhs;
    835 SCIP_Real fraclhs;
    836 SCIP_Real resvarcoef;
    837 int varidx;
    838
    839 assert(set != NULL);
    840 assert(vars != NULL);
    841 assert(reasonrow != NULL);
    842 assert(reasonrow->inds != NULL);
    843 assert(reasonrow->vals != NULL);
    844 assert(reasonrow->nnz > 0);
    845
    846 assert(SCIPsetIsGT(set, divisor, 0.0));
    847
    848 if( !isBinaryConflictRow(set, vars, reasonrow) )
    849 return SCIP_OKAY;
    850
    851 SCIPsetDebugMsgPrint(set, "MIR on 0-1 constraint with LHS %f and divisor %f\n" , reasonrow->lhs, divisor);
    852
    853 /* complement and apply MIR to the reason constraint lhs <= a^T x
    854 * say the idxreason is k, and a_k > 0 (so this reason constraint fixes x_k to 1).
    855 * Then we complement as follows:
    856 * - if a_i > 0 and x_i is not fixed to 0, we complement it
    857 * - if a_i < 0 and x_i is fixed to 1, we complement it
    858 * whenever we complement a variable x_i, we need to modify the lhs with -a_i
    859 * Then we compute the fractionality of the lhs f(lhs) and do the following:
    860 * The coefficient of ~x_i is going to be -a_i, which after division is going to be -a_i/divisor; and after MIR,
    861 * it becomes CEIL(-a_i / divisor) if f(-a_i/divisor) >= f(lhs) or FLOOR(-a_i / divisor)+f(-a_i/divisor)/f(lhs) otherwise.
    862 * Complementing this again (to go back to x_i) the new coefficient of x_i is going to be -CEIL(-a_i / divisor)
    863 * or FLOOR(-a_i / divisor)+f(-a_i/divisor)/f(lhs) otherwise. It is going to
    864 * contribute the same amount to the lhs of the resulting constraint.
    865 * So we keep to lhs deltas, one for complementing in the original space, and another for complementing after we do C-G
    866 *
    867 * On the other hand, if a_k < 0 (so this reason constraint fixes x_k to 0), then we complement x_k (so modify the lhs by -a_k)
    868 * and then we are in the previous case. However, at the end, we need to complement back, which means that we modify the lhs by -1
    869 */
    870
    871 /* first handle x_k and initialize lhs deltas */
    872 varidx = idxreason;
    873 resvarcoef = reasonrow->vals[varidx];
    874 if( resvarcoef < 0.0 )
    875 {
    876 deltaoldlhs = -reasonrow->vals[varidx];
    877 deltanewlhs = -1.0;
    878 reasonrow->vals[varidx] = -1.0;
    879 }
    880 else
    881 {
    882 deltaoldlhs = 0.0;
    883 deltanewlhs = 0.0;
    884 reasonrow->vals[varidx] = 1.0;
    885 }
    886
    887 /* compute the delta for the left hand side after complementation in order to apply MIR
    888 * In a second loop set the new coefficients for the other variables and compute the lhs delta after complementation */
    889 for( int i = 0; i < reasonrow->nnz; ++i )
    890 {
    891 varidx = reasonrow->inds[i];
    892 SCIP_VAR* currentvar;
    893 SCIP_Real coef;
    894
    895 if( varidx == idxreason )
    896 continue;
    897
    898 coef = reasonrow->vals[varidx];
    899 currentvar = vars[varidx];
    900
    901 assert(SCIPvarIsBinary(currentvar));
    902
    903 /* complementation offset */
    904 if( (coef > 0.0 && (SCIPgetVarUbAtIndex(set->scip, currentvar, currbdchgidx, TRUE) > 0.5 && fixsides[varidx] != 1) ) ||
    905 (coef < 0.0 && (SCIPgetVarLbAtIndex(set->scip, currentvar, currbdchgidx, TRUE) > 0.5 || fixsides[varidx] == -1)))
    906 {
    907 deltaoldlhs += -coef;
    908 }
    909 }
    910 oldlhs = reasonrow->lhs;
    911 newlhs = (oldlhs + deltaoldlhs) / divisor;
    912 fraclhs = newlhs - SCIPsetFloor(set, newlhs);
    913
    914 if( fraclhs < MINFRAC || fraclhs > MAXFRAC )
    915 {
    916 reasonrow->vals[idxreason] = resvarcoef;
    917 SCIPsetDebugMsgPrint(set, "skip MIR because the fractionality of the lhs %f is not in [%f,%f]\n", fraclhs, MINFRAC, MAXFRAC);
    918 return SCIP_OKAY;
    919 }
    920
    921 /* set the new coefficients for the other variables and compute the lhs deltas */
    922 for( int i = 0; i < reasonrow->nnz; ++i )
    923 {
    924 varidx = reasonrow->inds[i];
    925 SCIP_VAR* currentvar;
    926 SCIP_Real newcoef;
    927 SCIP_Real coef;
    928 SCIP_Real fraccoef;
    929
    930 if( varidx == idxreason )
    931 continue;
    932
    933 coef = reasonrow->vals[varidx] / divisor;
    934 fraccoef = coef - SCIPsetFloor(set, coef);
    935 currentvar = vars[varidx];
    936
    937 if( (coef > 0.0 && (SCIPgetVarUbAtIndex(set->scip, currentvar, currbdchgidx, TRUE) > 0.5 && fixsides[varidx] != 1) ) ||
    938 (coef < 0.0 && (SCIPgetVarLbAtIndex(set->scip, currentvar, currbdchgidx, TRUE) > 0.5 || fixsides[varidx] == -1)))
    939 {
    940 if( (1.0 - fraccoef) >= fraclhs )
    941 {
    942 newcoef = -SCIPsetCeil(set, -coef);
    943
    944 reasonrow->vals[varidx] = newcoef;
    945 deltanewlhs += newcoef;
    946 }
    947 else
    948 {
    949 newcoef = -SCIPsetFloor(set, -coef) - (1 - fraccoef) / fraclhs;
    950
    951 reasonrow->vals[varidx] = newcoef;
    952 deltanewlhs += newcoef;
    953 }
    954 }
    955 else
    956 {
    957 if( fraccoef >= fraclhs )
    958 reasonrow->vals[varidx] = SCIPsetCeil(set, coef);
    959 else
    960 reasonrow->vals[varidx] = SCIPsetFloor(set, coef) + fraccoef / fraclhs;
    961 }
    962 }
    963
    964 newlhs = SCIPsetCeil(set, newlhs) + deltanewlhs;
    965 reasonrow->lhs = newlhs;
    966
    967 /* remove variables with zero coefficient. */
    968 conflictRowRemoveZeroVars(reasonrow, set);
    969
    970 return SCIP_OKAY;
    971}
    972
    973/* linear combination row1 = row1 + scale * row2 */
    974static
    976 SCIP_SET* set, /**< global SCIP settings */
    977 SCIP_CONFLICTROW* row1, /**< first row (aggregated row) */
    978 SCIP_CONFLICTROW* row2, /**< second row */
    979 SCIP_Real scale /**< scale factor for second row */
    980 )
    981{
    982 int i;
    983
    984 assert(set != NULL);
    985 assert(row1 != NULL);
    986 assert(row2 != NULL);
    987 assert(scale > 0.0);
    988
    989 /* add conflict and reason conflict rows; */
    990 for( i = 0; i < row2->nnz; ++i )
    991 {
    992 int idx;
    993 idx = row2->inds[i];
    994 assert(idx >= 0);
    995 if( SCIPsetIsZero(set, row1->vals[idx]) )
    996 {
    997 row1->inds[row1->nnz] = idx;
    998 row1->vals[idx] = scale * row2->vals[idx];
    999 row1->nnz++;
    1000 }
    1001 else
    1002 row1->vals[idx] = row1->vals[idx] + scale * row2->vals[idx];
    1003 }
    1004 row1->lhs = row1->lhs + scale * row2->lhs;
    1005
    1006 /* remove variables with zero coefficient. */
    1008}
    1009
    1010/** returns whether a bound change is resolvable or not */
    1011static
    1013 SCIP_BDCHGINFO* bdchginfo /**< bound change to check */
    1014 )
    1015{
    1016 SCIP_CONSHDLR *conshdlr;
    1017 SCIP_BOUNDCHGTYPE bdchgtype;
    1018 const char* conshdlrname;
    1019
    1020 bdchgtype = SCIPbdchginfoGetChgtype(bdchginfo);
    1021
    1022 /* branching */
    1023 if( bdchgtype == SCIP_BOUNDCHGTYPE_BRANCHING )
    1024 return FALSE;
    1025 /* propagation */
    1026 else if( bdchgtype == SCIP_BOUNDCHGTYPE_PROPINFER )
    1027 return FALSE;
    1028 /* constraint */
    1029 assert(bdchgtype == SCIP_BOUNDCHGTYPE_CONSINFER);
    1030 conshdlr = SCIPconsGetHdlr(SCIPbdchginfoGetInferCons(bdchginfo));
    1031 conshdlrname = SCIPconshdlrGetName(conshdlr);
    1032
    1033 if( strcmp(conshdlrname, "nonlinear") == 0 )
    1034 return FALSE;
    1035
    1036 return TRUE;
    1037}
    1038
    1039/** returns whether there exists a resolvable bound change or not */
    1040static
    1042 SCIP_CONFLICT* conflict /**< conflict analysis data */
    1043 )
    1044{
    1045 SCIP_BDCHGINFO* bdchginfo;
    1046 int i;
    1047
    1048 /* loop through bound change and check if there exists a resolvable bound change */
    1049 for( i = 0; i < SCIPpqueueNElems(conflict->resbdchgqueue); ++i )
    1050 {
    1051 bdchginfo = (SCIP_BDCHGINFO*)(SCIPpqueueElems(conflict->resbdchgqueue)[i]);
    1052 if( isResolvableBdchg(bdchginfo) )
    1053 return TRUE;
    1054 }
    1055 return FALSE;
    1056}
    1057
    1058/** returns whether a bound change is relevant for the infeasibility of the conflict row.
    1059 * A bound change is relevant if:
    1060 * - It is an upper bound change with a positive row coefficient,
    1061 * - It is a lower bound change with a negative row coefficient
    1062 */
    1063static
    1065 SCIP_CONFLICT* conflict, /**< conflict analysis data */
    1066 SCIP_BDCHGINFO* bdchginfo, /**< bound change to check */
    1067 int initial /**< whether we are in the initialization of conflict analysis */
    1068 )
    1069{
    1070 SCIP_CONFLICTROW* conflictrow;
    1071 SCIP_VAR* var;
    1072 int idx;
    1073
    1074 conflictrow = conflict->conflictrow;
    1075
    1076 /* the initial bound change is always relevant */
    1077 if( initial )
    1078 return TRUE;
    1079 /* if the conflict row is empty, we have a global infeasibility */
    1080 else if( conflictrow->nnz == 0 )
    1081 return FALSE;
    1082
    1083 var = SCIPbdchginfoGetVar(bdchginfo);
    1084 idx = SCIPvarGetProbindex(var);
    1085
    1086 if( (conflictrow->vals[idx] > 0 ) && (SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_UPPER) )
    1087 return TRUE;
    1088 else if( (conflictrow->vals[idx] < 0 ) && (SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER) )
    1089 return TRUE;
    1090 return FALSE;
    1091}
    1092
    1093/** returns next conflict analysis bound change candidate from the queue without removing it */
    1094static
    1096 SCIP_SET* set, /**< global SCIP settings */
    1097 SCIP_CONFLICT* conflict, /**< conflict analysis data */
    1098 int initial /**< whether we are in the initialization of conflict analysis */
    1099 )
    1100{
    1101 SCIP_BDCHGINFO* bdchginfo;
    1102
    1103 assert(conflict != NULL);
    1104
    1105 /* get next potential candidate */
    1106 bdchginfo = (SCIP_BDCHGINFO*)(SCIPpqueueFirst(conflict->resbdchgqueue));
    1107
    1108 /* check if this candidate is relevant for the conflict */
    1109 if( bdchginfo != NULL && !isBdchgConflictRelevant(conflict, bdchginfo, initial) )
    1110 {
    1111 SCIP_VAR* var;
    1112
    1113 var = SCIPbdchginfoGetVar(bdchginfo);
    1114
    1115 SCIPsetDebugMsgPrint(set, "\t -> bound change info [%d:%d<%s> %s %g] is invalid -> pop it from the queue\n",
    1116 SCIPbdchginfoGetDepth(bdchginfo),
    1117 SCIPbdchginfoGetPos(bdchginfo),
    1118 SCIPvarGetName(var),
    1119 SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
    1120 SCIPbdchginfoGetNewbound(bdchginfo));
    1121
    1122 /* remove the bound change info from the queue if it is not relevant */
    1123 (void)(SCIPpqueueRemove(conflict->resbdchgqueue));
    1124
    1127 else
    1129
    1130 /* call method recursively to get next conflict analysis candidate */
    1131 bdchginfo = conflictFirstCand(set, conflict, initial);
    1132 }
    1133
    1134 assert(bdchginfo == NULL || !SCIPbdchginfoIsRedundant(bdchginfo));
    1135
    1136 return bdchginfo;
    1137}
    1138
    1139/** removes and returns next conflict analysis bound change candidate from the queue */
    1140static
    1142 SCIP_CONFLICT* conflict, /**< conflict analysis data */
    1143 int initial /**< whether we are in the initialization of conflict analysis */
    1144 )
    1145{
    1146 SCIP_BDCHGINFO* bdchginfo;
    1147
    1148 assert(conflict != NULL);
    1149
    1150 bdchginfo = (SCIP_BDCHGINFO*)(SCIPpqueueRemove(conflict->resbdchgqueue));
    1151
    1152 assert(!SCIPbdchginfoIsRedundant(bdchginfo));
    1153
    1154 /* if we have a candidate this one should be valid for the current conflict analysis */
    1155 assert(isBdchgConflictRelevant(conflict, bdchginfo, initial));
    1156
    1157 return bdchginfo;
    1158}
    1159
    1160/** return TRUE if generalized resolution conflict analysis is applicable */
    1162 SCIP_SET* set /**< global SCIP settings */
    1163 )
    1164{
    1165 /* check, if generalized resolution conflict analysis is enabled */
    1166 if( !set->conf_enable || !set->conf_usegenres )
    1167 return FALSE;
    1168
    1169 return TRUE;
    1170}
    1171
    1172/** creates a generalized resolution row */
    1173static
    1175 SCIP_CONFLICTROW** row, /**< generalized resolution row */
    1176 BMS_BLKMEM* blkmem /**< block memory of transformed problem */
    1177 )
    1178{
    1179 assert(row != NULL);
    1180
    1181 SCIP_ALLOC( BMSallocBlockMemory(blkmem, row) );
    1182 (*row)->vals = NULL;
    1183 (*row)->inds = NULL;
    1184 (*row)->lhs = 0.0;
    1185 (*row)->slack = 0.0;
    1186 (*row)->coefquotient = 0.0;
    1187 (*row)->nvars = 0;
    1188 (*row)->nnz = 0;
    1189 (*row)->size = 0;
    1190 (*row)->validdepth = 0;
    1191 (*row)->conflictdepth = 0;
    1192 (*row)->repropdepth = 0;
    1193 (*row)->insertdepth = 0;
    1194 (*row)->usescutoffbound = FALSE;
    1195 (*row)->isbinary = FALSE;
    1196 (*row)->conflicttype = SCIP_CONFTYPE_PROPAGATION;
    1197
    1198 return SCIP_OKAY;
    1199}
    1200
    1201/** creates conflict and reason rows */
    1203 SCIP_CONFLICT* conflict, /**< conflict analysis data */
    1204 BMS_BLKMEM* blkmem /**< block memory of transformed problem */
    1205 )
    1206{
    1207 assert(conflict != NULL);
    1208 assert(blkmem != NULL);
    1209
    1210 SCIP_CALL( conflictRowCreate(&conflict->conflictrow, blkmem) );
    1211 SCIP_CALL( conflictRowCreate(&conflict->resolvedconflictrow, blkmem) );
    1212
    1213 SCIP_CALL( conflictRowCreate(&conflict->reasonrow, blkmem) );
    1214 SCIP_CALL( conflictRowCreate(&conflict->reducedreasonrow, blkmem) );
    1215
    1216 return SCIP_OKAY;
    1217}
    1218
    1219/** frees a generalized resolution row */
    1221 SCIP_CONFLICTROW** row, /**< conflict row */
    1222 BMS_BLKMEM* blkmem /**< block memory */
    1223 )
    1224{
    1225 assert(row != NULL);
    1226 assert(*row != NULL);
    1227 assert(blkmem != NULL);
    1228
    1229 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->vals, (*row)->nvars);
    1230 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->inds, (*row)->size);
    1231 BMSfreeBlockMemory(blkmem, row);
    1232 (*row) = NULL;
    1233}
    1234
    1235/** frees all conflict rows and arrays that track unresolvable (fixed) variables */
    1236static
    1238 SCIP_CONFLICT* conflict, /**< conflict analysis data */
    1239 BMS_BLKMEM* blkmem, /**< block memory */
    1240 SCIP_SET* set, /**< global SCIP settings */
    1241 SCIP_Real* fixbounds, /**< dense array of fixed bounds */
    1242 int* fixsides /**< dense array of variables fixed to a bound */
    1243 )
    1244{
    1245 SCIPsetFreeBufferArray(set, &fixsides);
    1246 SCIPsetFreeBufferArray(set, &fixbounds);
    1247
    1248 /* free all conflict rows */
    1249 for (int i = 0; i < conflict->nconflictrows; i++) {
    1250 SCIPconflictRowFree(&conflict->conflictrows[i], blkmem);
    1251 }
    1252 conflict->nconflictrows = 0;
    1253}
    1254
    1255/** resets the data structure of a generalized resolution row */
    1256static
    1258 BMS_BLKMEM* blkmem, /**< block memory */
    1259 SCIP_CONFLICTROW* row, /**< generalized resolution row */
    1260 int nvars /**< number of variables in the problem */
    1261 )
    1262{
    1263 int i;
    1264 assert(row != NULL);
    1265
    1266 /* this is necesseary to avoid memory leaks if the number of variables in the problem changes */
    1267 if( row->vals != NULL && row->nvars != nvars )
    1268 BMSfreeBlockMemoryArrayNull(blkmem, &row->vals, row->nvars);
    1269 if( row->vals == NULL )
    1270 BMSallocBlockMemoryArray(blkmem, &row->vals, nvars );
    1271
    1272 for( i = 0 ; i < nvars; ++i )
    1273 row->vals[i] = 0.0;
    1274
    1275 row->nvars = nvars;
    1276 row->nnz = 0;
    1277 row->lhs = 0.0;
    1278 row->slack = 0.0;
    1279 row->coefquotient = 0.0;
    1280 row->validdepth = 0;
    1281 row->conflictdepth = 0;
    1282 row->repropdepth = 0;
    1283 row->insertdepth = 0;
    1285 row->usescutoffbound = FALSE;
    1286 row->isbinary = FALSE;
    1287}
    1288
    1289/** calculates the slack (maxact - rhs) for a generalized resolution row given a set of bounds and coefficients */
    1290static
    1292 SCIP_SET* set, /**< global SCIP settings */
    1293 SCIP_VAR** vars, /**< array of variables */
    1294 SCIP_CONFLICTROW* row, /**< generalized resolution row */
    1295 SCIP_BDCHGINFO* currbdchginfo, /**< current bound change */
    1296 SCIP_Real* fixbounds, /**< dense array of fixed bounds */
    1297 int* fixsides /**< dense array of variables fixed to a bound */
    1298 )
    1299{
    1300 SCIP_BDCHGIDX * currbdchgidx;
    1301 SCIP_Real QUAD(slack);
    1302 int i;
    1303
    1304 assert(vars != NULL);
    1305
    1306#ifdef SCIP_MORE_DEBUG
    1307 SCIPsetDebugMsgPrint(set, "Calculating slack for row at depth %d position %d \n", SCIPbdchginfoGetDepth(currbdchginfo), SCIPbdchginfoGetPos(currbdchginfo));
    1308#endif
    1309 QUAD_ASSIGN(slack, 0.0);
    1310 if( currbdchginfo == NULL )
    1311 currbdchgidx = NULL;
    1312 else
    1313 currbdchgidx = SCIPbdchginfoGetIdx(currbdchginfo);
    1314 for( i = 0; i < row->nnz; i++ )
    1315 {
    1316 SCIP_Real coef;
    1318 SCIP_Real QUAD(delta);
    1319 int v;
    1320 v = row->inds[i];
    1321
    1322 assert(SCIPvarGetProbindex(vars[v]) == v);
    1323
    1324 coef = row->vals[v];
    1325
    1326 /* get the latest bound change before currbdchgidx */
    1327 if( coef > 0.0 )
    1328 {
    1329 if( fixsides != NULL && fixsides[v] == 1 ) /* if the variable is fixed */
    1330 {
    1331 assert(fixbounds != NULL);
    1332 bound = fixbounds[v];
    1333 }
    1334 else
    1335 {
    1336 bound = SCIPgetVarUbAtIndex(set->scip, vars[v], currbdchgidx, TRUE);
    1337 }
    1338 SCIPquadprecProdDD(delta, coef, bound);
    1339 }
    1340 else
    1341 {
    1342 if( fixsides != NULL && fixsides[v] == -1 ) /* if the variable is fixed */
    1343 {
    1344 assert(fixbounds != NULL);
    1345 bound = fixbounds[v];
    1346 }
    1347 else
    1348 {
    1349 bound = SCIPgetVarLbAtIndex(set->scip, vars[v], currbdchgidx, TRUE);
    1350 }
    1351 SCIPquadprecProdDD(delta, coef, bound);
    1352 }
    1353 SCIPquadprecSumQQ(slack, slack, delta);
    1354#ifdef SCIP_MORE_DEBUG
    1355 SCIPsetDebugMsgPrint(set, "var: %s, coef: %f, bound: %f global bounds:[%.15g,%.15g], current bounds:[%.15g,%.15g] \n",
    1356 SCIPvarGetName(vars[v]), coef, bound, SCIPvarGetLbGlobal(vars[v]), SCIPvarGetUbGlobal(vars[v]),
    1357 SCIPgetVarLbAtIndex(set->scip, vars[v], currbdchgidx, TRUE), SCIPgetVarUbAtIndex(set->scip, vars[v],
    1358 currbdchgidx, TRUE));
    1359 SCIPsetDebugMsgPrint(set, "slack: %f \n",QUAD_TO_DBL(slack) );
    1360#endif
    1361 }
    1362 SCIPquadprecSumQD(slack, slack, -row->lhs);
    1363#ifdef SCIP_MORE_DEBUG
    1364 SCIPsetDebugMsgPrint(set, "Row slack: %f \n",QUAD_TO_DBL(slack) );
    1365#endif
    1366 row->slack = QUAD_TO_DBL(slack);
    1367 return SCIP_OKAY;
    1368}
    1369
    1370/**
    1371 * reduces the reason row by applying MIR. In the reference solution, each variable is set to
    1372 * the value that was used for the propagation of currbdchginfo.
    1373 */
    1374static
    1376 SCIP_SET* set, /**< global SCIP settings */
    1377 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
    1378 SCIP_VAR** vars, /**< array of variables */
    1379 int nvars, /**< number of variables */
    1380 SCIP_CONFLICTROW* reasonrow, /**< reason row */
    1381 SCIP_BDCHGINFO* currbdchginfo, /**< current bound change to resolve */
    1382 int varidx, /**< index of the variable to resolve */
    1383 SCIP_Real divisor /**< the divisor of the row */
    1384 )
    1385{
    1386 SCIP_SOL* refsol;
    1387 SCIP_AGGRROW* aggrrow;
    1388 SCIP_BDCHGIDX* currbdchgidx;
    1389 int* cutinds;
    1390 SCIP_Real* cutcoefs;
    1391 int* rowinds;
    1392 SCIP_Real* rowvals;
    1393
    1394 int cutnnz;
    1395 int rownnz;
    1396 SCIP_Real cutrhs;
    1397 SCIP_Real rowrhs;
    1398
    1399 assert(set != NULL);
    1400 assert(vars != NULL);
    1401 assert(reasonrow != NULL);
    1402 assert(reasonrow->inds != NULL);
    1403 assert(reasonrow->vals != NULL);
    1404 assert(reasonrow->nnz > 0);
    1405
    1406 assert(SCIPsetIsGT(set, divisor, 0.0));
    1407
    1408 if( !SCIPvarIsIntegral(vars[varidx]) )
    1409 return SCIP_OKAY;
    1410
    1411 SCIPsetDebugMsgPrint(set, "Apply MIR on general constraint with LHS %f and divisor %f\n" , reasonrow->lhs, divisor);
    1412
    1413 currbdchgidx = SCIPbdchginfoGetIdx(currbdchginfo);
    1414 /* creating the aggregation row. There will be only a single row in this aggregation, since it is only used to
    1415 * compute the MIR coefficients
    1416 */
    1417 SCIP_CALL( SCIPaggrRowCreate(set->scip, &aggrrow) );
    1418
    1419 SCIP_CALL( SCIPcreateSol(set->scip, &refsol, NULL) );
    1420
    1421 /* initialize arrays for cut indices, cut coefficients, row indices, row values */
    1422 SCIP_CALL( SCIPsetAllocBufferArray(set, &cutinds, reasonrow->nnz) );
    1423 SCIP_CALL( SCIPsetAllocBufferArray(set, &cutcoefs, reasonrow->nnz) );
    1424 SCIP_CALL( SCIPsetAllocBufferArray(set, &rowinds, reasonrow->nnz) );
    1425 SCIP_CALL( SCIPsetAllocBufferArray(set, &rowvals, reasonrow->nnz) );
    1426
    1427 /* set all variables to zero in the reference solution */
    1428 for( int i = 0; i < nvars; ++i )
    1429 SCIP_CALL( SCIPsetSolVal(set->scip, refsol, vars[i], 0.0) );
    1430
    1431 /* create a sparse row of the form ax <= b from the reason */
    1432 rowrhs = -reasonrow->lhs;
    1433 rownnz = reasonrow->nnz;
    1434 for( int i = 0; i < rownnz; ++i )
    1435 {
    1436 int idx;
    1437 SCIP_Real coef;
    1438 idx = reasonrow->inds[i];
    1439 coef = reasonrow->vals[idx];
    1440 rowinds[i] = idx;
    1441 rowvals[i] = -coef;
    1442 /* We set the solution to the values used in propagation */
    1443 if( idx == varidx )
    1444 {
    1445 SCIP_Real fracval;
    1446 SCIP_Real bnd;
    1447 SCIP_CALL( computeSlack(set, vars, reasonrow, currbdchginfo, NULL, NULL) );
    1448 if( coef > 0.0 )
    1449 {
    1450 fracval = SCIPgetVarUbAtIndex(set->scip, vars[idx], currbdchgidx, FALSE) - reasonrow->slack / coef;
    1451 bnd = SCIPvarGetUbGlobal(vars[idx]);
    1452 fracval = MIN(fracval, bnd);
    1453 }
    1454 else
    1455 {
    1456 assert(coef < 0.0);
    1457 fracval = SCIPgetVarLbAtIndex(set->scip, vars[idx], currbdchgidx, FALSE) - reasonrow->slack / coef;
    1458 bnd = SCIPvarGetLbGlobal(vars[idx]);
    1459 fracval = MAX(fracval, bnd);
    1460 }
    1461 SCIP_CALL( SCIPsetSolVal(set->scip, refsol, vars[idx], fracval) );
    1462 }
    1463 else
    1464 {
    1465 if( coef > 0.0 )
    1466 SCIP_CALL( SCIPsetSolVal(set->scip, refsol, vars[idx], SCIPgetVarUbAtIndex(set->scip, vars[idx], currbdchgidx, FALSE)) );
    1467 else
    1468 SCIP_CALL( SCIPsetSolVal(set->scip, refsol, vars[idx], SCIPgetVarLbAtIndex(set->scip, vars[idx], currbdchgidx, FALSE)) );
    1469 }
    1470 }
    1471
    1472 SCIP_Bool cutislocal = FALSE;
    1473 SCIP_Bool success;
    1474
    1475 SCIP_CALL( SCIPaggrRowAddCustomCons(set->scip, aggrrow, rowinds, rowvals, rownnz, rowrhs, 1.0 / divisor, 1, FALSE) );
    1476
    1477 SCIPdebug(printAggrrow(aggrrow, set, vars));
    1478
    1479 /* apply MIR */
    1481 MINFRAC, MAXFRAC, 1.0, aggrrow, cutcoefs, &cutrhs, cutinds, &cutnnz, NULL, NULL, &cutislocal, &success) );
    1482
    1483 if( success )
    1484 {
    1485 assert(!cutislocal);
    1486 conflictRowClear(blkmem, reasonrow, nvars);
    1487 reasonrow->nnz = cutnnz;
    1488 reasonrow->lhs = -cutrhs;
    1489 for( int i = 0; i < cutnnz; ++i )
    1490 {
    1491 reasonrow->inds[i] = cutinds[i];
    1492 reasonrow->vals[cutinds[i]] = -cutcoefs[i];
    1493 }
    1494 }
    1495
    1496 /* remove variables with zero coefficient. Loop backwards */
    1497 conflictRowRemoveZeroVars(reasonrow, set);
    1498
    1499 SCIPaggrRowFree(set->scip, &aggrrow);
    1500 SCIP_CALL( SCIPfreeSol(set->scip, &refsol) );
    1501 SCIPsetFreeBufferArray(set, &cutinds);
    1502 SCIPsetFreeBufferArray(set, &cutcoefs);
    1503 SCIPsetFreeBufferArray(set, &rowinds);
    1504 SCIPsetFreeBufferArray(set, &rowvals);
    1505
    1506 return SCIP_OKAY;
    1507}
    1508
    1509/** weaken variable in a generalized resolution row */
    1510static
    1512 SCIP_CONFLICTROW* row, /**< generalized resolution row */
    1513 SCIP_SET* set, /**< global SCIP settings */
    1514 SCIP_VAR* var, /**< variable to weaken */
    1515 int pos /**< position in array of indices */
    1516 )
    1517{
    1518 int idx;
    1519
    1520 assert(row != NULL);
    1521 assert(var != NULL);
    1522 assert(pos >= 0 && pos < row->nvars);
    1523 assert(!SCIPsetIsZero(set, row->vals[row->inds[pos]]));
    1524
    1525 idx = row->inds[pos];
    1526
    1527 SCIPdebugMessage("weaken variable <%s> in the row \n", SCIPvarGetName(var));
    1528
    1529 /* weaken with global upper bound */
    1530 if( SCIPsetIsGT(set, row->vals[idx], 0.0) )
    1531 row->lhs -= row->vals[idx] * SCIPvarGetUbGlobal(var);
    1532 /* weaken with global lower bound */
    1533 else if(SCIPsetIsLT(set, row->vals[idx], 0.0))
    1534 row->lhs -= row->vals[idx] * SCIPvarGetLbGlobal(var);
    1535
    1536 --row->nnz;
    1537 row->vals[idx] = 0.0;
    1538 row->inds[pos] = row->inds[row->nnz];
    1539}
    1540
    1541/** weaken generalized resolution row by setting variables to their global bounds */
    1542static
    1544 SCIP_CONFLICTROW* row, /**< generalized resolution row */
    1545 SCIP_SET* set, /**< global SCIP settings */
    1546 SCIP_VAR** vars, /**< array of variables */
    1547 SCIP_BDCHGIDX* currbdchgidx, /**< current bound change index */
    1548 int* fixsides /**< dense array of variables fixed to a bound */
    1549 )
    1550{
    1551 int i;
    1552 int nvarsweakened;
    1553
    1554 assert(row != NULL);
    1555 assert(set != NULL);
    1556 assert(vars != NULL);
    1557 assert(currbdchgidx != NULL);
    1558
    1559 nvarsweakened = 0;
    1560
    1561 for( i = row->nnz - 1; i >= 0; --i )
    1562 {
    1563 SCIP_VAR* vartoweaken;
    1564 int idx;
    1565
    1566 idx = row->inds[i];
    1567 vartoweaken = vars[idx];
    1568
    1569 if( row->vals[idx] > 0.0 )
    1570 {
    1571 SCIP_Real ub;
    1572
    1573 ub = SCIPgetVarUbAtIndex(set->scip, vartoweaken, currbdchgidx, TRUE);
    1574
    1575 if( SCIPsetIsEQ(set, ub, SCIPvarGetUbGlobal(vartoweaken)) && (fixsides == NULL || fixsides[idx] == 0) )
    1576 {
    1577 weakenVarConflictRow(row, set, vartoweaken, i);
    1578 ++nvarsweakened;
    1579 }
    1580 }
    1581 else
    1582 {
    1583 SCIP_Real lb;
    1584
    1585 lb = SCIPgetVarLbAtIndex(set->scip, vartoweaken, currbdchgidx, TRUE);
    1586
    1587 if( SCIPsetIsEQ(set, lb, SCIPvarGetLbGlobal(vartoweaken)) && (fixsides == NULL || fixsides[idx] == 0) )
    1588 {
    1589 weakenVarConflictRow(row, set, vartoweaken, i);
    1590 ++nvarsweakened;
    1591 }
    1592 }
    1593 }
    1594
    1595 SCIPdebugMessage("weakened %d variables in the conflict row \n", nvarsweakened);
    1596}
    1597
    1598/** weaken all continuous variables in a generalized resolution row */
    1599static
    1601 SCIP_CONFLICTROW* row, /**< generalized resolution row */
    1602 SCIP_SET* set, /**< global SCIP settings */
    1603 SCIP_VAR** vars, /**< array of variables */
    1604 int residx /**< index of variable we are resolving on */
    1605 )
    1606{
    1607 int i;
    1608 int nvarsweakened;
    1609
    1610 assert(row != NULL);
    1611 assert(set != NULL);
    1612 assert(vars != NULL);
    1613
    1614 nvarsweakened = 0;
    1615
    1616 for( i = row->nnz - 1; i >= 0; --i )
    1617 {
    1618 SCIP_VAR* vartoweaken;
    1619 int idx;
    1620
    1621 idx = row->inds[i];
    1622 vartoweaken = vars[idx];
    1623
    1624 /* avoid weakening the variable we are resolving on */
    1625 if( idx == residx )
    1626 continue;
    1627 else if( row->vals[idx] > 0.0 && !SCIPvarIsIntegral(vartoweaken) )
    1628 {
    1629 weakenVarConflictRow(row, set, vartoweaken, i);
    1630 ++nvarsweakened;
    1631 }
    1632 else if( row->vals[idx] < 0.0 && !SCIPvarIsIntegral(vartoweaken) )
    1633 {
    1634 weakenVarConflictRow(row, set, vartoweaken, i);
    1635 ++nvarsweakened;
    1636 }
    1637 }
    1638
    1639 SCIPdebugMessage("weakened %d continuous variables in the row \n", nvarsweakened);
    1640
    1641 return SCIP_OKAY;
    1642}
    1643
    1644
    1645/** returns the quotient of the largest and smallest value in a semi-sparse array */
    1646static
    1648 SCIP_SET* set, /**< global SCIP settings */
    1649 int* inds, /**< array of indices */
    1650 SCIP_Real* vals, /**< dense array of values */
    1651 int nnz /**< number of nonzeros */
    1652 )
    1653{
    1654 int i;
    1655 SCIP_Real minval;
    1656 SCIP_Real maxval;
    1657
    1658 assert(vals != NULL);
    1659
    1660 if( nnz == 0 )
    1661 return 0.0;
    1662
    1663 minval = SCIPsetInfinity(set);
    1664 maxval = -SCIPsetInfinity(set);
    1665
    1666 for( i = 0; i < nnz; i++ )
    1667 {
    1668 int idx;
    1669 idx = inds[i];
    1670 minval = MIN(minval, vals[idx]);
    1671 maxval = MAX(maxval, vals[idx]);
    1672 }
    1673 return REALABS(maxval / minval);
    1674}
    1675
    1676/** for every variable in the row, except the inferred variable, add bound changes */
    1677static
    1679 SCIP_SET* set, /**< global SCIP settings */
    1680 SCIP_VAR** vars, /**< array of variables */
    1681 SCIP_CONFLICTROW* conflictrow, /**< conflict row */
    1682 SCIP_BDCHGIDX* inferbdchgidx /**< bound change index (time stamp of bound change), or NULL for current time */
    1683 )
    1684{
    1685 int i;
    1686
    1687 assert(vars != NULL);
    1688
    1689 /* scan through the row and add bound changes that make the constraint infeasible */
    1690 for( i = 0; i < conflictrow->nnz; i++ )
    1691 {
    1692 SCIP_Real coef;
    1693 int v;
    1694 v = conflictrow->inds[i];
    1695
    1696 assert(SCIPvarGetProbindex(vars[v]) == v);
    1697
    1698 coef = conflictrow->vals[v];
    1699
    1700 if( coef > 0.0 )
    1701 {
    1702 SCIP_Real bnd;
    1703 if( SCIPvarGetNBdchgInfosUb(vars[v]) > 0 )
    1704 {
    1705 bnd = SCIPgetVarUbAtIndex(set->scip, vars[v], inferbdchgidx, FALSE);
    1706 if( SCIPsetIsLT(set, bnd, SCIPvarGetUbGlobal(vars[v])) )
    1707 {
    1708 SCIP_CALL( SCIPaddConflictUb(set->scip, vars[v], inferbdchgidx) );
    1709 }
    1710 }
    1711 }
    1712 else
    1713 {
    1714 SCIP_Real bnd;
    1715 if( SCIPvarGetNBdchgInfosLb(vars[v]) > 0 )
    1716 {
    1717 bnd = SCIPgetVarLbAtIndex(set->scip, vars[v], inferbdchgidx, FALSE);
    1718 if( SCIPsetIsGT(set, bnd, SCIPvarGetLbGlobal(vars[v])) )
    1719 {
    1720 SCIP_CALL( SCIPaddConflictLb(set->scip, vars[v], inferbdchgidx) );
    1721 }
    1722 }
    1723 }
    1724 }
    1725 return SCIP_OKAY;
    1726}
    1727
    1728/** add all slack reducing continuous bound changes to the continuous bound change queue */
    1729static
    1731 SCIP_CONFLICT* conflict, /**< conflict analysis data */
    1732 SCIP_VAR** vars, /**< array of variables */
    1733 SCIP_CONFLICTROW* row, /**< conflict row */
    1734 SCIP_BDCHGIDX* inferbdchgidx /**< bound change index of latest continuous bound change */
    1735 )
    1736{
    1737 SCIP_PQUEUE* continuousbdchgqueue;
    1738 int i;
    1739
    1740 assert(vars != NULL);
    1741
    1742 continuousbdchgqueue = conflict->continuousbdchgqueue;
    1743
    1744 /* make sure that the continuous bound change queue is empty */
    1745 if( SCIPpqueueNElems(conflict->continuousbdchgqueue) != 0 )
    1747
    1748 /* For a row of the form ax >= b, we can add all continuous bound changes before inferbdchgidx that reduce the slack
    1749 * for each continuous variable x_k with coefficient a_k:
    1750 * - a_k > 0: then add bound changes (if not already present). Uses SCIPvarGetUbchgInfo() to get the latest
    1751 * bound change used in the slack of row.
    1752 * - a_k < 0: then add bound changes (if not already present). Uses SCIPvarGetLbchgInfo() to get the latest
    1753 * bound change used in the slack of row.
    1754 */
    1755 for( i = 0; i < row->nnz; i++ )
    1756 {
    1757 SCIP_Real coef;
    1758 int v;
    1759
    1760 v = row->inds[i];
    1761
    1762 assert(SCIPvarGetProbindex(vars[v]) == v);
    1763
    1764 if( SCIPvarIsIntegral(vars[v]) )
    1765 continue;
    1766
    1767 coef = row->vals[v];
    1768
    1769 if( coef > 0.0 )
    1770 {
    1771 SCIP_BDCHGINFO* bdchginfo = SCIPvarGetUbchgInfo(vars[v], inferbdchgidx, FALSE);
    1772 if( bdchginfo != NULL )
    1773 {
    1774 assert((SCIPbdchginfoGetDepth(bdchginfo) < SCIPbdchgidxGetDepth(inferbdchgidx)) ||
    1775 (SCIPbdchginfoGetDepth(bdchginfo) == SCIPbdchgidxGetDepth(inferbdchgidx) && SCIPbdchginfoGetPos(bdchginfo) < SCIPbdchgidxGetPos(inferbdchgidx)));
    1776 SCIP_CALL( SCIPpqueueInsert(continuousbdchgqueue, (void*)bdchginfo) );
    1777 }
    1778 }
    1779 else
    1780 {
    1781 SCIP_BDCHGINFO* bdchginfo = SCIPvarGetLbchgInfo(vars[v], inferbdchgidx, FALSE);
    1782 if( bdchginfo != NULL )
    1783 {
    1784 assert((SCIPbdchginfoGetDepth(bdchginfo) < SCIPbdchgidxGetDepth(inferbdchgidx)) ||
    1785 (SCIPbdchginfoGetDepth(bdchginfo) == SCIPbdchgidxGetDepth(inferbdchgidx) && SCIPbdchginfoGetPos(bdchginfo) < SCIPbdchgidxGetPos(inferbdchgidx)));
    1786 SCIP_CALL( SCIPpqueueInsert(continuousbdchgqueue, (void*)bdchginfo) );
    1787 }
    1788 }
    1789 }
    1790 return SCIP_OKAY;
    1791}
    1792
    1793/** increases the conflict score of the variable in the given direction */
    1794static
    1796 SCIP_VAR* var, /**< problem variable */
    1797 BMS_BLKMEM* blkmem, /**< block memory */
    1798 SCIP_SET* set, /**< global SCIP settings */
    1799 SCIP_STAT* stat, /**< dynamic problem statistics */
    1800 SCIP_BOUNDTYPE boundtype, /**< type of bound for which the score should be increased */
    1801 SCIP_Real value, /**< value of the bound */
    1802 SCIP_Real weight /**< weight of this VSIDS updates */
    1803 )
    1804{
    1805 SCIP_BRANCHDIR branchdir;
    1806
    1807 assert(var != NULL);
    1808 assert(stat != NULL);
    1809
    1810 /* weight the VSIDS by the given weight */
    1811 weight *= stat->vsidsweight;
    1812
    1813 if( SCIPsetIsZero(set, weight) )
    1814 return SCIP_OKAY;
    1815
    1816 branchdir = (boundtype == SCIP_BOUNDTYPE_LOWER ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS); /*lint !e641*/
    1817 SCIP_CALL( SCIPvarIncVSIDS(var, blkmem, set, stat, branchdir, value, weight) );
    1818 SCIPhistoryIncVSIDS(stat->glbhistory, branchdir, weight);
    1819 SCIPhistoryIncVSIDS(stat->glbhistorycrun, branchdir, weight);
    1820
    1821 return SCIP_OKAY;
    1822}
    1823
    1824/** update conflict statistics */
    1825static
    1827 SCIP_CONFLICT* conflict, /**< conflict analysis data */
    1828 SCIP_VAR** vars, /**< array of variables */
    1829 BMS_BLKMEM* blkmem, /**< block memory */
    1830 SCIP_SET* set, /**< global SCIP settings */
    1831 SCIP_STAT* stat, /**< dynamic problem statistics */
    1832 SCIP_CONFLICTROW* conflictrow, /**< conflict row to add to the tree */
    1833 int insertdepth /**< depth level at which the conflict set should be added */
    1834 )
    1835{
    1836 if( insertdepth > 0 )
    1837 {
    1838 conflict->nappliedlocconss++;
    1839 conflict->nappliedlocliterals += conflictrow->nnz;
    1840 }
    1841 else
    1842 {
    1843 int i;
    1844 int conflictlength;
    1845 conflictlength = conflictrow->nnz;
    1846
    1847 assert(vars != NULL);
    1848
    1849 for( i = 0; i < conflictlength; i++ )
    1850 {
    1851 int idx;
    1852 SCIP_VAR* var;
    1853 SCIP_BRANCHDIR branchdir;
    1854 SCIP_BOUNDTYPE boundtype;
    1856
    1857 assert(stat != NULL);
    1858
    1859 idx = conflictrow->inds[i];
    1860 var = vars[idx];
    1861
    1862 assert(!SCIPsetIsZero(set, conflictrow->vals[idx]));
    1863
    1864 boundtype = conflictrow->vals[idx] > 0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER;
    1865 bound = conflictrow->vals[idx] > 0 ? SCIPvarGetLbLocal(var) : SCIPvarGetUbLocal(var);
    1866
    1867 branchdir = (boundtype == SCIP_BOUNDTYPE_LOWER ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS); /*lint !e641*/
    1868
    1869 SCIP_CALL( SCIPvarIncNActiveConflicts(var, blkmem, set, stat, branchdir, bound, (SCIP_Real)conflictlength) );
    1870 SCIPhistoryIncNActiveConflicts(stat->glbhistory, branchdir, (SCIP_Real)conflictlength);
    1871 SCIPhistoryIncNActiveConflicts(stat->glbhistorycrun, branchdir, (SCIP_Real)conflictlength);
    1872
    1873 /* each variable which is part of the conflict gets an increase in the VSIDS */
    1874 SCIP_CALL( incVSIDS(var, blkmem, set, stat, boundtype, bound, set->conf_conflictweight) );
    1875 }
    1876 conflict->nappliedglbconss++;
    1877 conflict->nappliedglbliterals += conflictrow->nnz;
    1878 }
    1879
    1880 return SCIP_OKAY;
    1881}
    1882
    1883/** creates a conflict constraint and tries to add it to the storage */
    1884static
    1886 SCIP_CONFLICT* conflict, /**< conflict analysis data */
    1887 BMS_BLKMEM* blkmem, /**< block memory */
    1888 SCIP_SET* set, /**< global SCIP settings */
    1889 SCIP_STAT* stat, /**< dynamic problem statistics */
    1890 SCIP_VAR** vars, /**< array of variables */
    1891 SCIP_TREE* tree, /**< branch and bound tree */
    1892 SCIP_REOPT* reopt, /**< reoptimization data structure */
    1893 SCIP_LP* lp, /**< current LP data */
    1894 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
    1895 SCIP_CONFLICTROW* conflictrow, /**< conflict row to add to the tree */
    1896 int insertdepth, /**< depth level at which the conflict set should be added */
    1897 SCIP_Bool* success /**< pointer to store whether the addition was successful */
    1898 )
    1899{
    1900 SCIP_VAR** consvars;
    1901 SCIP_CONS* cons;
    1902 SCIP_CONS* upgdcons;
    1903
    1904 char consname[SCIP_MAXSTRLEN];
    1905
    1906 SCIP_Real* vals;
    1907 SCIP_Real lhs;
    1908 int i;
    1909
    1910 assert(vars != NULL);
    1911 assert(conflictrow->nnz > 0);
    1912
    1913 SCIP_CALL( SCIPallocBufferArray(set->scip, &consvars, conflictrow->nnz) );
    1914 SCIP_CALL( SCIPallocBufferArray(set->scip, &vals, conflictrow->nnz) );
    1915
    1916 lhs = conflictrow->lhs;
    1917
    1918 for( i = 0; i < conflictrow->nnz; ++i )
    1919 {
    1920 int idx;
    1921 idx = conflictrow->inds[i];
    1922 assert(conflictrow->vals[idx]);
    1923 consvars[i] = vars[idx];
    1924 vals[i] = conflictrow->vals[idx];
    1925 }
    1926
    1927 /* create a constraint out of the conflict set */
    1928 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "confres_%" SCIP_LONGINT_FORMAT, conflict->nresconfconss);
    1929 SCIP_CALL( SCIPcreateConsLinear(set->scip, &cons, consname, conflictrow->nnz, consvars, vals,
    1930 lhs, SCIPsetInfinity(set), FALSE, FALSE, FALSE, FALSE, TRUE, (SCIPnodeGetDepth(tree->path[conflictrow->validdepth]) > 0 ),
    1931 FALSE, set->conf_dynamic, set->conf_removable, FALSE) );
    1932
    1933 /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
    1934 SCIP_CALL( SCIPupgradeConsLinear(set->scip, cons, &upgdcons) );
    1935 if( upgdcons != NULL )
    1936 {
    1937 SCIP_CALL( SCIPreleaseCons(set->scip, &cons) );
    1938 cons = upgdcons;
    1939 }
    1940
    1941 /* check if the constraint is valid for the debug solution */
    1942 SCIP_CALL( SCIPdebugCheckConss(set->scip, &cons, 1) );
    1943
    1944 /* update statistics */
    1945 SCIP_CALL( updateStatistics(conflict, vars, blkmem, set, stat, conflictrow, conflictrow->validdepth) );
    1946
    1947 /* add conflict to SCIP */
    1948 SCIP_CALL( SCIPaddConflict(set->scip, tree->path[insertdepth], &cons, tree->path[conflictrow->validdepth], conflictrow->conflicttype, conflictrow->usescutoffbound) );
    1949 *success = TRUE;
    1950 /* free temporary memory */
    1951 SCIPfreeBufferArray(set->scip, &consvars);
    1952 SCIPfreeBufferArray(set->scip, &vals);
    1953
    1954 return SCIP_OKAY;
    1955}/*lint !e715*/
    1956
    1957/** create conflict constraints out of conflict row and add them to the problem */
    1959 SCIP_CONFLICT* conflict, /**< conflict analysis data */
    1960 BMS_BLKMEM* blkmem, /**< block memory */
    1961 SCIP_SET* set, /**< global SCIP settings */
    1962 SCIP_STAT* stat, /**< dynamic problem statistics */
    1963 SCIP_PROB* transprob, /**< transformed problem */
    1964 SCIP_PROB* origprob, /**< original problem */
    1965 SCIP_TREE* tree, /**< branch and bound tree */
    1966 SCIP_REOPT* reopt, /**< reoptimization data structure */
    1967 SCIP_LP* lp, /**< current LP data */
    1968 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    1969 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    1970 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    1971 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
    1972 SCIP_CONFLICTROW* conflictrow, /**< conflict row to add to the tree */
    1973 SCIP_Bool* success /**< true if the conflict is added to the problem */
    1974 )
    1975{
    1976 SCIP_VAR** vars;
    1977 int focusdepth;
    1978 int maxsize;
    1979
    1980 vars = SCIPprobGetVars(transprob);
    1981
    1982 focusdepth = SCIPtreeGetFocusDepth(tree);
    1983
    1984 assert(conflict != NULL);
    1985 assert(set != NULL);
    1986 assert(stat != NULL);
    1987 assert(transprob != NULL);
    1988 assert(tree != NULL);
    1989 assert(conflictrow != NULL);
    1990 assert(conflictrow->validdepth == 0);
    1991 assert(vars != NULL);
    1992 assert(success != NULL);
    1993
    1994 assert(focusdepth <= SCIPtreeGetCurrentDepth(tree));
    1995 assert(SCIPtreeGetCurrentDepth(tree) == tree->pathlen-1);
    1996
    1997 /* calculate the maximal size of each accepted conflict set */
    1998 maxsize = 2 * conflictCalcResMaxsize(set, transprob);
    1999
    2000 SCIPsetDebugMsgPrint(set, "flushing conflict constraint at focus depth %d (id: %d, vd: %d, cd: %d, rd: %d, maxsize: %d)\n",
    2001 focusdepth, conflictrow->insertdepth, conflictrow->validdepth, conflictrow->conflictdepth, conflictrow->repropdepth, maxsize);
    2002
    2003 *success = FALSE;
    2004
    2005 /* do not add long conflicts */
    2006 if( conflictrow->nnz > maxsize )
    2007 {
    2008 conflict->nreslongconfs++;
    2009 SCIPsetDebugMsgPrint(set, " \t -> conflict row is too long: %d > %d nnzs\n", conflictrow->nnz, maxsize);
    2010 }
    2011 /* if the conflict row is empty and the lhs positive, the node and its sub-
    2012 * tree in the conflict row's valid depth can be cut off completely
    2013 */
    2014 else if( conflictrow->nnz == 0 && SCIPsetIsGT(set, conflictrow->lhs, 0.0) )
    2015 {
    2016 SCIPsetDebugMsgPrint(set, " \t -> empty conflict row with lhs %f in depth %d cuts off sub tree at depth %d\n",
    2017 conflictrow->lhs, focusdepth, conflictrow->validdepth);
    2018 *success = TRUE;
    2019 SCIP_CALL( SCIPnodeCutoff(tree->path[conflictrow->validdepth], set, stat, eventfilter, tree, transprob, origprob, reopt, lp, blkmem) );
    2020 }
    2021 /* in case the conflict set contains only one bound change which is globally valid we apply that bound change
    2022 * directly (except if we are in strong branching or diving - in this case a bound change would yield an unflushed LP
    2023 * and is not handled when restoring the information)
    2024 *
    2025 * @note A bound change can only be applied if it is related to the active node or if is a global bound
    2026 * change. Bound changes which are related to any other node cannot be handled at point due to the internal
    2027 * data structure
    2028 */
    2029 else if( !hasRelaxationOnlyVar(set, vars, conflictrow) && conflictrow->nnz == 1 && conflictrow->insertdepth == 0 && !lp->strongbranching && !lp->diving )
    2030 {
    2031 SCIP_VAR* var;
    2033 SCIP_BOUNDTYPE boundtype;
    2034 int idx;
    2035
    2036 idx = conflictrow->inds[0];
    2037 var = vars[idx];
    2038 assert(!SCIPsetIsZero(set, conflictrow->vals[idx]));
    2039 assert(var != NULL);
    2040
    2041 boundtype = conflictrow->vals[idx] > 0.0 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER;
    2042
    2043 /* Since the conflictrow is in the form a*x >= b:
    2044 * For integer variables:
    2045 * coef > 0: The lower bound change is equal to ceil(lhs / coef)
    2046 * coef < 0: The upper bound change is equal to floor(lhs / coef)
    2047 * For continuous variables we do not round the bound change
    2048 */
    2049 bound = conflictrow->lhs / conflictrow->vals[idx];
    2050 if( SCIPvarIsIntegral(var) )
    2051 bound = conflictrow->vals[idx] > 0.0 ? SCIPsetCeil(set, bound) : SCIPsetFloor(set, bound);
    2052
    2053 /* todo: rethink the logic and add asserts. Also find a better way
    2054 * to inform the statistics that a constraint is added "indirectly", also
    2055 * update number of global bound changes from conflict analysis */
    2057 {
    2058 SCIPsetDebugMsgPrint(set, " \t -> Bound %s >= %f contradicts with the global upper bound %s <= %f\n",
    2060 SCIP_CALL( SCIPnodeCutoff(tree->path[conflictrow->validdepth], set, stat, eventfilter, tree, transprob, origprob, reopt, lp, blkmem) );
    2061 }
    2062 else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, bound, SCIPvarGetLbGlobal(var)) )
    2063 {
    2064 SCIPsetDebugMsgPrint(set, " \t -> Bound %s <= %f contradicts with the global lower bound %s >= %f\n",
    2066 SCIP_CALL( SCIPnodeCutoff(tree->path[conflictrow->validdepth], set, stat, eventfilter, tree, transprob, origprob, reopt, lp, blkmem) );
    2067 }
    2068 else
    2069 {
    2070 SCIPsetDebugMsg(set, " -> apply global bound change: <%s> %s %g\n",
    2071 SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", bound);
    2072 SCIP_CALL( SCIPnodeAddBoundchg(tree->path[conflictrow->validdepth], blkmem, set, stat, transprob, origprob, tree,
    2073 reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, bound, boundtype, FALSE) );
    2074 }
    2075
    2076 *success = TRUE;
    2077 SCIP_CALL( updateStatistics(conflict, vars, blkmem, set, stat, conflictrow, conflictrow->validdepth) );
    2078 }
    2079 /* generate the linear constraint */
    2080 else if( !hasRelaxationOnlyVar(set, vars, conflictrow) )
    2081 {
    2082 /* todo use the right insert depth and not valid depth */
    2083 SCIP_CALL( createAndAddConflictCon(conflict, blkmem, set, stat, vars, \
    2084 tree, reopt, lp, cliquetable, conflictrow, conflictrow->insertdepth, success) );
    2085 conflict->nappliedglbresconss++;
    2086 SCIPsetDebugMsgPrint(set, " \t -> conflict row added (cdpt:%d, fdpt:%d, insert:%d, valid:%d, conf: %d, reprop: %d, len:%d):\n",
    2088 conflictrow->insertdepth, conflictrow->validdepth, conflictrow->conflictdepth,
    2089 conflictrow->repropdepth, conflictrow->nnz);
    2090 }
    2091 else
    2092 {
    2093 SCIPsetDebugMsgPrint(set, " \t -> conflict row has relaxation only variable \n");
    2094 return SCIP_OKAY;
    2095 }
    2096
    2097 return SCIP_OKAY;
    2098}/*lint !e715*/
    2099
    2100/** adds given data as row to the generalized resolution row */
    2101static
    2103 SCIP_CONFLICTROW* resolutionrow, /**< generalized resolution row */
    2104 BMS_BLKMEM* blkmem, /**< block memory */
    2105 SCIP_Real* vals, /**< variable coefficients */
    2106 int* inds, /**< variable array */
    2107 int nnz, /**< size of variable and coefficient array */
    2108 SCIP_Real lhs, /**< left-hand side of conflict row */
    2109 SCIP_Bool reverse /**< reverse coefficients */
    2110 )
    2111{
    2112 int i;
    2113 int idx;
    2114
    2115 assert(resolutionrow != NULL);
    2116 assert(resolutionrow->vals != NULL);
    2117 assert(blkmem != NULL);
    2118
    2119 if( resolutionrow->size == 0 )
    2120 {
    2121 assert(resolutionrow->inds == NULL);
    2122
    2123 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &resolutionrow->inds, nnz) );
    2124 resolutionrow->size = nnz;
    2125 }
    2126 else
    2127 {
    2128 assert(resolutionrow->vals != NULL);
    2129 assert(resolutionrow->inds != NULL);
    2130
    2131 if( resolutionrow->size < nnz )
    2132 {
    2133 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &resolutionrow->inds, resolutionrow->size, nnz) );
    2134 resolutionrow->size = nnz;
    2135 }
    2136 }
    2137
    2138 if( reverse )
    2139 {
    2140 for( i = 0; i < nnz; i++ )
    2141 {
    2142 idx = inds[i];
    2143 resolutionrow->vals[idx] = -vals[i];
    2144 resolutionrow->inds[i] = inds[i];
    2145 }
    2146 }
    2147 else
    2148 {
    2149 for( i = 0; i < nnz; i++ )
    2150 {
    2151 idx = inds[i];
    2152 resolutionrow->vals[idx] = vals[i];
    2153 resolutionrow->inds[i] = inds[i];
    2154 }
    2155 }
    2156
    2157 resolutionrow->lhs = lhs;
    2158 resolutionrow->nnz = nnz;
    2159
    2160 return SCIP_OKAY;
    2161}
    2162
    2163/** compute scale for the reason constraint such that the resolving variable cancels out */
    2164static
    2166 SCIP_SET* set, /**< global SCIP settings */
    2167 SCIP_CONFLICTROW* conflictrow, /**< conflict row */
    2168 SCIP_CONFLICTROW* reasonrow, /**< reason row */
    2169 int residx /**< index of variable to resolve */
    2170 )
    2171{
    2172 SCIP_Real coefconf;
    2173 SCIP_Real coefreas;
    2174 SCIP_Real scale;
    2175
    2176 coefconf = conflictrow->vals[residx];
    2177 coefreas = reasonrow->vals[residx];
    2178
    2179 assert(!SCIPsetIsZero(set, coefreas) && !SCIPsetIsZero(set, coefconf));
    2180 assert(coefconf * coefreas < 0);
    2181
    2182 scale = REALABS( coefconf / coefreas );
    2183 return scale;
    2184}
    2185
    2186/** compute the resolved conflict row resolvedrow = row1 + scale * row2 */
    2187static
    2189 SCIP_SET* set, /**< global SCIP settings */
    2190 SCIP_CONFLICT* conflict, /**< conflict analysis data */
    2191 SCIP_CONFLICTROW* row1, /**< conflict row */
    2192 SCIP_CONFLICTROW* row2, /**< reason conflict row */
    2193 SCIP_CONFLICTROW* resolvedrow, /**< resolved conflict row */
    2194 BMS_BLKMEM* blkmem, /**< block memory */
    2195 int residx, /**< index of variable to resolve */
    2196 SCIP_Bool* success /**< apply resolution */
    2197 )
    2198{
    2199 int i;
    2200 SCIP_Real scale;
    2201 SCIP_Real largestcoef;
    2202 SCIP_Real smallestcoef;
    2203
    2204 int newsize;
    2205 int newnnz;
    2206
    2207 SCIPsetDebugMsgPrint(set, "Nonzeros in first row: %d, slack: %f \n", row1->nnz, row1->slack);
    2208 SCIPsetDebugMsgPrint(set, "Nonzeros in second row: %d, slack: %f \n", row2->nnz, row2->slack);
    2209
    2210 *success = FALSE;
    2211
    2212 scale = computeScaleReason(set, row1, row2, residx);
    2213
    2214 if( SCIPsetIsGE(set, scale, set->conf_maxcoefquot) )
    2215 {
    2216 SCIPsetDebugMsgPrint(set, "Scale %f exceeds max allowed scale %f \n", scale, set->conf_maxcoefquot);
    2217 conflict->nreslargecoefs++;
    2218 return SCIP_OKAY;
    2219 }
    2220
    2221 SCIP_CALL( conflictRowReplace(resolvedrow, blkmem, row1) );
    2222
    2223 newsize = resolvedrow->nnz + row2->nnz;
    2224 if( resolvedrow->size < newsize )
    2225 {
    2226 assert(resolvedrow->vals != NULL);
    2227 assert(resolvedrow->inds != NULL);
    2228
    2229 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &resolvedrow->inds, resolvedrow->size, newsize ) );
    2230 resolvedrow->size = newsize;
    2231 }
    2232
    2233 /* add the reason conflict row to the resolved conflict row */
    2234 linearCombRows(set, resolvedrow, row2, scale);
    2235
    2236 newnnz = resolvedrow->nnz;
    2237
    2238 largestcoef = -SCIPsetInfinity(set);
    2239 smallestcoef = SCIPsetInfinity(set);
    2240 /* remove coefficients that are almost zero (1e-09 tolerance), loop backwards */
    2241 for( i = newnnz - 1; i >= 0 ; i-- )
    2242 {
    2243 int idx;
    2244 idx = resolvedrow->inds[i];
    2245 assert(!SCIPsetIsZero(set, resolvedrow->vals[idx]));
    2246
    2247 smallestcoef = MIN(smallestcoef, resolvedrow->vals[idx]);
    2248 largestcoef = MAX(largestcoef, resolvedrow->vals[idx]);
    2249 }
    2250
    2251 SCIPsetDebugMsgPrint(set, "Nonzeros in resolved row: %d \n", resolvedrow->nnz);
    2252
    2253 /* check if the quotient of coefficients in the resolvent exceeds the max allowed quotient */
    2254 resolvedrow->coefquotient = (resolvedrow->nnz > 0) ? fabs(largestcoef / smallestcoef) : 0.0;
    2255 if( SCIPsetIsGT(set, resolvedrow->coefquotient, set->conf_maxcoefquot) )
    2256 {
    2257 conflict->nreslargecoefs++;
    2258 SCIPsetDebugMsgPrint(set, "Quotient %f exceeds max allowed quotient", (resolvedrow->nnz > 0) ? fabs(largestcoef / smallestcoef) : 0.0);
    2259 return SCIP_OKAY;
    2260 }
    2261
    2262 *success = TRUE;
    2263
    2264 return SCIP_OKAY;
    2265}
    2266
    2267
    2268/** reduce the reason constraint */
    2269static
    2271 SCIP_SET* set, /**< global SCIP settings */
    2272 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
    2273 SCIP_VAR** vars, /**< array of variables */
    2274 int nvars, /**< number of variables */
    2275 SCIP_CONFLICTROW* rowtoreduce, /**< the row to reduce */
    2276 SCIP_BDCHGINFO* currbdchginfo, /**< current bound change to resolve */
    2277 int residx, /**< index of variable to resolve */
    2278 SCIP_Real* fixbounds, /**< dense array of fixed bounds */
    2279 int* fixsides /**< dense array of variables fixed to a bound */
    2280 )
    2281{
    2282 SCIP_Real coefinrow;
    2283 SCIP_BDCHGIDX* currbdchgidx;
    2284
    2285 currbdchgidx = SCIPbdchginfoGetIdx(currbdchginfo);
    2286
    2287 coefinrow = fabs(rowtoreduce->vals[residx]);
    2288
    2289 if( isBinaryConflictRow(set, vars, rowtoreduce) )
    2290 SCIP_CALL( ComplementedMirLhs(set, vars, rowtoreduce, fixsides, currbdchgidx, residx, coefinrow) );
    2291 else
    2292 SCIP_CALL( MirReduction(set, blkmem, vars, nvars, rowtoreduce, currbdchginfo, residx, coefinrow) );
    2293
    2294 SCIP_CALL( computeSlack(set, vars, rowtoreduce, currbdchginfo, fixbounds, fixsides) );
    2295
    2296 /* check that the variable we are resolving is still in the reason row */
    2297 assert(!SCIPsetIsZero(set, rowtoreduce->vals[residx]));
    2298
    2299 SCIPdebug(printConflictRow(rowtoreduce, set, vars, REDUCED_REASON_ROWTYPE));
    2300
    2301 return SCIP_OKAY;
    2302}
    2303
    2304/** reason row from an LP row */
    2305static
    2307 SCIP_SET* set, /**< global SCIP settings */
    2308 BMS_BLKMEM* blkmem, /**< block memory */
    2309 SCIP_ROW* row, /**< row to add */
    2310 SCIP_CONFLICTROW* reasonrow, /**< reason row */
    2311 SCIP_BDCHGINFO* bdchginfo /**< bound change to resolve */
    2312 )
    2313{
    2314 SCIP_COL** cols;
    2315 SCIP_VAR* vartoresolve;
    2316 SCIP_Real* vals;
    2317 int* inds;
    2318 SCIP_Real lhs;
    2319 SCIP_Real rowlhs;
    2320 SCIP_Real rowrhs;
    2321 int nnz;
    2322 int varidx;
    2323 int i;
    2324 SCIP_Bool changesign;
    2325 SCIP_Bool isincon;
    2326
    2327 assert(reasonrow != NULL);
    2328 assert(set != NULL);
    2329
    2330 nnz = SCIProwGetNNonz(row);
    2331 assert(nnz > 0);
    2332
    2333 rowlhs = SCIProwGetLhs(row) - SCIProwGetConstant(row);
    2334 rowrhs = SCIProwGetRhs(row) - SCIProwGetConstant(row);
    2335
    2336 vartoresolve = SCIPbdchginfoGetVar(bdchginfo);
    2337 varidx = SCIPvarGetProbindex(vartoresolve);
    2338
    2339 vals = SCIProwGetVals(row);
    2340 cols = SCIProwGetCols(row);
    2341
    2342 SCIP_CALL( SCIPsetAllocBufferArray(set, &inds, nnz ) );
    2343
    2344 isincon = FALSE;
    2345 changesign = FALSE;
    2346 for( i = 0; i < nnz; i++ )
    2347 {
    2348 SCIP_VAR* var;
    2349
    2350 var = SCIPcolGetVar(cols[i]);
    2351 inds[i] = SCIPvarGetProbindex(var);
    2352 if( inds[i] == varidx )
    2353 {
    2354 assert(var == vartoresolve);
    2355 if( (SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER && vals[i] < 0) ||
    2356 (SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_UPPER && vals[i] > 0) )
    2357 {
    2358 if( strcmp(SCIPconshdlrGetName(bdchginfo->inferencedata.reason.cons->conshdlr), "knapsack") != 0 )
    2359 assert(!SCIPsetIsInfinity(set, rowrhs));
    2360 changesign = TRUE;
    2361 }
    2362 else if( (SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER && vals[i] > 0 ) ||
    2363 (SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_UPPER && vals[i] < 0))
    2364 {
    2365 if( strcmp(SCIPconshdlrGetName(bdchginfo->inferencedata.reason.cons->conshdlr), "knapsack") != 0 )
    2366 assert(!SCIPsetIsInfinity(set, -rowlhs));
    2367 changesign = FALSE;
    2368 }
    2369 else
    2370 {
    2371 SCIPABORT();
    2372 }
    2373 isincon = TRUE;
    2374 }
    2375 }
    2376 assert(isincon);
    2377 SCIP_UNUSED(isincon);
    2378
    2379 if( changesign )
    2380 lhs = -rowrhs;
    2381 else
    2382 lhs = rowlhs;
    2383
    2384 assert(inds != NULL);
    2385 assert(vals != NULL);
    2386
    2387 SCIP_CALL( conflictRowAddSemiSparseData(reasonrow, blkmem, vals, inds, nnz, lhs, changesign) );
    2388
    2390
    2391 return SCIP_OKAY;
    2392}
    2393
    2394/** add a row to the conflict row */
    2395static
    2397 SCIP_SET* set, /**< global SCIP settings */
    2398 BMS_BLKMEM* blkmem, /**< block memory */
    2399 SCIP_ROW* row, /**< row to add */
    2400 SCIP_CONFLICTROW* conflictrow, /**< conflict row */
    2401 SCIP_BDCHGINFO* bdchginfo /**< bound change to resolve */
    2402 )
    2403{
    2404 SCIP_COL** cols;
    2405 SCIP_VAR* var;
    2406 SCIP_Real* vals;
    2407 int* inds;
    2408 SCIP_Real lhs;
    2409 SCIP_Real rowlhs;
    2410 SCIP_Real rowrhs;
    2411 int nnz;
    2412 int varidx;
    2413 int i;
    2414 SCIP_Bool changesign;
    2415 SCIP_Bool isincon;
    2416 assert(conflictrow != NULL);
    2417 assert(set != NULL);
    2418
    2419 nnz = SCIProwGetNNonz(row);
    2420 assert(nnz > 0);
    2421
    2422 rowlhs = SCIProwGetLhs(row) - SCIProwGetConstant(row);
    2423 rowrhs = SCIProwGetRhs(row) - SCIProwGetConstant(row);
    2424
    2425 var = SCIPbdchginfoGetVar(bdchginfo);
    2426 varidx = SCIPvarGetProbindex(var);
    2427
    2428 vals = SCIProwGetVals(row);
    2429 cols = SCIProwGetCols(row);
    2430
    2431 SCIP_CALL( SCIPsetAllocBufferArray(set, &inds, nnz ) );
    2432
    2433 isincon = FALSE;
    2434 changesign = FALSE;
    2435 for( i = 0; i < nnz; i++ )
    2436 {
    2437 var = SCIPcolGetVar(cols[i]);
    2438 inds[i] = SCIPvarGetProbindex(var);
    2439 if( inds[i] == varidx )
    2440 {
    2441 if( (SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER && vals[i] > 0 ) ||
    2442 (SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_UPPER && vals[i] < 0))
    2443 {
    2444 changesign = TRUE;
    2445 }
    2446 else if( (SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER && vals[i] < 0 ) ||
    2447 (SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_UPPER && vals[i] > 0))
    2448 {
    2449 changesign = FALSE;
    2450 }
    2451 else
    2452 {
    2453 SCIPABORT();
    2454 }
    2455 isincon = TRUE;
    2456 }
    2457 }
    2458
    2459 assert(isincon);
    2460 SCIP_UNUSED(isincon);
    2461
    2462 if( changesign )
    2463 lhs = -rowrhs;
    2464 else
    2465 lhs = rowlhs;
    2466
    2467 assert(inds != NULL);
    2468 assert(vals != NULL);
    2469
    2470 SCIP_CALL( conflictRowAddSemiSparseData(conflictrow, blkmem, vals, inds, nnz, lhs, changesign) );
    2471
    2473
    2474 return SCIP_OKAY;
    2475}
    2476
    2477/** get the reason for the given bound change */
    2478static
    2480 BMS_BLKMEM* blkmem, /**< block memory */
    2481 SCIP_VAR** vars, /**< array of variables */
    2482 SCIP_SET* set, /**< global SCIP settings */
    2483 SCIP_BDCHGINFO* currbdchginfo, /**< bound change to resolve */
    2484 SCIP_CONFLICTROW* reasonrow, /**< reason row for the bound change */
    2485 int residx, /**< index of the bound change to resolve */
    2486 SCIP_Real* fixbounds, /**< dense array of fixed bounds */
    2487 int* fixsides, /**< dense array of variables fixed to a bound */
    2488 SCIP_Bool* success /**< pointer to store whether we could get a linear reason */
    2489 )
    2490{
    2491 assert(success != NULL);
    2492 assert(reasonrow != NULL);
    2493
    2494 *success = FALSE;
    2495
    2496 if( isResolvableBdchg(currbdchginfo) && SCIPbdchginfoGetChgtype(currbdchginfo) == SCIP_BOUNDCHGTYPE_CONSINFER )
    2497 {
    2498 SCIP_CONS* reasoncon;
    2499 SCIP_ROW* reasonlprow = NULL;
    2500
    2501 reasoncon = SCIPbdchginfoGetInferCons(currbdchginfo);
    2502
    2503 if( !SCIPconsIsGlobal(reasoncon) )
    2504 {
    2505 SCIPsetDebugMsgPrint(set, "Reason constraint is not global \n");
    2506 return SCIP_OKAY;
    2507 }
    2508
    2509 /* get the corresponding reason row */
    2510 SCIP_CALL( SCIPconsCreateRow(set->scip, reasoncon, &reasonlprow) );
    2511
    2512 if( reasonlprow == NULL )
    2513 {
    2514 SCIPsetDebugMsgPrint(set, "Could not create row for reason constraint \n");
    2515 return SCIP_OKAY;
    2516 }
    2517
    2518 /* get the conflict row of the reason row */
    2519 SCIP_CALL( reasonRowFromLpRow(set, blkmem, reasonlprow, reasonrow, currbdchginfo) );
    2520 *success = TRUE;
    2521 /* it may happen that some specialized propagation took place and the real reason is not the constraint
    2522 e.g. negated cliques in cons_knapsack or ranged row propagation in cons_linear. */
    2523
    2524 /* this happens if the reason is a negated clique found in the knapsack constraint handler */
    2525 if( strcmp(SCIPconshdlrGetName(reasoncon->conshdlr), "knapsack") != 0 )
    2526 {
    2527 assert(!SCIPsetIsInfinity(set, -reasonrow->lhs) || !SCIPsetIsInfinity(set, reasonrow->lhs));
    2528 }
    2529 else if( SCIPsetIsInfinity(set, -reasonrow->lhs) || SCIPsetIsInfinity(set, reasonrow->lhs) )
    2530 {
    2531 *success = FALSE;
    2532 return SCIP_OKAY;
    2533 }
    2534
    2535 SCIP_CALL( computeSlack(set, vars, reasonrow, currbdchginfo, fixbounds, fixsides) );
    2536
    2537 /* If the slack is greater than 0, we check that the reason actually propagated the variable we resolve.
    2538 It propagates a variable x_i if (slack - a_i * ( boundusedinslack - oldbound)) < 0 */
    2539 if( SCIPsetIsGT(set, reasonrow->slack, 0.0) )
    2540 {
    2541 SCIP_VAR* var;
    2542 SCIP_BDCHGIDX* currbdchgidx;
    2543 SCIP_Real coef;
    2544 SCIP_Real boundusedinslack;
    2545
    2546 currbdchgidx = SCIPbdchginfoGetIdx(currbdchginfo);
    2547 var = SCIPbdchginfoGetVar(currbdchginfo);
    2548 assert(var != NULL);
    2549 assert(SCIPvarGetProbindex(var) == residx);
    2550
    2551 coef = reasonrow->vals[residx];
    2552 boundusedinslack = coef > 0 ? SCIPgetVarUbAtIndex(set->scip, var, currbdchgidx, TRUE) : SCIPgetVarLbAtIndex(set->scip, var, currbdchgidx, TRUE);
    2553
    2554 if( !SCIPsetIsLT(set, reasonrow->slack - coef * (boundusedinslack - SCIPbdchginfoGetOldbound(currbdchginfo)), 0.0) )
    2555 {
    2556 SCIPsetDebugMsgPrint(set, "Reason row does not propagate because of non-linear propagation \n");
    2557 *success = FALSE;
    2558 return SCIP_OKAY;
    2559 }
    2560 }
    2561 }
    2562 else
    2563 {
    2564 SCIPsetDebugMsgPrint(set, "Could not obtain a reason row \n");
    2565 *success = FALSE;
    2566 }
    2567
    2568 return SCIP_OKAY;
    2569}
    2570
    2571/** get the conflict row for the given bound change from the LP row. */
    2572static
    2574 SCIP_CONFLICT* conflict, /**< conflict analysis data */
    2575 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
    2576 SCIP_SET* set, /**< global SCIP settings */
    2577 SCIP_PROB* prob, /**< problem data */
    2578 SCIP_ROW* initialconflictrow, /**< row of constraint that detected the conflict */
    2579 SCIP_BDCHGINFO* currbdchginfo, /**< bound change to resolve */
    2580 int maxsize, /**< maximal size of conflict rows */
    2581 SCIP_Bool* success /**< pointer to store whether we could get a conflict row */
    2582 )
    2583{
    2584 SCIP_VAR** vars;
    2585 SCIP_CONFLICTROW* conflictrow;
    2586 SCIP_BDCHGIDX* currbdchgidx;
    2587
    2588 vars = prob->vars;
    2589 assert(vars != NULL);
    2590
    2591 conflictrow = conflict->conflictrow;
    2592 currbdchgidx = SCIPbdchginfoGetIdx(currbdchginfo);
    2593 assert(currbdchgidx != NULL);
    2594
    2595 assert(success != NULL);
    2596 *success = FALSE;
    2597 /* first try to create the conflict row from the infeasible LP row */
    2598 if( initialconflictrow != NULL )
    2599 {
    2600 SCIPsetDebugMsgPrint(set, "Initial LP Row: %s \n", SCIProwGetName(initialconflictrow));
    2601 SCIP_CALL( conflictRowFromLpRow(set, blkmem, initialconflictrow, conflictrow, currbdchginfo) );
    2602
    2603 /* if the conflict row is too large, we try to weaken it */
    2604 if( conflictrow->nnz > maxsize )
    2605 {
    2606 assert(conflictrow->nnz == SCIProwGetNNonz(initialconflictrow));
    2607 SCIPsetDebugMsgPrint(set, "Number of nonzeros in conflict is larger than maxsize %d > %d\n", conflictrow->nnz, maxsize);
    2608 SCIPsetDebugMsgPrint(set, "Try to shorten the conflict row by applying weakening \n");
    2609
    2610 weakenConflictRow(conflictrow, set, vars, currbdchgidx, NULL);
    2611
    2612 if( conflictrow->nnz > maxsize )
    2613 {
    2614 SCIPsetDebugMsgPrint(set, "Conflict row is still too large after weakening %d > %d\n", conflictrow->nnz, maxsize);
    2615 conflict->nreslongconfs++;
    2616 return SCIP_OKAY;
    2617 }
    2618 }
    2619
    2620 /* set the slack */
    2621 SCIP_CALL( computeSlack(set, vars, conflictrow, currbdchginfo, NULL, NULL) );
    2622 }
    2623
    2624 /* The conflict row might not be infeasible.
    2625 * This may not be true is if the conflict is found by some non-linear propagation argument:
    2626 * - by a negated clique in the knapsack constraint handler
    2627 * - by propagating a ranged row with a gcd argument
    2628 */
    2629 if( initialconflictrow == NULL || SCIPsetIsGE(set, conflictrow->slack, 0.0) )
    2630 {
    2631 SCIPsetDebugMsgPrint(set, "Initial conflict could not be retrieved \n");
    2632 return SCIP_OKAY;
    2633 }
    2634
    2635 /* check once more if the initial conflict is too long */
    2636 if( conflictrow->nnz > maxsize )
    2637 {
    2638 conflict->nreslongconfs++;
    2639 return SCIP_OKAY;
    2640 }
    2641
    2642 assert(SCIPsetIsLT(set, conflictrow->slack, 0.0));
    2643 *success = TRUE;
    2644
    2645 return SCIP_OKAY;
    2646}
    2647
    2648/** execute resolution; reduce reason if necessary */
    2649static
    2651 SCIP_CONFLICT * conflict, /**< conflict analysis data */
    2652 SCIP_SET* set, /**< global SCIP settings */
    2653 SCIP_VAR** vars, /**< array of variables */
    2654 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
    2655 SCIP_BDCHGINFO* currbdchginfo, /**< current bound change to resolve */
    2656 int residx, /**< index of variable to resolve */
    2657 int maxsize, /**< maximal size of conflict rows */
    2658 SCIP_Real* fixbounds, /**< dense array of fixed bounds */
    2659 int* fixsides, /**< dense array of variables fixed to a bound */
    2660 SCIP_Bool* successresolution /**< pointer to store whether the resolution was successful */
    2661 )
    2662{
    2663 SCIP_CONFLICTROW* conflictrow;
    2664 SCIP_CONFLICTROW* reasonrow;
    2665 SCIP_CONFLICTROW* reducedreasonrow;
    2666 SCIP_CONFLICTROW* resolvedconflictrow;
    2667
    2668 int nvars;
    2669
    2670 assert(conflict != NULL);
    2671
    2672 conflictrow = conflict->conflictrow;
    2673 reasonrow = conflict->reasonrow;
    2674 reducedreasonrow = conflict->reducedreasonrow;
    2675 resolvedconflictrow = conflict->resolvedconflictrow;
    2676
    2677 *successresolution = FALSE;
    2678
    2679 nvars = SCIPgetNVars(set->scip);
    2680 assert(!SCIPsetIsZero(set, reasonrow->vals[residx]));
    2681
    2682 /* try to resolve without reducing the reason row */
    2683 SCIPsetDebugMsgPrint(set, "Resolve %s without reducing the reason row \n", SCIPvarGetName(vars[residx]));
    2684 SCIP_CALL( rescaleAndResolve(set, conflict, conflictrow, reasonrow, resolvedconflictrow, blkmem,
    2685 residx, successresolution) );
    2686
    2687 if( !(*successresolution) )
    2688 return SCIP_OKAY;
    2689
    2690 SCIP_CALL( computeSlack(set, vars, resolvedconflictrow, currbdchginfo, fixbounds, fixsides) );
    2691
    2692 /* return if the reduction is off */
    2693 if( set->conf_reduction == 'o' )
    2694 return SCIP_OKAY;
    2695
    2696 /* if the resolvent is not infeasible under the local domain, try to reduce the reason row */
    2697 if( SCIPsetIsGE(set, resolvedconflictrow->slack, 0.0) )
    2698 {
    2699 /* copy the original reason here */
    2700 SCIP_CALL( conflictRowReplace(reducedreasonrow, blkmem, reasonrow) );
    2701
    2702 /* apply reduction to the reason row */
    2703 SCIP_CALL( reduceReason(set, blkmem, vars, nvars, reducedreasonrow, currbdchginfo, residx, fixbounds, fixsides) );
    2704
    2705 /* after reduction resolve again */
    2706 SCIPsetDebugMsgPrint(set, "Resolve %s after reducing the reason row \n", SCIPvarGetName(vars[residx]));
    2707 SCIP_CALL( rescaleAndResolve(set, conflict, conflictrow, reducedreasonrow, resolvedconflictrow, blkmem,
    2708 residx, successresolution) );
    2709
    2710 if( !(*successresolution) )
    2711 return SCIP_OKAY;
    2712
    2713 SCIP_CALL( computeSlack(set, vars, resolvedconflictrow, currbdchginfo, fixbounds, fixsides) );
    2714
    2715 /* mixed binary case reduction */
    2716 if( set->conf_mbreduction && SCIPsetIsGE(set, resolvedconflictrow->slack, 0.0) )
    2717 {
    2718 SCIP_BDCHGINFO* continuousbdchginfo;
    2719 SCIP_Bool successgetreason;
    2720 SCIP_Real coefresidx;
    2721
    2722 /* now both the reducedreasonrow and reasonrow are the rows before the reduction */
    2723 SCIP_CALL( conflictRowReplace(reducedreasonrow, blkmem, reasonrow) );
    2724
    2725 coefresidx = reducedreasonrow->vals[residx];
    2726
    2727 /* In the following the reducedreasonrow is the aggregation of the different reasonrows of continuous bound changes */
    2728 SCIP_CALL( slackReducingContinuousBdchgQueue(conflict, vars, reducedreasonrow, SCIPbdchginfoGetIdx(currbdchginfo)) );
    2729
    2730 if( SCIPpqueueNElems(conflict->continuousbdchgqueue) > 0 )
    2731 {
    2732 SCIPsetDebugMsgPrint(set, "Slack-reducing continuous variables in the reason row \n");
    2733 SCIPdebug(printConflictRow(reducedreasonrow, set, vars, REASON_ROWTYPE));
    2734 }
    2735 else
    2736 return SCIP_OKAY;
    2737
    2738 int nresconts = 0;
    2739
    2740 while( SCIPpqueueNElems(conflict->continuousbdchgqueue) > 0 )
    2741 {
    2742 nresconts++;
    2743 if( nresconts > maxsize / 2 || reducedreasonrow->nnz > maxsize )
    2744 {
    2745 (*successresolution) = FALSE;
    2746 conflict->nreslongconfs++;
    2747 return SCIP_OKAY;
    2748 }
    2749 SCIPdebug(printAllBoundChanges(conflict, set, TRUE));
    2750 continuousbdchginfo = (SCIP_BDCHGINFO*)(SCIPpqueueRemove(conflict->continuousbdchgqueue));
    2751 assert(continuousbdchginfo != NULL);
    2752
    2753 int varidx = SCIPvarGetProbindex(SCIPbdchginfoGetVar(continuousbdchginfo));
    2754
    2755 /* get reason row of the latest bdchginfo */
    2756 conflictRowClear(blkmem, reasonrow, nvars);
    2757 SCIP_CALL( getReasonRow(blkmem, vars, set, continuousbdchginfo, reasonrow, varidx, fixbounds, fixsides,
    2758 &successgetreason) );
    2759 if( !successgetreason )
    2760 {
    2761 (*successresolution) = FALSE;
    2762 return SCIP_OKAY;
    2763 }
    2764
    2765 SCIPdebug(printConflictRow(reasonrow, set, vars, CONTINUOUS_REASON_ROWTYPE));
    2766
    2767 SCIPsetDebugMsgPrint(set, "Resolve slack-reducing continuous variable %s \n", SCIPvarGetName(vars[varidx]));
    2768
    2769 /* resolve the continuous variable */
    2770 SCIP_CALL( rescaleAndResolve(set, conflict, reducedreasonrow, reasonrow, resolvedconflictrow, blkmem,
    2771 varidx, successresolution) );
    2772
    2773 if( !(*successresolution) )
    2774 return SCIP_OKAY;
    2775
    2776 /* if the coefficient of the variable we are resolving changed sign, then we have a new conflict constraint */
    2777 if( SCIPsetIsLE(set, coefresidx * resolvedconflictrow->vals[residx], 0.0) )
    2778 {
    2779#ifndef SCIP_DEBUG
    2780 SCIPsetDebugMsgPrint(set, "The sign of the coefficient of the variable we are resolving changed \n");
    2781 SCIP_CALL( computeSlack(set, vars, resolvedconflictrow, currbdchginfo, fixbounds, fixsides) );
    2782 assert(SCIPsetIsLT(set, resolvedconflictrow->slack, 0.0) || !isBinaryConflictRow(set, vars, reducedreasonrow));
    2783#endif
    2784 return SCIP_OKAY;
    2785 }
    2786
    2787 SCIP_CALL( conflictRowReplace(reducedreasonrow, blkmem, resolvedconflictrow) );
    2788
    2789 SCIPdebug(printConflictRow(reducedreasonrow, set, vars, REDUCED_REASON_ROWTYPE));
    2790 SCIP_CALL( slackReducingContinuousBdchgQueue(conflict, vars, reducedreasonrow, SCIPbdchginfoGetIdx(continuousbdchginfo)) );
    2791 }
    2792
    2793 /* after the loop we can weaken all continuous variables with their global bounds */
    2794 SCIP_CALL( weakenContinuousVarsConflictRow(reducedreasonrow, set, vars, residx) );
    2795
    2796 /* after resolving the continuous variables we resolve once more if the constraint is binary */
    2797 if( nresconts > 0 )
    2798 {
    2799 /* apply reduction to the reason row */
    2800 SCIP_CALL( reduceReason(set, blkmem, vars, nvars, reducedreasonrow, currbdchginfo, residx, fixbounds, fixsides) );
    2801
    2802 SCIPsetDebugMsgPrint(set, "Resolve %s after reducing the reason row \n", SCIPvarGetName(vars[residx]));
    2803 /* after all reductions resolve one final time */
    2804 SCIP_CALL( rescaleAndResolve(set, conflict, conflictrow, reducedreasonrow, resolvedconflictrow, blkmem,
    2805 residx, successresolution) );
    2806
    2807 SCIP_CALL( computeSlack(set, vars, resolvedconflictrow, currbdchginfo, fixbounds, fixsides) );
    2808 }
    2809 }
    2810 }
    2811
    2812 return SCIP_OKAY;
    2813}
    2814
    2815/** If a bound change cannot be resolved, it is treated as a branching decision.
    2816 * Subsequent bound changes for that variable are ignored by recording the variable's
    2817 * index in fixsides and its bound type in fixbounds (1 for upper, -1 for lower).
    2818 */
    2819static
    2821 SCIP_CONFLICT* conflict, /**< conflict analysis data */
    2822 SCIP_SET* set, /**< global SCIP settings */
    2823 SCIP_VAR** vars, /**< array of variables */
    2824 SCIP_BDCHGINFO** currbdchginfo, /**< pointer to current bound change to resolve */
    2825 int* currbdchgdepth, /**< pointer to store the depth of the bound change */
    2826 int nressteps, /**< number of bound changes that have been resolved so far */
    2827 SCIP_Real* fixbounds, /**< dense array of fixed bounds */
    2828 int* fixsides, /**< dense array of variables fixed to a bound */
    2829 SCIP_Bool* success /**< pointer to store whether the bound change was ignored */
    2830 )
    2831{
    2832 SCIP_VAR* var;
    2833 int varidx;
    2834 SCIP_BOUNDTYPE boundtype;
    2835 SCIP_BOUNDCHGTYPE bdchgtype;
    2836
    2837 assert(conflict != NULL);
    2838 assert(set != NULL);
    2839 assert(vars != NULL);
    2840 assert(*currbdchginfo != NULL);
    2841 assert(currbdchgdepth != NULL);
    2842 assert(fixbounds != NULL);
    2843 assert(fixsides != NULL);
    2844
    2845 *success = FALSE;
    2846
    2847 /* If the bound change is due to constraint inference, ensure it comes from a global constraint */
    2849 {
    2850 SCIP_CONS* reasoncon = SCIPbdchginfoGetInferCons(*currbdchginfo);
    2851 if( !SCIPconsIsGlobal(reasoncon) )
    2852 return SCIP_OKAY;
    2853 }
    2854
    2855 if( !existsResolvablebdchginfo(conflict) )
    2856 return SCIP_OKAY;
    2857
    2858 var = SCIPbdchginfoGetVar(*currbdchginfo);
    2859 varidx = SCIPvarGetProbindex(var);
    2860
    2861 /* If a bound for this variable has already been ignored, abort */
    2862 if( fixsides[varidx] != 0 )
    2863 return SCIP_OKAY;
    2864
    2865 boundtype = SCIPbdchginfoGetBoundtype(*currbdchginfo);
    2866 bdchgtype = SCIPbdchginfoGetChgtype(*currbdchginfo);
    2867
    2868 /* Record the ignored bound change: 1 for upper, -1 for lower */
    2869 fixsides[varidx] = (boundtype == SCIP_BOUNDTYPE_UPPER) ? 1 : -1;
    2870 fixbounds[varidx] = SCIPbdchginfoGetNewbound(*currbdchginfo);
    2871
    2872 /* Reset conflict bounds to allow weaker bounds to be added later */
    2873 if( boundtype == SCIP_BOUNDTYPE_LOWER )
    2874 conflict->conflictvarslbs[varidx] = SCIP_REAL_MIN;
    2875 else
    2876 conflict->conflictvarsubs[varidx] = SCIP_REAL_MAX;
    2877
    2878 SCIPsetDebugMsgPrint(set, "ignoring the latest bound change of variable %s to %f\n",
    2879 SCIPvarGetName(var), SCIPbdchginfoGetNewbound(*currbdchginfo));
    2880
    2881 if( nressteps == 0 )
    2882 SCIP_CALL( updateBdchgQueue(set, vars, conflict->conflictrow, SCIPbdchginfoGetIdx(*currbdchginfo)) );
    2883
    2884 *currbdchginfo = conflictFirstCand(set, conflict, FALSE);
    2885 assert(*currbdchginfo != NULL);
    2886
    2887 /* Extract the latest bound change from the candidate queue */
    2888 *currbdchginfo = conflictRemoveCand(conflict, FALSE);
    2889
    2890 /* If no resolution step has been applied and the bound change is a branching decision,
    2891 * update the last bound change depth.
    2892 */
    2893 if( nressteps == 0 && bdchgtype == SCIP_BOUNDCHGTYPE_BRANCHING )
    2894 *currbdchgdepth = SCIPbdchginfoGetDepth(*currbdchginfo);
    2895 else if( !set->conf_fixandcontinue )
    2896 return SCIP_OKAY;
    2897
    2898#ifndef SCIP_DEBUG
    2899 SCIP_CALL( computeSlack(set, vars, conflict->conflictrow, *currbdchginfo, fixbounds, fixsides) );
    2900 assert(SCIPsetIsLT(set, conflict->conflictrow->slack, 0.0));
    2901#endif
    2902
    2903 *success = TRUE;
    2904 return SCIP_OKAY;
    2905}
    2906
    2907/** add the conflict rows to the problem */
    2908static
    2910 SCIP_CONFLICT* conflict, /**< conflict analysis data */
    2911 BMS_BLKMEM* blkmem, /**< block memory */
    2912 SCIP_SET* set, /**< global SCIP settings */
    2913 SCIP_STAT* stat, /**< dynamic problem statistics */
    2914 SCIP_PROB* transprob, /**< transformed problem */
    2915 SCIP_PROB* origprob, /**< original problem */
    2916 SCIP_TREE* tree, /**< branch and bound tree */
    2917 SCIP_REOPT* reopt, /**< reoptimization data structure */
    2918 SCIP_LP* lp, /**< current LP data */
    2919 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    2920 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    2921 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    2922 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
    2923 int nconstoadd, /**< number of conflict constraints to add */
    2924 int* nconss, /**< pointer to store the number of generated conflict constraints */
    2925 int* nconfvars /**< pointer to store the number of variables in generated conflict constraints */
    2926 )
    2927{
    2928 int i;
    2929
    2930 for( i = 0; i < nconstoadd; i++ )
    2931 {
    2932 SCIP_CONFLICTROW* conflictrowtoadd;
    2933
    2934 conflictrowtoadd = conflict->conflictrows[i];
    2935 assert(SCIPsetIsLT(set, conflictrowtoadd->slack, 0.0));
    2936
    2937 if( SCIPsetIsLT(set, conflictrowtoadd->coefquotient, set->conf_maxcoefquot) )
    2938 {
    2939 SCIP_Bool success;
    2940
    2941 SCIP_CALL( SCIPconflictAddConflictCon(conflict, blkmem, set, stat, transprob, origprob, tree, reopt,
    2942 lp, branchcand, eventqueue, eventfilter, cliquetable, conflictrowtoadd, &success) );
    2943 if( success )
    2944 {
    2945 (*nconss)++;
    2946 (*nconfvars) += conflictrowtoadd->nnz;
    2947 }
    2948 }
    2949 }
    2950 return SCIP_OKAY;
    2951}
    2952
    2953/** Analyzes conflicting bound changes added via SCIPconflictAddBound().
    2954 * This function performs generalized resolution conflict analysis by iteratively aggregating the
    2955 * infeasible conflict row (conflictrow) with the reason row (reasonrow) that propagated the bound change.
    2956 * In each iteration, the coefficient of the resolving variable is cancelled. If the aggregation does not
    2957 * yield an infeasible row, MIR reduction is applied to the reason row and the aggregation is retried,
    2958 * continuing until a first unique implication point (FUIP) is reached. On success, a linear conflict
    2959 * constraint that explains the infeasibility is added to the problem.
    2960 */
    2962 SCIP_CONFLICT* conflict, /**< conflict analysis data */
    2963 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
    2964 SCIP_SET* set, /**< global SCIP settings */
    2965 SCIP_STAT* stat, /**< problem statistics */
    2966 SCIP_PROB* transprob, /**< transformed problem */
    2967 SCIP_PROB* origprob, /**< original problem */
    2968 SCIP_TREE* tree, /**< branch and bound tree */
    2969 SCIP_REOPT* reopt, /**< reoptimization data structure */
    2970 SCIP_LP* lp, /**< LP data */
    2971 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    2972 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    2973 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    2974 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
    2975 SCIP_ROW* initialconflictrow, /**< row of constraint that detected the conflict */
    2976 int validdepth, /**< minimal depth level at which the initial conflict set is valid */
    2977 int* nconss, /**< pointer to store the number of generated conflict constraints */
    2978 int* nconfvars /**< pointer to store the number of variables in generated conflict constraints */
    2979 )
    2980{
    2981 SCIP_CONFLICTROW *conflictrow;
    2982 SCIP_CONFLICTROW *resolvedconflictrow;
    2983
    2984 SCIP_BDCHGINFO* bdchginfo;
    2985 SCIP_BDCHGINFO* nextbdchginfo;
    2986 SCIP_BDCHGIDX* bdchgidx;
    2987
    2988 int bdchgdepth;
    2989 int lastuipdepth;
    2990 int maxsize;
    2991 int nchgcoefs;
    2992 int nressteps;
    2993 int nfuips;
    2994 SCIP_Real* fixbounds;
    2995 int* fixsides;
    2996 SCIP_Bool successresolution;
    2997 SCIP_Bool successgetconflict;
    2998 SCIP_Bool successgetreason;
    2999 int nvars;
    3000 int i;
    3001
    3002 SCIP_VAR** vars;
    3003 SCIP_VAR* vartoresolve;
    3004 int residx;
    3005
    3006 assert(conflict != NULL);
    3007 assert(set != NULL);
    3008 assert(stat != NULL);
    3009 assert(0 <= validdepth && validdepth <= SCIPtreeGetCurrentDepth(tree));
    3011 assert(nconss != NULL);
    3012 assert(nconfvars != NULL);
    3013 assert(conflict->nconflictrows == 0);
    3014
    3015 assert(SCIPtreeGetCurrentDepth(tree) == tree->pathlen-1);
    3016 assert(SCIPtreeGetFocusDepth(tree) <= SCIPtreeGetCurrentDepth(tree));
    3017
    3018 lastuipdepth = -1;
    3019
    3020 *nconss = 0;
    3021 *nconfvars = 0;
    3022
    3023 /* todo implement local conflict analysis */
    3024 if( validdepth > 0)
    3025 return SCIP_OKAY;
    3026
    3027 vars = SCIPprobGetVars(transprob);
    3028 nvars = transprob->nvars;
    3029
    3030 conflictrow = conflict->conflictrow;
    3031 resolvedconflictrow = conflict->resolvedconflictrow;
    3032
    3033 /* clear the conflict, reason, resolved conflict rows */
    3034 conflictRowClear(blkmem, conflict->conflictrow, nvars);
    3035 conflictRowClear(blkmem, conflict->resolvedconflictrow, nvars);
    3036 conflictRowClear(blkmem, conflict->reasonrow, nvars);
    3037 conflictRowClear(blkmem, conflict->reducedreasonrow, nvars);
    3038
    3039 /* last bound change that led to infeasibility */
    3040 bdchginfo = conflictFirstCand(set, conflict, TRUE);
    3041
    3042 /* if no bound change exists or none of them was infered by a resolvable
    3043 constraint then we terminate */
    3044 if( bdchginfo == NULL || !existsResolvablebdchginfo(conflict) )
    3045 {
    3046#ifdef SCIP_DEBUG
    3047 /* if at least one bound change is in the queue, print them all */
    3048 if( bdchginfo != NULL )
    3049 printAllBoundChanges(conflict, set, FALSE);
    3050#endif
    3051 SCIPsetDebugMsgPrint(set, "Conflict analysis not applicable since no resolvable bounds exist \n");
    3052 return SCIP_OKAY;
    3053 }
    3054
    3055 /* remove the last bound change */
    3056 bdchginfo = conflictRemoveCand(conflict, TRUE);
    3057 bdchgidx = SCIPbdchginfoGetIdx(bdchginfo);
    3058 bdchgdepth = SCIPbdchginfoGetDepth(bdchginfo);
    3059
    3060 vartoresolve = SCIPbdchginfoGetVar(bdchginfo);
    3061
    3062 /* check if the variable we are resolving is active */
    3063 assert(SCIPvarIsActive(vartoresolve));
    3064
    3065 /* calculate the maximal size of each accepted conflict set */
    3066 maxsize = 2 * conflictCalcResMaxsize(set, transprob);
    3067
    3068 /* sets the initial conflictrow */
    3069 SCIP_CALL( getConflictRow(conflict, blkmem, set, transprob, initialconflictrow, bdchginfo, maxsize, &successgetconflict) );
    3070 /* if we could not get the conflict row, then we abort */
    3071 if( !successgetconflict )
    3072 {
    3073 SCIPsetDebugMsgPrint(set, "Conflict analysis not applicable since no conflict row could be created \n");
    3074 return SCIP_OKAY;
    3075 }
    3076
    3077 /* before we resolve any bound change the resolved conflict row is the same as the conflict row */
    3078 SCIP_CALL( conflictRowReplace(resolvedconflictrow, blkmem, conflictrow) );
    3079
    3080 /* Apply coefficient tightening to the conflict constraint should never hurt */
    3081 SCIP_CALL( tightenCoefs(set, vars, FALSE, conflictrow->vals, conflictrow->inds,
    3082 &conflictrow->nnz, &conflictrow->lhs, &nchgcoefs, NULL) );
    3083
    3084 if( nchgcoefs > 0 )
    3085 {
    3086 /* remove variables with zero coefficients from the conflict row */
    3087 conflictRowRemoveZeroVars(conflictrow, set);
    3088
    3089 SCIP_CALL( computeSlack(set, vars, conflictrow, bdchginfo, NULL, NULL) );
    3090 /* the slack after coefficient tightening must also be negative */
    3091 assert(SCIPsetIsLT(set, conflictrow->slack, 0.0));
    3092 }
    3093
    3094 conflictrow->coefquotient = getQuotLargestSmallestCoef(set, conflictrow->inds, conflictrow->vals, conflictrow->nnz);
    3095
    3096 nressteps = 0;
    3097 nfuips = 0;
    3098
    3099 /* initialize indices and bounds for the unresolvable bound changes */
    3100 SCIP_CALL( SCIPsetAllocBufferArray(set, &fixsides, nvars) );
    3101 SCIP_CALL( SCIPsetAllocBufferArray(set, &fixbounds, nvars) );
    3102
    3103 /* set value in fixsides to 0 to indicate that a variable is not fixed
    3104 * if a variable is set at an upper bound, then the value is 1
    3105 * if a variable is set at a lower bound, then the value is -1
    3106 */
    3107 for( i = 0; i < nvars; ++i )
    3108 fixsides[i] = 0;
    3109
    3110 /* main loop:
    3111 * --------------------------------
    3112 * - we start with the initial conflict row and the first bound change to
    3113 * resolve
    3114 * --------------------------------
    3115 * - Fix & Continue: if we can't explain/resolve the bound change, i.e. the reason
    3116 * is a branching or non-linear then we ignore(fix) it and continue with the
    3117 * next bound change. We have to ignore all other bound changes for
    3118 * this variable (resolve with no-good)
    3119 * - if the bound change is resolvable:
    3120 * - get the reason row for the bound change
    3121 * - if needed apply the MIR reduction to the reason
    3122 * - take the linear combination of the conflict row and the reason row
    3123 * - apply coefficient tightening to the resolved row
    3124 * - if there is no other bound change in the queue from the same depth level
    3125 * then we are at a UIP
    3126 * - keep this constraint and either terminate 1-FUIP resolution or continue
    3127 * with the next bound change
    3128 */
    3129 while( TRUE ) /*lint !e716*/
    3130 {
    3131#ifdef SCIP_DEBUG
    3132 {
    3133 SCIPsetDebugMsgPrint(set, "\nResolution Iteration: %d \n", nressteps);
    3134 SCIPsetDebugMsgPrint(set, "Current bound change already removed from the queue: \n");
    3135 printSingleBoundChange(set, bdchginfo);
    3136 printAllBoundChanges(conflict, set, FALSE);
    3137 }
    3138#endif
    3139
    3140 if( !isResolvableBdchg(bdchginfo) )
    3141 {
    3142 SCIP_Bool successfixing;
    3143
    3144#ifdef SCIP_DEBUG
    3145 printNonResolvableReasonType(set, bdchginfo);
    3146#endif
    3147 SCIP_CALL( markBdchgAsFixed(conflict, set, vars, &bdchginfo, &bdchgdepth, nressteps,
    3148 fixbounds, fixsides, &successfixing) );
    3149 if( !successfixing )
    3150 goto TERMINATE_RESOLUTION_LOOP;
    3151
    3152 assert(bdchginfo != NULL);
    3153
    3154 /* get the current bound change index */
    3155 bdchgidx = SCIPbdchginfoGetIdx(bdchginfo);
    3156
    3157 vartoresolve = SCIPbdchginfoGetVar(bdchginfo);
    3158 /* check if the variable we are resolving is active */
    3159 assert(SCIPvarIsActive(vartoresolve));
    3160 }
    3161
    3162 /* here is the generalized resolution iteration */
    3163 else
    3164 {
    3165 residx = SCIPvarGetProbindex(vartoresolve);
    3166
    3167 conflictRowClear(blkmem, conflict->reasonrow, nvars);
    3168
    3169 /* get reason row of the latest bdchginfo */
    3170 SCIP_CALL( getReasonRow(blkmem, vars, set, bdchginfo, conflict->reasonrow, residx, fixbounds, fixsides,
    3171 &successgetreason) );
    3172 if( !successgetreason )
    3173 {
    3174 SCIPsetDebugMsgPrint(set, "Could not obtain reason row for bound change \n");
    3175 goto TERMINATE_RESOLUTION_LOOP;
    3176 }
    3177
    3178 SCIPdebug(printConflictRow(conflictrow, set, vars, CONFLICT_ROWTYPE));
    3179 SCIPdebug(printConflictRow(conflict->reasonrow, set, vars, REASON_ROWTYPE));
    3180
    3181 successresolution = FALSE;
    3182
    3183 /* call resolution */
    3184 SCIPsetDebugMsgPrint(set, " Applying resolution with resolving variable <%s>\n", SCIPvarGetName(vartoresolve));
    3185 SCIP_CALL( executeResolutionStep(conflict, set, vars, blkmem, bdchginfo, residx, maxsize, fixbounds, fixsides, &successresolution ) );
    3186
    3187 /* todo we can strengthen the conflict row by applying MIR */
    3188 if( successresolution )
    3189 SCIP_CALL( conflictRowReplace(conflictrow, blkmem, resolvedconflictrow) );
    3190 else
    3191 goto TERMINATE_RESOLUTION_LOOP;
    3192
    3193 /* we must reset the conflict lower and upper bound to be able to add weaker bounds later */
    3195 conflict->conflictvarslbs[residx] = SCIP_REAL_MIN;
    3196 else
    3197 conflict->conflictvarsubs[residx] = SCIP_REAL_MAX;
    3198
    3199 if( conflictrow->nnz > maxsize )
    3200 {
    3201 SCIPsetDebugMsgPrint(set, "Number of nonzeros in conflict is larger than maxsize %d > %d\n",
    3202 conflictrow->nnz, maxsize);
    3203 weakenConflictRow(conflictrow, set, vars, bdchgidx, fixsides);
    3204 if( conflictrow->nnz > maxsize )
    3205 {
    3206 conflict->nreslongconfs++;
    3207 goto TERMINATE_RESOLUTION_LOOP;
    3208 }
    3209#ifdef SCIP_DEBUG
    3210 SCIP_Real oldslack;
    3211 oldslack = conflictrow->slack;
    3212 SCIP_CALL( computeSlack(set, vars, conflictrow, bdchginfo, fixbounds, fixsides) );
    3213 assert(SCIPsetIsEQ(set, conflictrow->slack, oldslack));
    3214#endif
    3215 }
    3216
    3217 SCIPsetDebugMsgPrint(set, "Slack of resolved row: %f \n", conflictrow->slack);
    3218
    3219 SCIPdebug(printConflictRow(conflictrow, set, vars, RESOLVED_CONFLICT_ROWTYPE));
    3220
    3221 /* A positive slack means that the conflict row is not infeasible anymore.
    3222 * Unfortunately we cannot guarrante that the slack becomes zero after reducing
    3223 * the reason (even if we have only binary variables).
    3224 * Two issues are non-linear propagations, e.g.
    3225 * - Knapsack constraints that use negated cliques in the propagation
    3226 * - Ranged row propagation (gcd argument)
    3227 */
    3228 if( SCIPsetIsGE(set, conflictrow->slack, 0.0) )
    3229 goto TERMINATE_RESOLUTION_LOOP;
    3230
    3231 nressteps++;
    3232
    3233 /* apply coefficient tightening to the resolved constraint should never hurt */
    3234 SCIP_CALL( tightenCoefs(set, vars, FALSE, conflictrow->vals, conflictrow->inds,
    3235 &conflictrow->nnz, &conflictrow->lhs, &nchgcoefs, NULL) );
    3236 if( nchgcoefs > 0 )
    3237 {
    3238 SCIP_Real previousslack;
    3239
    3240 /* remove variables with zero coefficients from the conflict row */
    3241 conflictRowRemoveZeroVars(conflictrow, set);
    3242
    3243 /* The new slack should always be less or equal to the old slack */
    3244 previousslack = conflictrow->slack;
    3245 SCIP_CALL( computeSlack(set, vars, conflictrow, bdchginfo, fixbounds, fixsides) );
    3246 SCIPsetDebugMsgPrint(set, "Tightened %d coefficients in the resolved constraint, old slack %f, new slack %f \n", nchgcoefs, previousslack, conflictrow->slack);
    3247 assert(SCIPsetIsLE(set, conflictrow->slack, previousslack + EPS) || SCIPsetIsRelLE(set, conflictrow->slack, previousslack));
    3248 SCIPdebug(printConflictRow(conflictrow, set, vars, CONFLICT_ROWTYPE));
    3249 }
    3250
    3251 /* if we reached this point the conflict constraint must have negative slack */
    3252 assert(SCIPsetIsLT(set, conflictrow->slack, 0.0));
    3253
    3254 SCIP_CALL( updateBdchgQueue(set, vars, conflictrow, bdchgidx) );
    3255
    3256 /* get the next bound change */
    3257 bdchginfo = conflictFirstCand(set, conflict, FALSE);
    3258
    3259 /* if no bound change exists the we should stop */
    3260 /* in case we have applied resolution steps we keep the last conflict constraint */
    3261 if( bdchginfo == NULL )
    3262 {
    3263 /* this can happen only if we already have resolved and some
    3264 and it means that we have already reached a FUIP */
    3265 SCIPsetDebugMsgPrint(set, " reached UIP in depth %d \n", bdchgdepth);
    3266 /* add the previous conflict in the list of conflict rows */
    3267 conflictrow->validdepth = validdepth;
    3268 conflictrow->conflictdepth = bdchgdepth;
    3269 conflictrow->insertdepth = validdepth;
    3270 conflictrow->repropdepth = MAX(0, validdepth);
    3271 SCIP_CONFLICTROW* tmpconflictrow;
    3272 SCIP_CALL( conflictRowCopy(&tmpconflictrow, blkmem, conflictrow) );
    3273 SCIP_CALL( conflictInsertConflictRow(conflict, set, &tmpconflictrow) );
    3274 goto TERMINATE_RESOLUTION_LOOP;
    3275 }
    3276
    3277 bdchginfo = conflictRemoveCand(conflict, FALSE);
    3278 bdchgidx = SCIPbdchginfoGetIdx(bdchginfo);
    3279 vartoresolve = SCIPbdchginfoGetVar(bdchginfo);
    3280 bdchgdepth = SCIPbdchginfoGetDepth(bdchginfo);
    3281
    3282 residx = SCIPvarGetProbindex(vartoresolve);
    3283
    3284 assert(!SCIPsetIsZero(set, conflictrow->vals[residx]));
    3285
    3286 /* get the bound change before bdchginfo */
    3287 nextbdchginfo = conflictFirstCand(set, conflict, FALSE);
    3288
    3289 /* check if the variable we are resolving is active */
    3290 assert(SCIPvarIsActive(vartoresolve));
    3291
    3292 assert(nextbdchginfo == NULL || SCIPbdchginfoGetDepth(nextbdchginfo) <= bdchgdepth);
    3293
    3294 /* when at an UIP add the previous conflict in the list of conflict rows */
    3295 if( (nextbdchginfo == NULL || SCIPbdchginfoGetDepth(nextbdchginfo) != bdchgdepth )
    3296 && SCIPbdchginfoGetDepth(bdchginfo) != lastuipdepth)
    3297 {
    3298 SCIPsetDebugMsgPrint(set, " reached UIP in depth %d \n", bdchgdepth);
    3299 /* add the previous conflict in the list of conflict rows */
    3300 conflictrow->validdepth = validdepth;
    3301 conflictrow->conflictdepth = bdchgdepth;
    3302 conflictrow->insertdepth = validdepth;
    3303 conflictrow->repropdepth = (nextbdchginfo == NULL) ? 0 : SCIPbdchginfoGetDepth(nextbdchginfo);
    3304 SCIP_CONFLICTROW* tmpconflictrow;
    3305 SCIP_CALL( conflictRowCopy(&tmpconflictrow, blkmem, conflictrow) );
    3306 SCIP_CALL( conflictInsertConflictRow(conflict, set, &tmpconflictrow) );
    3307 lastuipdepth = bdchgdepth;
    3308 nfuips++;
    3309 /* stop after conf_resfuiplevels UIPs */
    3310 if( set->conf_resfuiplevels > 0 && nfuips >= set->conf_resfuiplevels )
    3311 goto TERMINATE_RESOLUTION_LOOP;
    3312 }
    3313 }
    3314 }
    3315
    3316 TERMINATE_RESOLUTION_LOOP:
    3317
    3318 if( conflict->nconflictrows > 0 )
    3319 {
    3320 int nconstoadd;
    3321
    3322 nconstoadd = (set->conf_resfuiplevels > 0) ? MIN(set->conf_resfuiplevels, conflict->nconflictrows) : conflict->nconflictrows;
    3323
    3324 SCIP_CALL( addConflictRows(conflict, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
    3325 eventfilter, cliquetable, nconstoadd, nconss, nconfvars) );
    3326 }
    3327
    3328 freeConflictResources(conflict, blkmem, set, fixbounds, fixsides);
    3329
    3330 return SCIP_OKAY;
    3331}
    3332
    3333/** analyzes conflicting bound changes that were added with calls to SCIPconflictAddBound(), and on success,
    3334 * creates a linear constraint that explains the infeasibility
    3335 */
    3337 SCIP_CONFLICT* conflict, /**< conflict analysis data */
    3338 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
    3339 SCIP_SET* set, /**< global SCIP settings */
    3340 SCIP_STAT* stat, /**< problem statistics */
    3341 SCIP_PROB* transprob, /**< transformed problem */
    3342 SCIP_PROB* origprob, /**< original problem */
    3343 SCIP_TREE* tree, /**< branch and bound tree */
    3344 SCIP_REOPT* reopt, /**< reoptimization data structure */
    3345 SCIP_LP* lp, /**< LP data */
    3346 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    3347 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    3348 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    3349 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
    3350 SCIP_ROW* initialconflictrow, /**< row of constraint that detected the conflict */
    3351 int validdepth, /**< minimal depth level at which the initial conflict set is valid */
    3352 SCIP_Bool* success /**< pointer to store whether a conflict constraint was created, or NULL */
    3353 )
    3354{
    3355 int nconss;
    3356 int nconfvars;
    3357 int i;
    3358
    3359 /* check if generalized resolution conflict analysis is applicable */
    3361 return SCIP_OKAY;
    3362
    3363 assert(conflict != NULL);
    3364 assert(set != NULL);
    3365 assert(origprob != NULL);
    3366 assert(transprob != NULL);
    3367
    3368 if( success != NULL )
    3369 *success = FALSE;
    3370
    3371 SCIPsetDebugMsgPrint(set, "Starting resolution based conflict analysis after infeasible propagation in depth %d\n",
    3373
    3374 /* start timing */
    3375 SCIPclockStart(conflict->resanalyzetime, set);
    3376
    3377 conflict->nrescalls++;
    3378
    3379 /* setting this to true adds bound changes only to the resolution bdchg queue */
    3380 conflict->bdchgonlyresqueue = TRUE;
    3381
    3382 /* analyze the conflict set, and create a conflict constraint on success */
    3383 SCIP_CALL( conflictAnalyzeResolution(conflict, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
    3384 eventfilter, cliquetable, initialconflictrow, validdepth, &nconss, &nconfvars) );
    3385
    3386 conflict->nressuccess += (nconss > 0 ? 1 : 0);
    3387 conflict->nresconfconss += nconss;
    3388 conflict->nresconfvariables += nconfvars;
    3389
    3390 if( success != NULL )
    3391 *success = (nconss > 0);
    3392
    3393 /* free all conflictrows */
    3394 for( i = 0; i < conflict->nconflictrows; i++ )
    3395 SCIPconflictRowFree(&conflict->conflictrows[i], blkmem);
    3396
    3397 conflict->nconflictrows = 0;
    3398 conflict->bdchgonlyresqueue = FALSE;
    3399
    3400 /* clear the bound change queues */
    3401 SCIPpqueueClear(conflict->resbdchgqueue);
    3403
    3404 /* stop timing */
    3405 SCIPclockStop(conflict->resanalyzetime, set);
    3406 SCIPsetDebugMsgPrint(set, "resolution based conflict analysis added %d constraints \n \n", nconss);
    3407
    3408 return SCIP_OKAY;
    3409}
    static long bound
    void SCIPclockStop(SCIP_CLOCK *clck, SCIP_SET *set)
    Definition: clock.c:360
    void SCIPclockStart(SCIP_CLOCK *clck, SCIP_SET *set)
    Definition: clock.c:290
    internal methods for clocks and timing issues
    internal methods for conflict analysis
    static void conflictRowRemoveZeroVars(SCIP_CONFLICTROW *row, SCIP_SET *set)
    static SCIP_RETCODE conflictEnsureConflictRowsMem(SCIP_CONFLICT *conflict, SCIP_SET *set, int num)
    static SCIP_Real getQuotLargestSmallestCoef(SCIP_SET *set, int *inds, SCIP_Real *vals, int nnz)
    static void conflictRowClear(BMS_BLKMEM *blkmem, SCIP_CONFLICTROW *row, int nvars)
    static SCIP_RETCODE updateStatistics(SCIP_CONFLICT *conflict, SCIP_VAR **vars, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_CONFLICTROW *conflictrow, int insertdepth)
    static void weakenConflictRow(SCIP_CONFLICTROW *row, SCIP_SET *set, SCIP_VAR **vars, SCIP_BDCHGIDX *currbdchgidx, int *fixsides)
    static void weakenVarConflictRow(SCIP_CONFLICTROW *row, SCIP_SET *set, SCIP_VAR *var, int pos)
    static SCIP_RETCODE conflictInsertConflictRow(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_CONFLICTROW **conflictrow)
    static SCIP_Bool isBdchgConflictRelevant(SCIP_CONFLICT *conflict, SCIP_BDCHGINFO *bdchginfo, int initial)
    void SCIPconflictRowFree(SCIP_CONFLICTROW **row, BMS_BLKMEM *blkmem)
    static void linearCombRows(SCIP_SET *set, SCIP_CONFLICTROW *row1, SCIP_CONFLICTROW *row2, SCIP_Real scale)
    static SCIP_Real computeScaleReason(SCIP_SET *set, SCIP_CONFLICTROW *conflictrow, SCIP_CONFLICTROW *reasonrow, int residx)
    #define BOUNDSWITCH
    SCIP_RETCODE SCIPconflictAddConflictCon(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_CONFLICTROW *conflictrow, SCIP_Bool *success)
    static int conflictCalcResMaxsize(SCIP_SET *set, SCIP_PROB *prob)
    static SCIP_RETCODE updateBdchgQueue(SCIP_SET *set, SCIP_VAR **vars, SCIP_CONFLICTROW *conflictrow, SCIP_BDCHGIDX *inferbdchgidx)
    static SCIP_Bool isResolvableBdchg(SCIP_BDCHGINFO *bdchginfo)
    #define MAXFRAC
    static SCIP_Bool existsResolvablebdchginfo(SCIP_CONFLICT *conflict)
    static SCIP_RETCODE weakenContinuousVarsConflictRow(SCIP_CONFLICTROW *row, SCIP_SET *set, SCIP_VAR **vars, int residx)
    #define POSTPROCESS
    SCIP_RETCODE conflictAnalyzeResolution(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_ROW *initialconflictrow, int validdepth, int *nconss, int *nconfvars)
    SCIP_Longint SCIPconflictGetNResConflictConss(SCIP_CONFLICT *conflict)
    static void conflictRowRemoveZeroVar(SCIP_CONFLICTROW *row, SCIP_SET *set, int pos)
    static SCIP_RETCODE conflictRowReplace(SCIP_CONFLICTROW *targetrow, BMS_BLKMEM *blkmem, SCIP_CONFLICTROW *sourcerow)
    static SCIP_BDCHGINFO * conflictFirstCand(SCIP_SET *set, SCIP_CONFLICT *conflict, int initial)
    SCIP_Longint SCIPconflictGetNResLargeCoefs(SCIP_CONFLICT *conflict)
    static SCIP_RETCODE addConflictRows(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, int nconstoadd, int *nconss, int *nconfvars)
    static SCIP_RETCODE MirReduction(SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_VAR **vars, int nvars, SCIP_CONFLICTROW *reasonrow, SCIP_BDCHGINFO *currbdchginfo, int varidx, SCIP_Real divisor)
    static SCIP_RETCODE getReasonRow(BMS_BLKMEM *blkmem, SCIP_VAR **vars, SCIP_SET *set, SCIP_BDCHGINFO *currbdchginfo, SCIP_CONFLICTROW *reasonrow, int residx, SCIP_Real *fixbounds, int *fixsides, SCIP_Bool *success)
    static SCIP_RETCODE conflictRowFromLpRow(SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_ROW *row, SCIP_CONFLICTROW *conflictrow, SCIP_BDCHGINFO *bdchginfo)
    SCIP_Longint SCIPconflictGetNResSuccess(SCIP_CONFLICT *conflict)
    #define EPS
    SCIP_Longint SCIPconflictGetNResCalls(SCIP_CONFLICT *conflict)
    static SCIP_Bool hasRelaxationOnlyVar(SCIP_SET *set, SCIP_VAR **vars, SCIP_CONFLICTROW *row)
    static SCIP_RETCODE conflictRowAddSemiSparseData(SCIP_CONFLICTROW *resolutionrow, BMS_BLKMEM *blkmem, SCIP_Real *vals, int *inds, int nnz, SCIP_Real lhs, SCIP_Bool reverse)
    SCIP_RETCODE SCIPconflictInitRows(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem)
    #define FIXINTEGRALRHS
    static SCIP_RETCODE getConflictRow(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PROB *prob, SCIP_ROW *initialconflictrow, SCIP_BDCHGINFO *currbdchginfo, int maxsize, SCIP_Bool *success)
    static SCIP_RETCODE ComplementedMirLhs(SCIP_SET *set, SCIP_VAR **vars, SCIP_CONFLICTROW *reasonrow, int *fixsides, SCIP_BDCHGIDX *currbdchgidx, int idxreason, SCIP_Real divisor)
    static SCIP_RETCODE slackReducingContinuousBdchgQueue(SCIP_CONFLICT *conflict, SCIP_VAR **vars, SCIP_CONFLICTROW *row, SCIP_BDCHGIDX *inferbdchgidx)
    #define USEVBDS
    static void freeConflictResources(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real *fixbounds, int *fixsides)
    static SCIP_RETCODE incVSIDS(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_BOUNDTYPE boundtype, SCIP_Real value, SCIP_Real weight)
    static SCIP_RETCODE reduceReason(SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_VAR **vars, int nvars, SCIP_CONFLICTROW *rowtoreduce, SCIP_BDCHGINFO *currbdchginfo, int residx, SCIP_Real *fixbounds, int *fixsides)
    SCIP_Longint SCIPconflictGetNResLongConflicts(SCIP_CONFLICT *conflict)
    SCIP_Bool SCIPconflictResolutionApplicable(SCIP_SET *set)
    static SCIP_Bool isBinaryConflictRow(SCIP_SET *set, SCIP_VAR **vars, SCIP_CONFLICTROW *row)
    #define MINFRAC
    static SCIP_RETCODE conflictRowCopy(SCIP_CONFLICTROW **targetrow, BMS_BLKMEM *blkmem, SCIP_CONFLICTROW *sourcerow)
    static SCIP_BDCHGINFO * conflictRemoveCand(SCIP_CONFLICT *conflict, int initial)
    static SCIP_RETCODE computeSlack(SCIP_SET *set, SCIP_VAR **vars, SCIP_CONFLICTROW *row, SCIP_BDCHGINFO *currbdchginfo, SCIP_Real *fixbounds, int *fixsides)
    static SCIP_RETCODE tightenCoefs(SCIP_SET *set, SCIP_VAR **vars, SCIP_Bool localbounds, SCIP_Real *rowcoefs, int *rowinds, int *rownnz, SCIP_Real *rowlhs, int *nchgcoefs, SCIP_Bool *redundant)
    SCIP_RETCODE SCIPconflictAnalyzeResolution(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_ROW *initialconflictrow, int validdepth, SCIP_Bool *success)
    static SCIP_RETCODE markBdchgAsFixed(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_VAR **vars, SCIP_BDCHGINFO **currbdchginfo, int *currbdchgdepth, int nressteps, SCIP_Real *fixbounds, int *fixsides, SCIP_Bool *success)
    static SCIP_RETCODE executeResolutionStep(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_VAR **vars, BMS_BLKMEM *blkmem, SCIP_BDCHGINFO *currbdchginfo, int residx, int maxsize, SCIP_Real *fixbounds, int *fixsides, SCIP_Bool *successresolution)
    static SCIP_RETCODE createAndAddConflictCon(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **vars, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_CONFLICTROW *conflictrow, int insertdepth, SCIP_Bool *success)
    static SCIP_RETCODE rescaleAndResolve(SCIP_SET *set, SCIP_CONFLICT *conflict, SCIP_CONFLICTROW *row1, SCIP_CONFLICTROW *row2, SCIP_CONFLICTROW *resolvedrow, BMS_BLKMEM *blkmem, int residx, SCIP_Bool *success)
    static SCIP_RETCODE reasonRowFromLpRow(SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_ROW *row, SCIP_CONFLICTROW *reasonrow, SCIP_BDCHGINFO *bdchginfo)
    static SCIP_RETCODE conflictRowCreate(SCIP_CONFLICTROW **row, BMS_BLKMEM *blkmem)
    Methods for generalized resolution conflict analysis.
    internal methods for constraints and constraint handlers
    Constraint handler for linear constraints in their most general form, .
    methods for the aggregation rows
    #define SCIPquadprecProdDD(r, a, b)
    Definition: dbldblarith.h:58
    #define SCIPquadprecProdQD(r, a, b)
    Definition: dbldblarith.h:63
    #define SCIPquadprecSumQD(r, a, b)
    Definition: dbldblarith.h:62
    #define QUAD_ASSIGN(a, constant)
    Definition: dbldblarith.h:51
    #define QUAD(x)
    Definition: dbldblarith.h:47
    #define SCIPquadprecSumDD(r, a, b)
    Definition: dbldblarith.h:60
    #define SCIPquadprecSumQQ(r, a, b)
    Definition: dbldblarith.h:67
    #define QUAD_ARRAY_LOAD(r, a, idx)
    Definition: dbldblarith.h:54
    #define QUAD_TO_DBL(x)
    Definition: dbldblarith.h:49
    #define SCIPdebugCheckConss(scip, conss, nconss)
    Definition: debug.h:296
    #define NULL
    Definition: def.h:248
    #define SCIP_MAXSTRLEN
    Definition: def.h:269
    #define SCIP_Longint
    Definition: def.h:141
    #define SCIP_UNUSED(x)
    Definition: def.h:409
    #define SCIP_REAL_MAX
    Definition: def.h:158
    #define SCIP_Bool
    Definition: def.h:91
    #define MIN(x, y)
    Definition: def.h:224
    #define SCIP_ALLOC(x)
    Definition: def.h:366
    #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_CALL_ABORT(x)
    Definition: def.h:334
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:148
    #define SCIPABORT()
    Definition: def.h:327
    #define SCIP_REAL_MIN
    Definition: def.h:159
    #define REALABS(x)
    Definition: def.h:182
    #define SCIP_CALL(x)
    Definition: def.h:355
    SCIP_RETCODE SCIPupgradeConsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_CONS **upgdcons)
    SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    int SCIPgetNContVars(SCIP *scip)
    Definition: scip_prob.c:2569
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    SCIP_RETCODE SCIPaddConflict(SCIP *scip, SCIP_NODE *node, SCIP_CONS **cons, SCIP_NODE *validnode, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
    Definition: scip_prob.c:3806
    void ** SCIPpqueueElems(SCIP_PQUEUE *pqueue)
    Definition: misc.c:1540
    void SCIPpqueueClear(SCIP_PQUEUE *pqueue)
    Definition: misc.c:1335
    SCIP_RETCODE SCIPpqueueInsert(SCIP_PQUEUE *pqueue, void *elem)
    Definition: misc.c:1396
    int SCIPpqueueNElems(SCIP_PQUEUE *pqueue)
    Definition: misc.c:1529
    void * SCIPpqueueRemove(SCIP_PQUEUE *pqueue)
    Definition: misc.c:1495
    void * SCIPpqueueFirst(SCIP_PQUEUE *pqueue)
    Definition: misc.c:1515
    SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
    Definition: lp.c:17425
    SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
    SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
    const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4316
    SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
    Definition: cons.c:8409
    SCIP_Bool SCIPconsIsGlobal(SCIP_CONS *cons)
    Definition: cons.c:8618
    const char * SCIPconsGetName(SCIP_CONS *cons)
    Definition: cons.c:8389
    SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    SCIP_RETCODE SCIPcalcMIR(SCIP *scip, SCIP_SOL *sol, SCIP_Bool postprocess, SCIP_Real boundswitch, int vartypeusevbds, SCIP_Bool allowlocal, SCIP_Bool fixintegralrhs, int *boundsfortrans, SCIP_BOUNDTYPE *boundtypesfortrans, SCIP_Real minfrac, SCIP_Real maxfrac, SCIP_Real scale, SCIP_AGGRROW *aggrrow, SCIP_Real *cutcoefs, SCIP_Real *cutrhs, int *cutinds, int *cutnnz, SCIP_Real *cutefficacy, int *cutrank, SCIP_Bool *cutislocal, SCIP_Bool *success)
    Definition: cuts.c:7923
    SCIP_RETCODE SCIPaggrRowCreate(SCIP *scip, SCIP_AGGRROW **aggrrow)
    Definition: cuts.c:2668
    SCIP_RETCODE SCIPaggrRowAddCustomCons(SCIP *scip, SCIP_AGGRROW *aggrrow, int *inds, SCIP_Real *vals, int len, SCIP_Real rhs, SCIP_Real weight, int rank, SCIP_Bool local)
    Definition: cuts.c:3143
    void SCIPaggrRowFree(SCIP *scip, SCIP_AGGRROW **aggrrow)
    Definition: cuts.c:2700
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPfreeBufferArrayNull(scip, ptr)
    Definition: scip_mem.h:137
    int SCIPnodeGetDepth(SCIP_NODE *node)
    Definition: tree.c:8493
    const char * SCIPpropGetName(SCIP_PROP *prop)
    Definition: prop.c:951
    SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
    Definition: lp.c:17686
    int SCIProwGetNNonz(SCIP_ROW *row)
    Definition: lp.c:17607
    SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
    Definition: lp.c:17632
    SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
    Definition: lp.c:17696
    const char * SCIProwGetName(SCIP_ROW *row)
    Definition: lp.c:17745
    SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
    Definition: lp.c:17652
    SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
    Definition: lp.c:17642
    SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:516
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1252
    SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_sol.c:1571
    SCIP_Bool SCIPbdchginfoIsRedundant(SCIP_BDCHGINFO *bdchginfo)
    Definition: var.c:25057
    SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
    Definition: var.c:23642
    SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
    Definition: var.c:23478
    SCIP_BDCHGIDX * SCIPbdchginfoGetIdx(SCIP_BDCHGINFO *bdchginfo)
    Definition: var.c:24979
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23386
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24268
    SCIP_BDCHGINFO * SCIPvarGetLbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
    Definition: var.c:22629
    SCIP_PROP * SCIPbdchginfoGetInferProp(SCIP_BDCHGINFO *bdchginfo)
    Definition: var.c:25013
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23453
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24142
    int SCIPbdchginfoGetDepth(SCIP_BDCHGINFO *bdchginfo)
    Definition: var.c:24959
    SCIP_CONS * SCIPbdchginfoGetInferCons(SCIP_BDCHGINFO *bdchginfo)
    Definition: var.c:25001
    int SCIPbdchginfoGetPos(SCIP_BDCHGINFO *bdchginfo)
    Definition: var.c:24969
    SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
    Definition: scip_var.c:2872
    int SCIPvarGetProbindex(SCIP_VAR *var)
    Definition: var.c:23662
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
    Definition: var.c:24929
    SCIP_Real SCIPbdchginfoGetOldbound(SCIP_BDCHGINFO *bdchginfo)
    Definition: var.c:24909
    SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
    Definition: var.c:23490
    SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(SCIP_BDCHGINFO *bdchginfo)
    Definition: var.c:24939
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24234
    SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
    Definition: var.c:23600
    SCIP_BDCHGINFO * SCIPvarGetUbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
    Definition: var.c:22685
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24120
    SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
    Definition: scip_var.c:2736
    int SCIPvarGetNBdchgInfosUb(SCIP_VAR *var)
    Definition: var.c:24736
    SCIP_BOUNDTYPE SCIPbdchginfoGetBoundtype(SCIP_BDCHGINFO *bdchginfo)
    Definition: var.c:24949
    SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
    Definition: var.c:24919
    int SCIPvarGetNBdchgInfosLb(SCIP_VAR *var)
    Definition: var.c:24716
    void SCIPsortDownRealInt(SCIP_Real *realarray, int *intarray, int len)
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    void SCIPhistoryIncNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real length)
    Definition: history.c:674
    void SCIPhistoryIncVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
    Definition: history.c:635
    internal methods for branching and inference history
    memory allocation routines
    #define BMSfreeBlockMemory(mem, ptr)
    Definition: memory.h:465
    #define BMSallocBlockMemory(mem, ptr)
    Definition: memory.h:451
    #define BMSreallocMemoryArray(ptr, num)
    Definition: memory.h:127
    #define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
    Definition: memory.h:468
    #define BMSallocBlockMemoryArray(mem, ptr, num)
    Definition: memory.h:454
    #define BMScopyMemoryArray(ptr, source, num)
    Definition: memory.h:134
    #define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
    Definition: memory.h:458
    struct BMS_BlkMem BMS_BLKMEM
    Definition: memory.h:437
    SCIP_RETCODE SCIPconsCreateRow(SCIP *scip, SCIP_CONS *cons, SCIP_ROW **row)
    Definition: misc_linear.c:599
    SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
    Definition: prob.c:2913
    internal methods for storing and manipulating the main problem
    internal methods for propagators
    public methods for conflict analysis handlers
    public methods for managing constraints
    public methods for LP management
    public methods for message output
    #define SCIPdebug(x)
    Definition: pub_message.h:93
    #define SCIPdebugMessage
    Definition: pub_message.h:96
    #define SCIPdebugPrintf
    Definition: pub_message.h:99
    public data structures and miscellaneous methods
    public methods for problem variables
    public methods for conflict handler plugins and conflict analysis
    public methods for constraint handler plugins and constraints
    public methods for memory management
    public methods for global and local (sub)problems
    public methods for solutions
    public methods for SCIP variables
    SCIP_Real SCIPsetFloor(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6716
    SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6617
    SCIP_Real SCIPsetCeil(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6728
    SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:7017
    SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6648
    SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6577
    SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6537
    SCIP_Real SCIPsetInfinity(SCIP_SET *set)
    Definition: set.c:6380
    SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6557
    SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6515
    SCIP_Bool SCIPsetIsRelGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:7559
    SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6597
    SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6637
    SCIP_Bool SCIPsetIsRelLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:7511
    int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
    Definition: set.c:6080
    SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6659
    internal methods for global SCIP settings
    #define SCIPsetFreeBufferArray(set, ptr)
    Definition: set.h:1782
    #define SCIPsetDebugMsgPrint
    Definition: set.h:1812
    #define SCIPsetAllocBufferArray(set, ptr, num)
    Definition: set.h:1775
    #define SCIPsetDebugMsg
    Definition: set.h:1811
    internal methods for storing primal CIP solutions
    SCIP_Real * vals
    Definition: struct_cuts.h:42
    SCIP_INFERENCEDATA inferencedata
    Definition: struct_var.h:126
    SCIP_VAR * var
    Definition: struct_var.h:125
    SCIP_Real coefquotient
    unsigned int isbinary
    SCIP_CONFTYPE conflicttype
    unsigned int usescutoffbound
    SCIP_Real * conflictvarsubs
    SCIP_Longint nappliedglbconss
    SCIP_CONFLICTROW ** conflictrows
    SCIP_PQUEUE * resbdchgqueue
    SCIP_Longint nappliedglbliterals
    SCIP_Longint nresconfconss
    SCIP_Longint nappliedglbresconss
    SCIP_CONFLICTROW * resolvedconflictrow
    SCIP_CONFLICTROW * reducedreasonrow
    SCIP_Longint nreslongconfs
    SCIP_Longint nresconfvariables
    SCIP_Longint nappliedlocconss
    SCIP_CLOCK * resanalyzetime
    SCIP_PQUEUE * continuousbdchgqueue
    SCIP_CONFLICTROW * conflictrow
    SCIP_Bool bdchgonlyresqueue
    SCIP_CONFLICTROW * reasonrow
    SCIP_Longint nrescalls
    SCIP_Real * conflictvarslbs
    SCIP_Longint nressuccess
    SCIP_Longint nreslargecoefs
    SCIP_Longint nappliedlocliterals
    SCIP_CONSHDLR * conshdlr
    Definition: struct_cons.h:50
    SCIP_Bool strongbranching
    Definition: struct_lp.h:383
    SCIP_Bool diving
    Definition: struct_lp.h:386
    int ncontvars
    Definition: struct_prob.h:80
    SCIP_VAR ** vars
    Definition: struct_prob.h:67
    SCIP_HISTORY * glbhistory
    Definition: struct_stat.h:195
    SCIP_Real vsidsweight
    Definition: struct_stat.h:134
    SCIP_HISTORY * glbhistorycrun
    Definition: struct_stat.h:196
    SCIP_NODE ** path
    Definition: struct_tree.h:190
    datastructures for conflict analysis
    data structures for LP management
    datastructures for storing and manipulating the main problem
    datastructures for global SCIP settings
    datastructures for problem statistics
    Definition: heur_padm.c:135
    int SCIPtreeGetFocusDepth(SCIP_TREE *tree)
    Definition: tree.c:9404
    SCIP_RETCODE SCIPnodeAddBoundchg(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype, SCIP_Bool probingchange)
    Definition: tree.c:2539
    SCIP_RETCODE SCIPnodeCutoff(SCIP_NODE *node, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTFILTER *eventfilter, SCIP_TREE *tree, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_REOPT *reopt, SCIP_LP *lp, BMS_BLKMEM *blkmem)
    Definition: tree.c:1259
    int SCIPtreeGetCurrentDepth(SCIP_TREE *tree)
    Definition: tree.c:9479
    internal methods for branch and bound tree
    @ SCIP_CONFTYPE_PROPAGATION
    Definition: type_conflict.h:62
    @ SCIP_BRANCHDIR_DOWNWARDS
    Definition: type_history.h:43
    @ SCIP_BRANCHDIR_UPWARDS
    Definition: type_history.h:44
    enum SCIP_BranchDir SCIP_BRANCHDIR
    Definition: type_history.h:48
    @ SCIP_BOUNDTYPE_UPPER
    Definition: type_lp.h:58
    @ SCIP_BOUNDTYPE_LOWER
    Definition: type_lp.h:57
    enum SCIP_BoundType SCIP_BOUNDTYPE
    Definition: type_lp.h:60
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    enum SCIP_BoundchgType SCIP_BOUNDCHGTYPE
    Definition: type_var.h:135
    @ SCIP_VARTYPE_INTEGER
    Definition: type_var.h:65
    @ SCIP_VARTYPE_BINARY
    Definition: type_var.h:64
    @ SCIP_BOUNDCHGTYPE_PROPINFER
    Definition: type_var.h:133
    @ SCIP_BOUNDCHGTYPE_BRANCHING
    Definition: type_var.h:131
    @ SCIP_BOUNDCHGTYPE_CONSINFER
    Definition: type_var.h:132
    SCIP_RETCODE SCIPvarIncVSIDS(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_BRANCHDIR dir, SCIP_Real value, SCIP_Real weight)
    Definition: var.c:21103
    int SCIPbdchgidxGetDepth(SCIP_BDCHGIDX *bdchgidx)
    Definition: var.c:24859
    SCIP_RETCODE SCIPvarIncNActiveConflicts(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_BRANCHDIR dir, SCIP_Real value, SCIP_Real length)
    Definition: var.c:21239
    int SCIPbdchgidxGetPos(SCIP_BDCHGIDX *bdchgidx)
    Definition: var.c:24849
    internal methods for problem variables