conflict.c
Go to the documentation of this file.
28 * Given is a set of bound changes that are not allowed being applied simultaneously, because they
29 * render the current node infeasible (e.g. because a single constraint is infeasible in the these
30 * bounds, or because the LP relaxation is infeasible). The goal is to deduce a clause on variables
31 * -- a conflict clause -- representing the "reason" for this conflict, i.e., the branching decisions
32 * or the deductions (applied e.g. in domain propagation) that lead to the conflict. This clause can
35 * conflict was detected by a locally valid constraint. In this case, the resulting conflict clause
114 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
181 static SCIP_BDCHGINFO* confgraphcurrentbdchginfo = NULL; /**< currently resolved bound change */
196 SCIPgmlWriteNode(confgraphfile, (unsigned int)(size_t)idptr, label, nodetype, fillcolor, bordercolor);
210 SCIPgmlWriteArc(confgraphfile, (unsigned int)(size_t)source, (unsigned int)(size_t)target, NULL, color);
212 SCIPgmlWriteEdge(confgraphfile, (unsigned int)(size_t)source, (unsigned int)(size_t)target, NULL, color);
216 /** creates a file to output the current conflict graph into; adds the conflict vertex to the graph */
266 /** adds a bound change node to the conflict graph and links it to the currently resolved bound change */
303 (void) SCIPsnprintf(label, SCIP_MAXSTRLEN, "%s %s %g\n[%s:%d]", SCIPvarGetName(SCIPbdchginfoGetVar(bdchginfo)),
340 (void) SCIPsnprintf(label, SCIP_MAXSTRLEN, "conf %d (%d)", confgraphnconflictsets, conflictset->validdepth);
341 confgraphWriteNode((void*)(size_t)confgraphnconflictsets, label, "rectangle", "#ff00ff", "#000000");
343 confgraphWriteEdge((void*)(size_t)confgraphnconflictsets, conflictset->bdchginfos[i], "#ff00ff");
361 return strcmp(SCIPconflicthdlrGetName((SCIP_CONFLICTHDLR*)elem1), SCIPconflicthdlrGetName((SCIP_CONFLICTHDLR*)elem2));
374 SCIP_CALL( SCIPsetConflicthdlrPriority(scip, (SCIP_CONFLICTHDLR*)paramdata, SCIPparamGetInt(param)) ); /*lint !e740*/
391 SCIPsetDebugMsg(set, "including conflict handler %s in subscip %p\n", SCIPconflicthdlrGetName(conflicthdlr), (void*)set->scip);
408 SCIP_DECL_CONFLICTCOPY((*conflictcopy)), /**< copy method of conflict handler or NULL if you don't want to copy your plugin into sub-SCIPs */
412 SCIP_DECL_CONFLICTINITSOL((*conflictinitsol)),/**< solving process initialization method of conflict handler */
413 SCIP_DECL_CONFLICTEXITSOL((*conflictexitsol)),/**< solving process deinitialization method of conflict handler */
447 SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc, &(*conflicthdlr)->priority, TRUE, \
448 priority, INT_MIN, INT_MAX, paramChgdConflicthdlrPriority, (SCIP_PARAMDATA*)(*conflicthdlr)) ); /*lint !e740*/
462 SCIP_DECL_CONFLICTCOPY((*conflictcopy)), /**< copy method of conflict handler or NULL if you don't want to
467 SCIP_DECL_CONFLICTINITSOL((*conflictinitsol)),/**< solving process initialization method of conflict handler */
468 SCIP_DECL_CONFLICTEXITSOL((*conflictexitsol)),/**< solving process deinitialization method of conflict handler */
477 SCIP_CALL_FINALLY( doConflicthdlrCreate(conflicthdlr, set, messagehdlr, blkmem, name, desc, priority,
478 conflictcopy, conflictfree, conflictinit, conflictexit, conflictinitsol, conflictexitsol, conflictexec,
635 SCIP_Real* relaxedbds, /**< array with relaxed bounds which are efficient to create a valid conflict */
655 SCIP_CALL( conflicthdlr->conflictexec(set->scip, conflicthdlr, node, validnode, bdchginfos, relaxedbds, nbdchginfos,
656 conftype, usescutoffbound, set->conf_separate, (SCIPnodeGetDepth(validnode) > 0), set->conf_dynamic,
743 SCIP_DECL_CONFLICTINITSOL((*conflictinitsol))/**< solving process initialization method of conflict handler */
754 SCIP_DECL_CONFLICTEXITSOL((*conflictexitsol))/**< solving process deinitialization method of conflict handler */
818 SCIP_CONFLICTHDLR* conflicthdlr, /**< the conflict handler for which all clocks should be enabled or disabled */
1147 SCIP_CALL( proofsetAddSparseData(proofset, blkmem, vals, inds, nnz, SCIPaggrRowGetRhs(aggrrow)) );
1154 /** Removes a given variable @p var from position @p pos from the proofset and updates the right-hand side according
1155 * to sign of the coefficient, i.e., rhs -= coef * bound, where bound = lb if coef >= 0 and bound = ub, otherwise.
1157 * @note: The list of non-zero indices and coefficients will be updated by swapping the last non-zero index to @p pos.
1202 /** resizes the array of the temporary bound change informations to be able to store at least num bound change entries */
1226 /** creates a temporary bound change information object that is destroyed after the conflict sets are flushed */
1325 BMScopyMemoryArray((*targetconflictset)->bdchginfos, sourceconflictset->bdchginfos, sourceconflictset->nbdchginfos);
1326 BMScopyMemoryArray((*targetconflictset)->relaxedbds, sourceconflictset->relaxedbds, sourceconflictset->nbdchginfos);
1327 BMScopyMemoryArray((*targetconflictset)->sortvals, sourceconflictset->sortvals, sourceconflictset->nbdchginfos);
1350 BMSfreeBlockMemoryArrayNull(blkmem, &(*conflictset)->bdchginfos, (*conflictset)->bdchginfossize);
1351 BMSfreeBlockMemoryArrayNull(blkmem, &(*conflictset)->relaxedbds, (*conflictset)->bdchginfossize);
1352 BMSfreeBlockMemoryArrayNull(blkmem, &(*conflictset)->sortvals, (*conflictset)->bdchginfossize);
1356 /** resizes the arrays of the conflict set to be able to store at least num bound change entries */
1373 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &conflictset->bdchginfos, conflictset->bdchginfossize, newsize) );
1374 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &conflictset->relaxedbds, conflictset->bdchginfossize, newsize) );
1375 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &conflictset->sortvals, conflictset->bdchginfossize, newsize) );
1429 * (SCIP_Real)(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL))/(SCIP_Real)(SCIPcolGetNNonz(col));
1437 * (SCIP_Real)(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL))/(SCIP_Real)(SCIPcolGetNNonz(col));
1445 /** check if the bound change info (which is the potential next candidate which is queued) is valid for the current
1446 * conflict analysis; a bound change info can get invalid if after this one was added to the queue, a weaker bound
1447 * change was added to the queue (due the bound widening idea) which immediately makes this bound change redundant; due
1448 * to the priority we did not removed that bound change info since that cost O(log(n)); hence we have to skip/ignore it
1451 * The following situations can occur before for example the bound change info (x >= 3) is potentially popped from the
1454 * Postcondition: the reason why (x >= 3) was queued is that at this time point no lower bound of x was involved yet in
1455 * the current conflict or the lower bound which was involved until then was stronger, e.g., (x >= 2).
1457 * 1) during the time until (x >= 3) gets potentially popped no weaker lower bound was added to the queue, in that case
1458 * the conflictlbcount is valid and conflictlb is 3; that is (var->conflictlbcount == conflict->count &&
1461 * 2) a weaker bound change info gets queued (e.g., x >= 4); this bound change is popped before (x >= 3) since it has
1462 * higher priority (which is the time stamp of the bound change info and (x >= 4) has to be done after (x >= 3)
1465 * a) if (x >= 4) is popped and added to the conflict set the conflictlbcount is still valid and conflictlb is at
1466 * most 4; that is (var->conflictlbcount == conflict->count && var->conflictlb >= 4); it follows that any bound
1469 * b) if (x >= 4) is popped and resolved without introducing a new lower bound on x until (x >= 3) is a potentially
1473 * c) if (x >= 4) is popped and resolved and a new lower bound on x (e.g., x >= 2) is introduced until (x >= 3) is
1474 * pooped, the conflictlbcount indicates that bound change is currently present; that is (var->conflictlbcount ==
1475 * conflict->count); however the (x >= 3) only has be explained if conflictlb matches that one; that is
1491 /* the bound change info of a binary (domained) variable can never be invalid since the concepts of relaxed bounds
1497 /* check if the bdchginfo is invaild since a tight/weaker bound change was already explained */
1500 if( var->conflictlbcount != conflict->count || var->conflictlb != SCIPbdchginfoGetNewbound(bdchginfo) ) /*lint !e777*/
1510 if( var->conflictubcount != conflict->count || var->conflictub != SCIPbdchginfoGetNewbound(bdchginfo) ) /*lint !e777*/
1543 SCIP_CALL( conflictsetEnsureBdchginfosMem(conflictset, blkmem, set, conflictset->nbdchginfos+1) );
1545 /* insert the new bound change in the arrays sorted by increasing variable index and by bound type */
1554 sortval = 2*idx + (int)boundtype; /* first sorting criteria: variable index, second criteria: boundtype */
1556 /* insert new element into the sorted arrays; if an element exits with the same value insert the new element afterwards
1558 * @todo check if it better (faster) to first search for the position O(log n) and compare the sort values and if
1562 SCIPsortedvecInsertIntPtrReal(sortvals, (void**)bdchginfos, relaxedbds, sortval, (void*)bdchginfo, relaxedbd, &conflictset->nbdchginfos, &pos);
1572 SCIPsortedvecDelPosIntPtrReal(sortvals, (void**)bdchginfos, relaxedbds, pos-1, &conflictset->nbdchginfos);
1577 SCIPsortedvecDelPosIntPtrReal(sortvals, (void**)bdchginfos, relaxedbds, pos, &conflictset->nbdchginfos);
1581 /* both bound change are equivalent; hence, keep the worse relaxed bound and remove one of them */
1582 relaxedbds[pos-1] = boundtype == SCIP_BOUNDTYPE_LOWER ? MAX(relaxedbds[pos-1], relaxedbd) : MIN(relaxedbds[pos-1], relaxedbd);
1583 SCIPsortedvecDelPosIntPtrReal(sortvals, (void**)bdchginfos, relaxedbds, pos, &conflictset->nbdchginfos);
1631 SCIP_CALL( conflictsetAddBound(conflictset, blkmem, set, bdchginfo, SCIPbdchginfoGetRelaxedBound(bdchginfo)) );
1635 SCIPsetDebugMsg(set, "-> bound change info [%d:<%s> %s %g] is invaild -> ignore it\n", SCIPbdchginfoGetDepth(bdchginfo),
1647 SCIP_CALL( conflictsetEnsureBdchginfosMem(conflictset, blkmem, set, confnbdchginfos + nbdchginfos) );
1672 sortval = 2*idx + (int)boundtype; /* first sorting criteria: variable index, second criteria: boundtype */
1682 SCIPsetDebugMsg(set, "-> bound change info [%d:<%s> %s %g] is invaild -> ignore it\n", SCIPbdchginfoGetDepth(bdchginfo),
1721 /* both bound change are equivalent; hence, keep the worse relaxed bound and remove one of them */
1722 confrelaxedbds[k] = (confsortvals[k] % 2 == 0) ? MAX(confrelaxedbds[k], confrelaxedbds[i]) : MIN(confrelaxedbds[k], confrelaxedbds[i]);
1744 /* the number of bound change infos cannot be decreased, it would mean that the conflict set was not merged
1792 * - if the branching rule operates on variables only, and if all branching variables up to a certain
1793 * depth level are member of the conflict, the conflict constraint can only be violated in the subtree
1794 * of the node at that depth, because in all other nodes, at least one of these branching variables
1796 * - if there is at least one branching variable in a node, we assume, that this branching was performed
1797 * on variables, and that the siblings of this node are disjunct w.r.t. the branching variables' fixings
1831 depth = MIN(depth, currentdepth+1); /* put diving/probing/strong branching changes in this depth level */
1836 while( conflictset->insertdepth < currentdepth && branchingincluded[conflictset->insertdepth+1] )
1842 assert(conflictset->validdepth <= conflictset->insertdepth && conflictset->insertdepth <= currentdepth);
1864 /* check, if all bound changes in conflictset2 are also present at least as tight in conflictset1;
1865 * we can stop immediately, if more bound changes are remaining in conflictset2 than in conflictset1
1867 for( i1 = 0, i2 = 0; i2 < conflictset2->nbdchginfos && conflictset1->nbdchginfos - i1 >= conflictset2->nbdchginfos - i2;
1875 for( ; i1 < conflictset1->nbdchginfos && conflictset1->sortvals[i1] < sortval; ++i1 ) /*lint !e445*/
1978 /** inserts conflict set into sorted conflictsets array and deletes the conflict set pointer */
2002 /* if we apply repropagations, the conflict set should be inserted at most at its repropdepth */
2009 SCIPsetDebugMsg(set, "inserting conflict set (valid: %d, insert: %d, conf: %d, reprop: %d):\n",
2010 (*conflictset)->validdepth, (*conflictset)->insertdepth, (*conflictset)->conflictdepth, (*conflictset)->repropdepth);
2017 for( pos = 0; pos < conflict->nconflictsets && score < conflict->conflictsetscores[pos]; ++pos )
2028 /**@todo like in sepastore.c: calculate overlap between conflictsets -> large overlap reduces score */
2113 branchdir = (boundtype == SCIP_BOUNDTYPE_LOWER ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS); /*lint !e641*/
2156 branchdir = (boundtype == SCIP_BOUNDTYPE_LOWER ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS); /*lint !e641*/
2158 SCIP_CALL( SCIPvarIncNActiveConflicts(var, blkmem, set, stat, branchdir, bound, (SCIP_Real)conflictlength) );
2173 /** check conflict set for redundancy, other conflicts in the same conflict analysis could have led to global reductions
2204 assert(SCIPbdchginfoGetBoundtype(bdchginfos[v]) == SCIP_BOUNDTYPE_LOWER || SCIPsetIsGE(set, relaxedbds[v], SCIPbdchginfoGetNewbound(bdchginfos[v])));
2205 assert(SCIPbdchginfoGetBoundtype(bdchginfos[v]) == SCIP_BOUNDTYPE_UPPER || SCIPsetIsLE(set, relaxedbds[v], SCIPbdchginfoGetNewbound(bdchginfos[v])));
2248 SCIP_Bool* redundant /**< did we found a global reduction on a conflict set variable, which makes this conflict redundant */
2277 /* due to other conflict in the same conflict analysis, this conflict set might have become redundant */
2298 /* due to multiple conflict sets for one conflict, it can happen, that we already have redundant information in the
2315 SCIPsetDebugMsg(set, "remove redundant variable <%s> from conflict set\n", SCIPvarGetName(var));
2327 SCIPsetDebugMsg(set, "trivially removed %d redundant of %d variables from conflictset (%p)\n", ntrivialredvars, conflictset->nbdchginfos, (void*)conflictset);
2330 /* all variables where removed, the conflict cannot be fulfilled, i.e., we have an infeasibility proof */
2335 if( conflictset->nbdchginfos > set->conf_maxvarsdetectimpliedbounds || conflictset->nbdchginfos == 1 )
2359 assert(SCIPbdchginfoGetBoundtype(bdchginfos[v]) == SCIP_BOUNDTYPE_LOWER || SCIPsetIsGE(set, relaxedbds[v], SCIPbdchginfoGetNewbound(bdchginfos[v])));
2360 assert(SCIPbdchginfoGetBoundtype(bdchginfos[v]) == SCIP_BOUNDTYPE_UPPER || SCIPsetIsLE(set, relaxedbds[v], SCIPbdchginfoGetNewbound(bdchginfos[v])));
2362 /* for continuous variables, we can only use the relaxed version of the bounds negation: !(x <= u) -> x >= u */
2388 /* the literal is satisfied in global bounds (may happen due to weak "negation" of continuous variables)
2403 if( v == nbdchginfos && ((!set->conf_fullshortenconflict && nzeroimpls < 2) || (set->conf_fullshortenconflict && nzeroimpls < nbdchginfos)) )
2412 SCIPsetDebugMsg(set, "checking for global reductions and redundant conflict variables(in %s) on conflict:\n", SCIPprobGetName(prob));
2416 SCIPsetDebugMsgPrint(set, "%s %s %g", SCIPvarGetName(SCIPbdchginfoGetVar(bdchginfos[v])), (!boundtypes[v]) ? ">=" : "<=", bounds[v]);
2429 SCIP_CALL( SCIPshrinkDisjunctiveVarSet(set->scip, vars, bounds, boundtypes, redundants, nbdchginfos, nredvars, \
2444 SCIPsetDebugMsg(set, "conflict set (%p) led to %d global bound reductions\n", (void*) conflictset, *nbdchgs);
2451 SCIPsetDebugMsg(set, "conflict set (%p) is redundant because at least one global reduction, fulfills the conflict constraint\n", (void*)conflictset);
2467 SCIPsetDebugMsg(set, "remove redundant variable <%s> from conflict set\n", SCIPvarGetName(SCIPbdchginfoGetVar(bdchginfos[v])));
2481 SCIPsetDebugMsg(set, "removed %d redundant of %d variables from conflictset (%p)\n", (*nredvars), conflictset->nbdchginfos, (void*)conflictset);
2508 * in this case we need to create and add a constraint of size one such that propagating this constraint will
2553 || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsGE(set, newbound, SCIPvarGetUbGlobal(var)))) )
2561 || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, newbound, SCIPvarGetLbGlobal(var)))) )
2563 SCIPsetDebugMsg(set, "detected global infeasibility at var <%s>: locdom=[%g,%g] glbdom=[%g,%g] new %s bound=%g\n",
2567 SCIP_CALL( SCIPnodeCutoff(tree->path[0], set, stat, tree, transprob, origprob, reopt, lp, blkmem) );
2579 SCIPvarGetName(var), varGetChar(var), boundtype == SCIP_BOUNDTYPE_UPPER ? "<=" : ">=", newbound,
2621 SCIP_CALL( SCIPnodeAddBoundchg(tree->path[0], blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, \
2666 SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables (or NULL for global bounds) */
2667 SCIP_Real* curvarubs, /**< current upper bounds of active problem variables (or NULL for global bounds) */
2668 SCIP_Bool* infdelta /**< pointer to store whether at least one variable contributes with an infinite value */
2737 SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables (or NULL for global bounds) */
2738 SCIP_Real* curvarubs /**< current upper bounds of active problem variables (or NULL for global bounds) */
2803 SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables (or NULL for global bounds) */
2804 SCIP_Real* curvarubs /**< current upper bounds of active problem variables (or NULL for global bounds) */
2932 SCIP_CALL( tightenSingleVar(conflict, set, stat, tree, blkmem, origprob, transprob, reopt, lp, branchcand, \
2950 SCIP_CALL( tightenSingleVar(conflict, set, stat, tree, blkmem, origprob, transprob, reopt, lp, branchcand, \
2954 /* the minimal activity should stay unchanged because we tightened the bound that doesn't contribute to the
2957 assert(SCIPsetIsEQ(set, minact, getMinActivity(set, transprob, coefs, inds, nnz, NULL, NULL)));
3037 SCIPsetDebugMsg(set, "detect global infeasibility: minactivity=%g, rhs=%g\n", globalminactivity, rhs);
3039 SCIP_CALL( SCIPnodeCutoff(tree->path[proofset->validdepth], set, stat, tree, transprob, origprob, reopt, lp, blkmem) );
3059 fillin += SCIPconflictstoreGetNDualInfProofs(conflictstore) * SCIPconflictstoreGetAvgNnzDualInfProofs(conflictstore);
3065 assert(conflicttype == SCIP_CONFTYPE_BNDEXCEEDING || conflicttype == SCIP_CONFTYPE_ALTBNDPROOF);
3067 fillin += SCIPconflictstoreGetNDualBndProofs(conflictstore) * SCIPconflictstoreGetAvgNnzDualBndProofs(conflictstore);
3080 SCIP_CALL( propagateLongProof(conflict, set, stat, reopt, tree, blkmem, origprob, transprob, lp, branchcand,
3086 /* check if conflict contains variables that are invalid after a restart to label it appropriately */
3101 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "dualproof_inf_%" SCIP_LONGINT_FORMAT, conflict->ndualproofsinfsuccess);
3102 else if( conflicttype == SCIP_CONFTYPE_BNDEXCEEDING || conflicttype == SCIP_CONFTYPE_ALTBNDPROOF )
3103 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "dualproof_bnd_%" SCIP_LONGINT_FORMAT, conflict->ndualproofsbndsuccess);
3107 SCIP_CALL( SCIPcreateConsLinear(set->scip, &cons, name, 0, NULL, NULL, -SCIPsetInfinity(set), rhs,
3121 /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
3142 SCIP_CALL( SCIPconflictstoreAddDualraycons(conflictstore, cons, blkmem, set, stat, transprob, reopt, hasrelaxvar) );
3149 /* In some cases the constraint could not be updated to a more special type. However, it is possible that
3150 * constraint got scaled. Therefore, we need to be very careful when updating the lhs/rhs after the incumbent
3196 SCIP_CALL( SCIPconflictstoreAddDualsolcons(conflictstore, cons, blkmem, set, stat, transprob, reopt, scale, updateside, hasrelaxvar) );
3209 SCIPsetDebugMsg(set, "added proof-constraint to node %p (#%lld) in depth %d (nproofconss %d)\n",
3213 ? SCIPconflictstoreGetNDualInfProofs(conflictstore) : SCIPconflictstoreGetNDualBndProofs(conflictstore));
3231 assert(conflicttype == SCIP_CONFTYPE_BNDEXCEEDING || conflicttype == SCIP_CONFTYPE_ALTBNDPROOF);
3265 /* only one variable has a coefficient different to zero, we add this bound change instead of a constraint */
3279 SCIP_CALL( tightenSingleVar(conflict, set, stat, tree, blkmem, origprob, transprob, reopt, lp, \
3280 branchcand, eventqueue, cliquetable, vars[inds[0]], coefs[0], rhs, conflict->proofset->conflicttype,
3291 if( set->conf_prefinfproof && proofsetGetConftype(conflict->proofset) == SCIP_CONFTYPE_BNDEXCEEDING )
3308 SCIP_CALL( createAndAddProofcons(conflict, conflictstore, conflict->proofset, set, stat, origprob, transprob, \
3326 /* only one variable has a coefficient different to zero, we add this bound change instead of a constraint */
3347 SCIP_CALL( createAndAddProofcons(conflict, conflictstore, conflict->proofsets[i], set, stat, origprob, \
3395 /* try to derive global bound changes and shorten the conflictset by using implication and clique and variable bound
3408 SCIP_CALL( SCIPdebugCheckConflict(blkmem, set, tree->root, conflictset->bdchginfos, conflictset->relaxedbds, conflictset->nbdchginfos) );
3413 SCIP_CALL( detectImpliedBounds(set, transprob, conflictset, &nbdchgs, &nredvars, &redundant) );
3423 SCIP_CALL( SCIPdebugCheckConflict(blkmem, set, tree->root, conflictset->bdchginfos, conflictset->relaxedbds, conflictset->nbdchginfos) ); /*lint !e506 !e774*/
3427 SCIPsetDebugMsg(set, " -> conflict set removed %d redundant variables (old nvars %d, new nvars = %d)\n", nredvars, oldnbdchginfos, conflictset->nbdchginfos);
3428 SCIPsetDebugMsg(set, " -> conflict set led to %d global bound changes %s(cdpt:%d, fdpt:%d, confdpt:%d, len:%d):\n",
3429 nbdchgs, redundant ? "(conflict became redundant) " : "", SCIPtreeGetCurrentDepth(tree), SCIPtreeGetFocusDepth(tree),
3445 /* in case the conflict set contains only one bound change which is globally valid we apply that bound change
3446 * directly (except if we are in strong branching or diving - in this case a bound change would yield an unflushed LP
3449 * @note A bound change can only be applied if it is are related to the active node or if is a global bound
3450 * change. Bound changes which are related to any other node cannot be handled at point due to the internal
3465 /* for continuous variables, we can only use the relaxed version of the bounds negation: !(x <= u) -> x >= u */
3475 SCIP_CALL( SCIPnodeAddBoundchg(tree->path[conflictset->validdepth], blkmem, set, stat, transprob, origprob, tree,
3495 conflictset->nbdchginfos, conflictset->conflicttype, conflictset->usescutoffbound, *success, &result) );
3502 SCIPsetDebugMsg(set, " -> call conflict handler <%s> (prio=%d) to create conflict set with %d bounds returned result %d\n",
3503 SCIPconflicthdlrGetName(set->conflicthdlrs[h]), SCIPconflicthdlrGetPriority(set->conflicthdlrs[h]),
3511 /** adds the collected conflict constraints to the corresponding nodes; the best set->conf_maxconss conflict constraints
3512 * are added to the node of their validdepth; additionally (if not yet added, and if repropagation is activated), the
3513 * conflict constraint that triggers the earliest repropagation is added to the node of its validdepth
3551 /* calculate the maximal number of conflict sets to accept, and the maximal size of each accepted conflict set */
3562 SCIPsetDebugMsg(set, "flushing %d conflict sets at focus depth %d (maxconflictsets: %d, maxsize: %d)\n",
3583 assert(conflictset->repropdepth <= currentdepth || conflictset->repropdepth == INT_MAX); /* INT_MAX for dive/probing/strong */
3584 assert(conflictset->conflictdepth <= currentdepth || conflictset->conflictdepth == INT_MAX); /* INT_MAX for dive/probing/strong */
3594 /* if no conflict bounds exist, the node and its sub tree in the conflict set's valid depth can be
3602 SCIP_CALL( SCIPnodeCutoff(tree->path[conflictset->validdepth], set, stat, tree, transprob, origprob, reopt, lp, blkmem) );
3607 /* if the conflict set is too long, use the conflict set only if it decreases the repropagation depth */
3610 SCIPsetDebugMsg(set, " -> conflict set is too long: %d > %d literals\n", conflictset->nbdchginfos, maxsize);
3611 if( set->conf_keepreprop && conflictset->repropagate && conflictset->repropdepth < repropdepth )
3622 SCIP_CALL( conflictAddConflictCons(conflict, blkmem, set, stat, transprob, origprob, tree, reopt, lp, \
3625 /* if no conflict bounds exist, the node and its sub tree in the conflict set's valid depth can be
3635 SCIP_CALL( SCIPnodeCutoff(tree->path[conflictset->validdepth], set, stat, tree, transprob, origprob, \
3643 SCIPsetDebugMsg(set, " -> conflict set %d/%d added (cdpt:%d, fdpt:%d, insert:%d, valid:%d, conf:%d, reprop:%d, len:%d):\n",
3644 nconflictsetsused+1, maxconflictsets, SCIPtreeGetCurrentDepth(tree), SCIPtreeGetFocusDepth(tree),
3645 conflictset->insertdepth, conflictset->validdepth, conflictset->conflictdepth, conflictset->repropdepth,
3659 /* reactivate propagation on the first node where one of the new conflict sets trigger a deduction */
3665 /* if the conflict constraint of smallest repropagation depth was not yet added, insert it now */
3673 SCIP_CALL( conflictAddConflictCons(conflict, blkmem, set, stat, transprob, origprob, tree, reopt, lp, \
3676 /* if no conflict bounds exist, the node and its sub tree in the conflict set's valid depth can be
3683 SCIPsetDebugMsg(set, " -> empty reprop conflict set in depth %d cuts off sub tree at depth %d\n",
3686 SCIP_CALL( SCIPnodeCutoff(tree->path[repropconflictset->validdepth], set, stat, tree, transprob, \
3693 SCIPsetDebugMsg(set, " -> additional reprop conflict set added (cdpt:%d, fdpt:%d, insert:%d, valid:%d, conf:%d, reprop:%d, len:%d):\n",
3695 repropconflictset->insertdepth, repropconflictset->validdepth, repropconflictset->conflictdepth,
3705 SCIPsetDebugMsg(set, "marked node %p in depth %d to be repropagated due to conflicts found in depth %d\n",
3743 /** returns the total number of literals in conflict constraints that were added to the problem */
3763 /** returns the total number of conflict constraints that were added globally to the problem */
3773 /** returns the total number of literals in conflict constraints that were added globally to the problem */
3803 /** returns the total number of literals in conflict constraints that were added locally to the problem */
3820 /** returns whether bound change has a valid reason that can be resolved in conflict analysis */
3853 if( !SCIPbdchgidxIsEarlierNonNull(SCIPbdchginfoGetIdx(bdchginfo1), SCIPbdchginfoGetIdx(bdchginfo2)) )
3859 /** return TRUE if conflict analysis is applicable; In case the function return FALSE there is no need to initialize the
3898 SCIP_CALL( SCIPpqueueCreate(&(*conflict)->bdchgqueue, set->mem_arraygrowinit, set->mem_arraygrowfac,
3900 SCIP_CALL( SCIPpqueueCreate(&(*conflict)->forcedbdchgqueue, set->mem_arraygrowinit, set->mem_arraygrowfac,
4043 /* increase the conflict counter, such that binary variables of new conflict set and new conflict queue are labeled
4047 if( conflict->count == 0 ) /* make sure, 0 is not a valid conflict counter (may happen due to integer overflow) */
4057 /* if the conflict score for the next conflict exceeds 1000.0, rescale all history conflict scores */
4081 /** marks bound to be present in the current conflict and returns whether a bound which is at least as tight was already
4107 /* the variable is already member of the conflict; hence check if the new bound is redundant */
4110 SCIPsetDebugMsg(set, "ignoring redundant bound change <%s> >= %g since a stronger lower bound exist <%s> >= %g\n",
4116 SCIPsetDebugMsg(set, "ignoring redundant bound change <%s> >= %g since this lower bound is already present\n", SCIPvarGetName(var), newbound);
4126 /* remember the lower bound and relaxed bound to allow only better/tighter lower bounds for that variables
4138 /* the variable is already member of the conflict; hence check if the new bound is redundant */
4141 SCIPsetDebugMsg(set, "ignoring redundant bound change <%s> <= %g since a stronger upper bound exist <%s> <= %g\n",
4147 SCIPsetDebugMsg(set, "ignoring redundant bound change <%s> <= %g since this upper bound is already present\n", SCIPvarGetName(var), newbound);
4157 /* remember the upper bound and relaxed bound to allow only better/tighter upper bounds for that variables
4186 assert(SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER || SCIPsetIsGE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
4187 assert(SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_UPPER || SCIPsetIsLE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
4189 SCIPsetDebugMsg(set, "putting bound change <%s> %s %g(%g) at depth %d to current conflict set\n",
4191 SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", SCIPbdchginfoGetNewbound(bdchginfo),
4194 /* mark the bound to be member of the conflict and check if a bound which is at least as tight is already member of
4215 /** returns whether the negation of the given bound change would lead to a globally valid literal */
4231 && ((boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGE(set, bound, SCIPvarGetUbGlobal(var)))
4232 || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLE(set, bound, SCIPvarGetLbGlobal(var)))));
4250 assert(SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER || SCIPsetIsGE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
4251 assert(SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_UPPER || SCIPsetIsLE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
4253 /* mark the bound to be member of the conflict and check if a bound which is at least as tight is already member of
4286 SCIP_BOUNDTYPE* boundtype, /**< pointer to type of bound that was changed: lower or upper bound */
4333 SCIPsetDebugMsg(set, " -> adding bound <%s> %s %.15g(%.15g) [status:%d, type:%d, depth:%d, pos:%d, reason:<%s>, info:%d] to candidates\n",
4342 : (SCIPbdchginfoGetInferProp(bdchginfo) != NULL ? SCIPpropGetName(SCIPbdchginfoGetInferProp(bdchginfo))
4344 SCIPbdchginfoGetChgtype(bdchginfo) != SCIP_BOUNDCHGTYPE_BRANCHING ? SCIPbdchginfoGetInferInfo(bdchginfo) : -1);
4347 * we even put bound changes without inference information on the queue in order to automatically
4356 assert(boundtype == SCIP_BOUNDTYPE_LOWER ? SCIPsetIsLE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)) : SCIPsetIsGE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
4359 assert(boundtype == SCIP_BOUNDTYPE_LOWER ? SCIPsetIsGT(set, relaxedbd, SCIPbdchginfoGetOldbound(bdchginfo)) : SCIPsetIsLT(set, relaxedbd, SCIPbdchginfoGetOldbound(bdchginfo)));
4368 SCIP_CALL( incVSIDS(var, blkmem, set, stat, boundtype, relaxedbd, set->conf_conflictgraphweight) );
4381 SCIP_BDCHGIDX* bdchgidx /**< bound change index (time stamp of bound change), or NULL for current time */
4421 /* if bound of variable was not changed (this means it is still the global bound), we can ignore the conflicting
4429 SCIP_CALL( conflictAddBound(conflict, blkmem, set, stat, var, boundtype, bdchginfo, SCIPbdchginfoGetNewbound(bdchginfo)) );
4442 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4465 SCIPsetDebugMsg(set, "ignoring relaxed bound information since variable <%s> is multi-aggregated active\n", SCIPvarGetName(var));
4477 /* if bound of variable was not changed (this means it is still the global bound), we can ignore the conflicting
4486 /* get the position of the bound change information within the bound change array of the variable */
4490 /* if the relaxed bound should be ignored, set the relaxed bound to the bound given by the bdchgidx; that ensures
4504 /* due to numericis we compare the relaxed lower bound to the one present at the particular time point and take
4510 /* check if relaxed lower bound is smaller or equal to global lower bound; if so we can ignore the conflicting
4520 /* check if the old lower bound is greater than or equal to relaxed lower bound; if not we found the bound
4528 SCIPsetDebugMsg(set, "lower bound change %d oldbd=%.15g, newbd=%.15g, depth=%d, pos=%d, redundant=%u\n",
4533 /* if bound change is redundant (this means it now a global bound), we can ignore the conflicting bound */
4550 /* due to numericis we compare the relaxed upper bound to the one present at the particular time point and take
4556 /* check if relaxed upper bound is greater or equal to global upper bound; if so we can ignore the conflicting
4566 /* check if the old upper bound is smaller than or equal to the relaxed upper bound; if not we found the
4574 SCIPsetDebugMsg(set, "upper bound change %d oldbd=%.15g, newbd=%.15g, depth=%d, pos=%d, redundant=%u\n",
4579 /* if bound change is redundant (this means it now a global bound), we can ignore the conflicting bound */
4591 SCIP_CALL( conflictAddBound(conflict, blkmem, set, stat, var, boundtype, bdchginfo, relaxedbd) );
4596 /** checks if the given variable is already part of the current conflict set or queued for resolving with the same or
4604 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4613 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED || SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR )
4628 SCIPsetDebugMsg(set, "already queued bound change <%s> >= %g\n", SCIPvarGetName(var), newbound);
4640 SCIPsetDebugMsg(set, "already queued bound change <%s> <= %g\n", SCIPvarGetName(var), newbound);
4656 /** returns the conflict lower bound if the variable is present in the current conflict set; otherwise the global lower
4673 /** returns the conflict upper bound if the variable is present in the current conflict set; otherwise the global upper
4711 /* mark the bound change to be no longer in the conflict (it will be either added again to the conflict set or
4752 SCIPdebugMessage("bound change info [%d:<%s> %s %g] is invaild -> pop it from the force queue\n", SCIPbdchginfoGetDepth(bdchginfo),
4771 SCIPdebugMessage("bound change info [%d:<%s> %s %g] is invaild -> pop it from the queue\n", SCIPbdchginfoGetDepth(bdchginfo),
4788 /** adds the current conflict set (extended by all remaining bound changes in the queue) to the pool of conflict sets */
4830 assert(0 <= conflict->conflictset->validdepth && conflict->conflictset->validdepth <= currentdepth);
4837 /* create a copy of the current conflict set, allocating memory for the additional elements of the queue */
4843 SCIPsetDebugMsg(set, "adding %d variables from the queue as temporary conflict variables\n", nbdchginfos);
4844 SCIP_CALL( conflictsetAddBounds(conflict, conflictset, blkmem, set, bdchginfos, nbdchginfos) );
4848 assert(conflictset->validdepth <= conflictset->insertdepth && conflictset->insertdepth <= currentdepth);
4849 SCIPsetDebugMsg(set, " -> conflict with %d literals found at depth %d is active in depth %d and valid in depth %d\n",
4855 if( (diving || conflictset->insertdepth < currentdepth) && conflictset->insertdepth <= focusdepth )
4857 /* if the conflict should not be located only in the subtree where it is useful, put it to its valid depth level */
4866 conflictset->bdchginfos, conflictset->relaxedbds, conflictset->nbdchginfos) ); /*lint !e506 !e774*/
4883 * current minimal valid depth level, because this depth level is the topmost level to add the conflict
4927 SCIPsetDebugMsg(set, "processing next conflicting bound (depth: %d, valid depth: %d, bdchgtype: %s [%s], vartype: %d): [<%s> %s %g(%g)]\n",
4943 SCIPsetDebugMsgPrint(set, " [%d:<%s> %s %g(%g)]", SCIPbdchginfoGetDepth(conflict->conflictset->bdchginfos[i]),
4945 SCIPbdchginfoGetBoundtype(conflict->conflictset->bdchginfos[i]) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
4946 SCIPbdchginfoGetNewbound(conflict->conflictset->bdchginfos[i]), conflict->conflictset->relaxedbds[i]);
4954 SCIPsetDebugMsgPrint(set, " [%d:<%s> %s %g(%g)]", SCIPbdchginfoGetDepth(info), SCIPvarGetName(SCIPbdchginfoGetVar(info)),
4955 bdchginfoIsInvalid(conflict, info) ? "<!>" : SCIPbdchginfoGetBoundtype(info) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
4964 SCIPsetDebugMsgPrint(set, " [%d:<%s> %s %g(%g)]", SCIPbdchginfoGetDepth(info), SCIPvarGetName(SCIPbdchginfoGetVar(info)),
4965 bdchginfoIsInvalid(conflict, info) ? "<!>" : SCIPbdchginfoGetBoundtype(info) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
4974 * current minimal valid depth level (which is initialized with the valid depth level of the initial
4975 * conflict set), because this depth level is the topmost level to add the conflict constraint to anyways
4990 /* resolve bound change by asking the constraint that infered the bound to put all bounds that were
4999 SCIPsetDebugMsg(set, "resolving bound <%s> %s %g(%g) [status:%d, type:%d, depth:%d, pos:%d]: <%s> %s %g [cons:<%s>(%s), info:%d]\n",
5012 /* in case the inference variables is not an active variables, we need to transform the relaxed bound */
5021 || (SCIPvarGetStatus(infervar) == SCIP_VARSTATUS_MULTAGGR && SCIPvarGetMultaggrNVars(infervar) == 1));
5036 SCIP_CALL( SCIPconsResolvePropagation(infercons, set, infervar, inferinfo, inferboundtype, bdchgidx, relaxedbd, &result) );
5050 /* resolve bound change by asking the propagator that infered the bound to put all bounds that were
5059 SCIPsetDebugMsg(set, "resolving bound <%s> %s %g(%g) [status:%d, depth:%d, pos:%d]: <%s> %s %g [prop:<%s>, info:%d]\n",
5069 SCIP_CALL( SCIPpropResolvePropagation(inferprop, set, infervar, inferinfo, inferboundtype, bdchgidx, relaxedbd, &result) );
5090 /* in case the bound change was not resolved, the conflict queues should have the same size (contents) */
5097 /** if only one conflicting bound change of the last depth level was used, and if this can be resolved,
5098 * creates GRASP-like reconvergence conflict constraints in the conflict graph up to the branching variable of this
5113 int* nreconvliterals /**< pointer to store the number of literals generated reconvergence constraints */
5135 /* check, whether local constraints are allowed; however, don't generate reconvergence constraints that are only valid
5147 /* for each succeeding UIP pair of the last depth level, create one reconvergence constraint */
5149 while( uip != NULL && SCIPbdchginfoGetDepth(uip) == SCIPbdchginfoGetDepth(firstuip) && bdchginfoIsResolvable(uip) )
5161 SCIPsetDebugMsg(set, "creating reconvergence constraint for UIP <%s> %s %g in depth %d pos %d\n",
5162 SCIPvarGetName(SCIPbdchginfoGetVar(uip)), SCIPbdchginfoGetBoundtype(uip) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
5173 * for reconvergence constraints for continuous variables we can only use the "negation" !(x <= u) == (x >= u);
5174 * during conflict analysis, we treat a continuous bound "x >= u" in the conflict set as "x > u", and in the
5186 oppositeuipboundtype == SCIP_BOUNDTYPE_LOWER ? SCIP_REAL_MIN : SCIP_REAL_MAX, oppositeuipbound, &oppositeuip) );
5208 /* remove currently processed candidate and get next conflicting bound from the conflict candidate queue before
5209 * we remove the candidate we have to collect the relaxed bound since removing the candidate from the queue
5219 assert(nextbdchginfo == NULL || SCIPbdchginfoGetDepth(bdchginfo) >= SCIPbdchginfoGetDepth(nextbdchginfo)
5223 /* bound changes that are higher in the tree than the valid depth of the conflict can be ignored;
5267 assert(conflict->conflictset->nbdchginfos >= 1); /* starting UIP is already member of the conflict set */
5269 /* if this is the first variable of the conflict set besides the current starting UIP, it is the next
5286 /* get next conflicting bound from the conflict candidate queue (this does not need to be nextbdchginfo, because
5294 /* if only one propagation was resolved, the reconvergence constraint is already member of the constraint set
5307 conflict->conflictset->nbdchginfos, conflict->bdchgqueue, conflict->forcedbdchgqueue) ); /*lint !e506 !e774*/
5309 SCIPsetDebugMsg(set, "creating reconvergence constraint from UIP <%s> to UIP <%s> in depth %d with %d literals after %d resolutions\n",
5314 SCIP_CALL( conflictAddConflictset(conflict, blkmem, set, stat, tree, validdepth, diving, FALSE, &success, &nlits) );
5322 /* clear the conflict candidate queue and the conflict set (to make sure, oppositeuip is not referenced anymore) */
5334 /** analyzes conflicting bound changes that were added with calls to SCIPconflictAddBound() and
5335 * SCIPconflictAddRelaxedBound(), and on success, calls the conflict handlers to create a conflict constraint out of
5348 SCIP_Bool mustresolve, /**< should the conflict set only be used, if a resolution was applied? */
5350 int* nliterals, /**< pointer to store the number of literals in generated conflict constraints */
5352 int* nreconvliterals /**< pointer to store the number of literals generated reconvergence constraints */
5387 /* if we must resolve at least one bound change, find the first UIP at least in the last depth level */
5391 SCIPsetDebugMsg(set, "analyzing conflict with %d+%d conflict candidates and starting conflict set of size %d in depth %d (resolvedepth=%d)\n",
5400 /* check, whether local conflicts are allowed; however, don't generate conflict constraints that are only valid in the
5407 /* allocate temporary memory for storing first UIPs (in each depth level, at most two bound changes can be flagged
5421 NULL, conflict->conflictset->bdchginfos, conflict->conflictset->relaxedbds, conflict->conflictset->nbdchginfos, \
5443 assert(SCIPbdchginfoGetPos(bdchginfo) < (int)tree->path[bdchgdepth]->domchg->domchgbound.nboundchgs);
5444 assert(tree->path[bdchgdepth]->domchg->domchgbound.boundchgs[SCIPbdchginfoGetPos(bdchginfo)].var
5446 assert(tree->path[bdchgdepth]->domchg->domchgbound.boundchgs[SCIPbdchginfoGetPos(bdchginfo)].newbound
5449 ? SCIPvarGetLbGlobal(SCIPbdchginfoGetVar(bdchginfo)) : SCIPvarGetUbGlobal(SCIPbdchginfoGetVar(bdchginfo)))
5451 assert((SCIP_BOUNDTYPE)tree->path[bdchgdepth]->domchg->domchgbound.boundchgs[SCIPbdchginfoGetPos(bdchginfo)].boundtype
5459 lastconsresoldepth = bdchgdepth; /* all intermediate depth levels consisted of only unresolved bound changes */
5460 else if( bdchgdepth < lastconsresoldepth && (set->conf_interconss == -1 || *nconss < set->conf_interconss) )
5466 SCIPsetDebugMsg(set, "creating intermediate conflictset after %d resolutions up to depth %d (valid at depth %d): %d conflict bounds, %d bounds in queue\n",
5470 SCIP_CALL( conflictAddConflictset(conflict, blkmem, set, stat, tree, validdepth, diving, TRUE, &success, &nlits) );
5481 /* remove currently processed candidate and get next conflicting bound from the conflict candidate queue before
5482 * we remove the candidate we have to collect the relaxed bound since removing the candidate from the queue
5491 assert(nextbdchginfo == NULL || SCIPbdchginfoGetDepth(bdchginfo) >= SCIPbdchginfoGetDepth(nextbdchginfo)