All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
tree.c
Go to the documentation of this file.
23 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
49 #define MAXDEPTH 65535 /**< maximal depth level for nodes; must correspond to node data structure */
50 #define MAXREPROPMARK 511 /**< maximal subtree repropagation marker; must correspond to node data structure */
165 SCIPdebugMessage("captured LPI state of fork %p %d times -> new nlpistateref=%d\n", (void*)fork, nuses, fork->nlpistateref);
187 SCIPdebugMessage("released LPI state of fork %p -> new nlpistateref=%d\n", (void*)fork, fork->nlpistateref);
227 SCIPdebugMessage("released LPI state of subroot %p -> new nlpistateref=%d\n", (void*)subroot, subroot->nlpistateref);
240 SCIPdebugMessage("capture %d times LPI state of node #%"SCIP_LONGINT_FORMAT" at depth %d (current: %d)\n",
242 SCIPnodeGetType(node) == SCIP_NODETYPE_FORK ? node->data.fork->nlpistateref : node->data.subroot->nlpistateref);
269 SCIPdebugMessage("release LPI state of node #%"SCIP_LONGINT_FORMAT" at depth %d (current: %d)\n",
271 SCIPnodeGetType(node) == SCIP_NODETYPE_FORK ? node->data.fork->nlpistateref : node->data.subroot->nlpistateref);
302 SCIPdebugMessage("created probingnode information (%d cols, %d rows)\n", (*probingnode)->ncols, (*probingnode)->nrows);
339 SCIPdebugMessage("updated probingnode information (%d cols, %d rows)\n", probingnode->ncols, probingnode->nrows);
414 SCIPdebugMessage("creating pseudofork information with %d children (%d new cols, %d new rows)\n",
420 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*pseudofork)->addedcols, SCIPlpGetNewcols(lp),
428 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*pseudofork)->addedrows, SCIPlpGetNewrows(lp),
517 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*fork)->addedcols, SCIPlpGetNewcols(lp), (*fork)->naddedcols) );
524 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*fork)->addedrows, SCIPlpGetNewrows(lp), (*fork)->naddedrows) );
607 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*subroot)->cols, SCIPlpGetCols(lp), (*subroot)->ncols) );
613 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*subroot)->rows, SCIPlpGetRows(lp), (*subroot)->nrows) );
674 assert(sibling->data.sibling.arraypos >= 0 && sibling->data.sibling.arraypos < tree->nsiblings);
737 /** makes node a child of the given parent node, which must be the focus node; if the child is a probing node,
752 assert(SCIPnodeGetType(node) == SCIP_NODETYPE_CHILD || SCIPnodeGetType(node) == SCIP_NODETYPE_PROBINGNODE);
781 SCIPdebugMessage("assigning parent #%"SCIP_LONGINT_FORMAT" to node #%"SCIP_LONGINT_FORMAT" at depth %d\n",
782 parent != NULL ? SCIPnodeGetNumber(parent) : -1, SCIPnodeGetNumber(node), SCIPnodeGetDepth(node));
812 SCIPdebugMessage("releasing parent-child relationship of node #%"SCIP_LONGINT_FORMAT" at depth %d of type %d with parent #%"SCIP_LONGINT_FORMAT" of type %d\n",
828 assert(SCIPnodeGetType(node) == SCIP_NODETYPE_CHILD || SCIPnodeGetType(node) == SCIP_NODETYPE_PROBINGNODE
853 freeParent = (parent->data.junction.nchildren == 0); /* free parent if it has no more children */
860 freeParent = (parent->data.pseudofork->nchildren == 0); /* free parent if it has no more children */
874 freeParent = (parent->data.subroot->nchildren == 0); /* free parent if it has no more children */
878 /* the only possible child a refocused node can have in its refocus state is the probing root node;
879 * we don't want to free the refocused node, because we first have to convert it back to its original
901 SCIPdebugMessage("unlinked node #%"SCIP_LONGINT_FORMAT" in depth %d -> new effective root depth: %d\n",
943 SCIP_Real estimate /**< estimate for (transformed) objective value of best feasible solution in subtree */
1062 /* release special root LPI state capture which is used to keep the root LPI state over the whole solving
1124 SCIPdebugMessage("cutting off %s node #%"SCIP_LONGINT_FORMAT" at depth %d (cutoffdepth: %d)\n",
1125 node->active ? "active" : "inactive", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), tree->cutoffdepth);
1128 /** marks node, that propagation should be applied again the next time, a node of its subtree is focused */
1149 SCIPdebugMessage("marked %s node #%"SCIP_LONGINT_FORMAT" at depth %d to be propagated again (repropdepth: %d)\n",
1150 node->active ? "active" : "inactive", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), tree->repropdepth);
1167 /* if the node was the highest repropagation node in the path, update the repropdepth in the tree data */
1247 SCIP_CALL( SCIPeventqueueProcess(eventqueue, blkmem, set, primal, lp, branchcand, eventfilter) );
1276 SCIP_CALL( SCIPpropagateDomains(blkmem, set, stat, transprob, origprob, primal, tree, lp, branchcand, eventqueue, conflict,
1295 SCIPdebugMessage("repropagation %"SCIP_LONGINT_FORMAT" at depth %u changed %"SCIP_LONGINT_FORMAT" bounds (total reprop bound changes: %"SCIP_LONGINT_FORMAT"), cutoff: %u\n",
1296 stat->nreprops, node->depth, stat->nboundchgs - oldnboundchgs, stat->nrepropboundchgs, *cutoff);
1298 /* if a propagation marked with the reprop flag was successful, we want to repropagate the whole subtree */
1299 /**@todo because repropsubtree is only a bit flag, we cannot mark a whole subtree a second time for
1307 SCIPdebugMessage("initial repropagation at depth %u changed %"SCIP_LONGINT_FORMAT" bounds -> repropagating subtree (new mark: %d)\n",
1309 assert((int)(node->repropsubtreemark) == tree->repropsubtreecount); /* bitfield must be large enough */
1343 /** informs node, that it is now on the active path and applies any domain and constraint set changes */
1369 SCIPdebugMessage("activate node #%"SCIP_LONGINT_FORMAT" at depth %d of type %d (reprop subtree mark: %u)\n",
1370 SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), SCIPnodeGetType(node), node->repropsubtreemark);
1375 SCIP_CALL( SCIPdomchgApply(node->domchg, blkmem, set, stat, lp, branchcand, eventqueue, node->depth, cutoff) );
1384 /* try to repropagate the node to see, if the propagation also leads to a conflict and a conflict constraint
1385 * could be generated; if propagation conflict analysis is turned off, repropagating the node makes no
1394 /* propagate node again, if the reprop flag is set; in the new focus node, no repropagation is necessary, because
1398 && (node->reprop || (node->parent != NULL && node->repropsubtreemark != node->parent->repropsubtreemark)) )
1402 SCIP_CALL( nodeRepropagate(node, blkmem, set, stat, transprob, origprob, primal, tree, lp, branchcand, conflict,
1410 /** informs node, that it is no longer on the active path and undoes any domain and constraint set changes */
1430 SCIPdebugMessage("deactivate node #%"SCIP_LONGINT_FORMAT" at depth %d of type %d (reprop subtree mark: %u)\n",
1431 SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), SCIPnodeGetType(node), node->repropsubtreemark);
1481 /** adds constraint locally to the node and captures it; activates constraint, if node is active;
1482 * if a local constraint is added to the root node, it is automatically upgraded into a global constraint
1510 /* add constraint addition to the node's constraint set change data, and activate constraint if node is active */
1520 /** locally deletes constraint at the given node by disabling its separation, enforcing, and propagation capabilities
1637 /** adds bound change with inference information to focus node, child of focus node, or probing node;
1681 SCIPdebugMessage("adding boundchange at node at depth %u to variable <%s>: old bounds=[%g,%g], new %s bound: %g (infer%s=<%s>, inferinfo=%d)\n",
1685 infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo);
1687 /* remember variable as inference variable, and get corresponding active variable, bound and bound type */
1695 SCIPerrorMessage("cannot change bounds of multi-aggregated variable <%s>\n", SCIPvarGetName(var));
1699 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
1724 SCIPerrorMessage("cannot change lower bound of variable <%s> to infinity.\n", SCIPvarGetName(var));
1742 SCIPerrorMessage("cannot change upper bound of variable <%s> to minus infinity.\n", SCIPvarGetName(var));
1748 SCIPdebugMessage(" -> transformed to active variable <%s>: old bounds=[%g,%g], new %s bound: %g, obj: %g\n",
1749 SCIPvarGetName(var), oldlb, oldub, boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", newbound,
1752 /* if the bound change takes place at an active node but is conflicting with the current local bounds,
1753 * we cannot apply it immediately because this would introduce inconsistencies to the bound change data structures
1755 * instead we have to remember the bound change as a pending bound change and mark the affected nodes on the active
1770 SCIPdebugMessage(" -> bound change <%s> %s %g violates current local bounds [%g,%g] since depth %d: remember for later application\n",
1775 SCIP_CALL( treeAddPendingBdchg(tree, set, node, var, newbound, boundtype, infercons, inferprop, inferinfo,
1787 /* if we are in probing mode we have to additionally count the bound changes for the probing statistic */
1799 SCIP_CALL( SCIPvarChgBdGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound, boundtype) );
1805 SCIPdebugMessage("marked root node to be repropagated due to global bound change <%s>:[%g,%g] -> [%g,%g] found in depth %u\n",
1828 * - if the last solved LP was the one in the current lpstatefork, the LP value in the columns are still valid
1832 || (tree->focuslpstateforklpcount == stat->lpcount && SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN) )
1839 /* remember the bound change as branching decision (infervar/infercons/inferprop are not important: use NULL) */
1840 SCIP_CALL( SCIPdomchgAddBoundchg(&node->domchg, blkmem, set, var, newbound, boundtype, SCIP_BOUNDCHGTYPE_BRANCHING,
1845 newpseudoobjval = SCIPlpGetModifiedProvedPseudoObjval(lp, set, var, oldbound, newbound, boundtype);
1847 newpseudoobjval = SCIPlpGetModifiedPseudoObjval(lp, set, transprob, var, oldbound, newbound, boundtype);
1853 SCIP_CALL( SCIPdebugCheckInference(blkmem, set, node, var, newbound, boundtype) ); /*lint !e506 !e774*/
1866 assert(node->domchg->domchgdyn.boundchgs[node->domchg->domchgdyn.nboundchgs-1].newbound == newbound); /*lint !e777*/
1873 /**@todo if the node is active, it currently must either be the effective root (see above) or the current node;
1874 * if a bound change to an intermediate active node should be added, we must make sure, the bound change
1875 * information array of the variable stays sorted (new info must be sorted in instead of putting it to
1876 * the end of the array), and we should identify now redundant bound changes that are applied at a
1880 SCIP_CALL( SCIPboundchgApply(&node->domchg->domchgdyn.boundchgs[node->domchg->domchgdyn.nboundchgs-1],
1881 blkmem, set, stat, lp, branchcand, eventqueue, node->depth, node->domchg->domchgdyn.nboundchgs-1, &cutoff) );
1909 SCIP_CALL( SCIPnodeAddBoundinfer(node, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue, var, newbound,
1978 SCIPdebugMessage("adding hole (%g,%g) at node at depth %u to variable <%s>: bounds=[%g,%g], (infer%s=<%s>, inferinfo=%d)\n",
1981 infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo);
1984 /* remember variable as inference variable, and get corresponding active variable, bound and bound type */
1991 SCIPerrorMessage("cannot change bounds of multi-aggregated variable <%s>\n", SCIPvarGetName(var));
1995 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
2002 /* if we are in probing mode we have to additionally count the bound changes for the probing statistic */
2020 SCIPdebugMessage("marked root node to be repropagated due to global added hole <%s>: (%g,%g) found in depth %u\n",
2034 /* if we are in probing mode we have to additionally count the bound changes for the probing statistic */
2103 /* It can happen, that a pending bound change conflicts with the global bounds, because when it was collected, it
2104 * just conflicted with the local bounds, but a conflicting global bound change was applied afterwards. In this
2124 /* ignore bounds that are now redundant (for example, multiple entries in the pendingbdchgs for the same
2153 SCIP_CALL( SCIPnodeAddBoundinfer(tree->pendingbdchgs[i].node, blkmem, set, stat, transprob, origprob, tree, lp, branchcand,
2155 tree->pendingbdchgs[i].infercons, tree->pendingbdchgs[i].inferprop, tree->pendingbdchgs[i].inferinfo,
2157 assert(tree->npendingbdchgs == npendingbdchgs); /* this time, the bound change can be applied! */
2167 /** if given value is larger than the node's lower bound, sets the node's lower bound to the new value */
2192 SCIPstatUpdatePrimalDualIntegral(stat, set, transprob, origprob, SCIPsetInfinity(set), newbound);
2200 /* updating the primal integral is only necessary if dual bound has increased since last evaluation */
2202 SCIPstatUpdatePrimalDualIntegral(stat, set, transprob, origprob, SCIPsetInfinity(set), lowerbound);
2224 /* @todo check for dual feasibility of LP solution and use sub-optimal solution if they are dual feasible */
2273 /** propagates implications of binary fixings at the given node triggered by the implication graph and the clique table */
2298 SCIPdebugMessage("implication graph propagation of node #%"SCIP_LONGINT_FORMAT" in depth %d\n",
2340 /* @note should this be checked here (because SCIPnodeAddBoundinfer fails for multi-aggregated variables)
2371 SCIP_CALL( SCIPnodeAddBoundinfer(node, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
2426 SCIP_CALL( SCIPnodeAddBoundinfer(node, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
2487 || (ncols == node->data.probingnode->ninitialcols && nrows == node->data.probingnode->ninitialrows));
2550 /** finds the common fork node, the new LP state defining fork, and the new focus subroot, if the path is switched to
2561 SCIP_Bool* cutoff /**< pointer to store whether the given node can be cut off and no path switching
2576 assert(tree->focuslpstatefork == NULL || tree->focuslpstatefork->depth <= tree->focuslpfork->depth);
2578 assert(tree->focussubroot == NULL || tree->focussubroot->depth <= tree->focuslpstatefork->depth);
2597 /* if the new focus node is NULL, there is no common fork node, and the new LP fork, LP state fork, and subroot
2614 /* if the old focus node is NULL, there is no common fork node, and we have to search the new LP fork, LP state fork
2626 && SCIPnodeGetType(lpfork) != SCIP_NODETYPE_FORK && SCIPnodeGetType(lpfork) != SCIP_NODETYPE_SUBROOT )
2640 while( SCIPnodeGetType(lpstatefork) != SCIP_NODETYPE_FORK && SCIPnodeGetType(lpstatefork) != SCIP_NODETYPE_SUBROOT )
2680 /* find the common fork node, the new LP defining fork, the new LP state defining fork, and the new focus subroot */
2697 || SCIPnodeGetType(fork) == SCIP_NODETYPE_FORK || SCIPnodeGetType(fork) == SCIP_NODETYPE_SUBROOT) )
2700 && (SCIPnodeGetType(fork) == SCIP_NODETYPE_FORK || SCIPnodeGetType(fork) == SCIP_NODETYPE_SUBROOT) )
2710 /* if the common fork node is below the current cutoff depth, the cutoff node is an ancestor of the common fork
2727 /* if not already found, continue searching the LP defining fork; it cannot be deeper than the common fork */
2732 /* focuslpfork is not on the same active path as the new node: we have to continue searching */
2745 /* focuslpfork is on the same active path as the new node: old and new node have the same lpfork */
2755 SCIPdebugMessage("find switch forks: lpforkdepth=%d\n", lpfork == NULL ? -1 : (int)(lpfork->depth));
2757 /* if not already found, continue searching the LP state defining fork; it cannot be deeper than the
2764 /* focuslpstatefork is not on the same active path as the new node: we have to continue searching */
2779 /* focuslpstatefork is on the same active path as the new node: old and new node have the same lpstatefork */
2789 SCIPdebugMessage("find switch forks: lpstateforkdepth=%d\n", lpstatefork == NULL ? -1 : (int)(lpstatefork->depth));
2791 /* if not already found, continue searching the subroot; it cannot be deeper than the LP defining fork, the
2798 /* focussubroot is not on the same active path as the new node: we have to continue searching */
2818 SCIPdebugMessage("find switch forks: subrootdepth=%d\n", subroot == NULL ? -1 : (int)(subroot->depth));
2820 /* if a node prior to the common fork should be repropagated, we select the node to be repropagated as common
2821 * fork in order to undo all bound changes up to this node, repropagate the node, and redo the bound changes
2848 /** switches the active path to the new focus node, applies domain and constraint set changes */
2869 int forkdepth; /* depth of the common subroot/fork/pseudofork/junction node, or -1 if no common fork exists */
2892 /* undo the domain and constraint set changes of the old active path by deactivating the path's nodes */
2895 SCIP_CALL( nodeDeactivate(tree->path[i], blkmem, set, stat, tree, lp, branchcand, eventqueue) );
2900 SCIP_CALL( treeApplyPendingBdchgs(tree, blkmem, set, stat, transprob, origprob, lp, branchcand, eventqueue) );
2920 SCIP_CALL( nodeRepropagate(fork, blkmem, set, stat, transprob, origprob, primal, tree, lp, branchcand, conflict,
2926 * on the way, domain propagation might be applied again to the path's nodes, which can result in the cutoff of
2936 SCIP_CALL( nodeActivate(tree->path[i], blkmem, set, stat, transprob, origprob, primal, tree, lp, branchcand,
2952 SCIP_CALL( SCIPeventqueueProcess(eventqueue, blkmem, set, primal, lp, branchcand, eventfilter) );
3088 SCIP_CALL( SCIPlpAddRow(lp, blkmem, set, eventqueue, eventfilter, rows[r], pseudofork->depth) );
3122 || (ncols == node->data.probingnode->ninitialcols && nrows == node->data.probingnode->ninitialrows));
3156 SCIPerrorMessage("node at depth %d on active path has to be of type JUNCTION, PSEUDOFORK, FORK, SUBROOT, FOCUSNODE, REFOCUSNODE, or PROBINGNODE, but is %d\n",
3176 SCIP_Bool* initroot /**< pointer to store whether the root LP relaxation has to be initialized */
3200 SCIPdebugMessage("-> old LP has %d cols and %d rows\n", SCIPlpGetNCols(lp), SCIPlpGetNRows(lp));
3222 || SCIPnodeGetType(lpfork) == SCIP_NODETYPE_FORK || SCIPnodeGetType(lpfork) == SCIP_NODETYPE_SUBROOT);
3227 assert(lpforkdepth < tree->pathlen-1); /* lpfork must not be the last (the focus) node of the active path */
3233 assert(lpforkdepth == -1 || tree->pathnlpcols[tree->correctlpdepth] <= tree->pathnlpcols[lpforkdepth]);
3234 assert(lpforkdepth == -1 || tree->pathnlprows[tree->correctlpdepth] <= tree->pathnlprows[lpforkdepth]);
3238 SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, tree->pathnlprows[tree->correctlpdepth]) );
3274 assert(lpforkdepth == -1 || tree->pathnlpcols[tree->correctlpdepth] == tree->pathnlpcols[lpforkdepth]);
3275 assert(lpforkdepth == -1 || tree->pathnlprows[tree->correctlpdepth] == tree->pathnlprows[lpforkdepth]);
3285 SCIPdebugMessage("-> new LP has %d cols and %d rows\n", SCIPlpGetNCols(lp), SCIPlpGetNRows(lp));
3337 assert(SCIPnodeGetType(lpstatefork) == SCIP_NODETYPE_FORK || SCIPnodeGetType(lpstatefork) == SCIP_NODETYPE_SUBROOT);
3341 assert(lpstateforkdepth < tree->pathlen-1); /* lpstatefork must not be the last (the focus) node of the active path */
3342 assert(lpstateforkdepth <= tree->correctlpdepth); /* LP must have been constructed at least up to the fork depth */
3343 assert(tree->pathnlpcols[tree->correctlpdepth] >= tree->pathnlpcols[lpstateforkdepth]); /* LP can only grow */
3344 assert(tree->pathnlprows[tree->correctlpdepth] >= tree->pathnlprows[lpstateforkdepth]); /* LP can only grow */
3369 /* we do not need to check the bounds, since primalfeasible is updated anyway when flushing the LP */
3381 /* check the path from LP fork to focus node for domain changes (destroying primal feasibility of LP basis) */
3387 lp->primalfeasible = (tree->path[d]->domchg == NULL || tree->path[d]->domchg->domchgbound.nboundchgs == 0);
3392 SCIPdebugMessage("-> primalfeasible=%u, dualfeasible=%u\n", lp->primalfeasible, lp->dualfeasible);
3418 SCIP_Real cutoffbound /**< cutoff bound: all nodes with lowerbound >= cutoffbound are cut off */
3421 assert(SCIPnodeGetType(*node) == SCIP_NODETYPE_SIBLING || SCIPnodeGetType(*node) == SCIP_NODETYPE_CHILD);
3424 assert(lpstatefork == NULL || lpstatefork->active || SCIPsetIsGE(set, (*node)->lowerbound, cutoffbound));
3430 SCIPdebugMessage("convert node #%"SCIP_LONGINT_FORMAT" at depth %d to leaf with lpstatefork #%"SCIP_LONGINT_FORMAT" at depth %d\n",
3438 /* check, if the LP state fork is the first node with LP state information on the path back to the root */
3439 if( cutoffbound != SCIP_REAL_MIN ) /* if the node was cut off in SCIPnodeFocus(), the lpstatefork is invalid */
3476 /** removes variables from the problem, that are marked to be deletable, and were created at the focusnode;
3477 * only removes variables that were created at the focusnode, unless inlp is TRUE (e.g., when the node is cut off, anyway)
3516 /* also delete variables currently in the LP, thus remove all new variables from the LP, first */
3571 SCIP_CALL( SCIPprobPerformVarDeletions(transprob, blkmem, set, stat, eventqueue, lp, branchcand) );
3601 /* remove variables from the problem that are marked as deletable and were created at this node */
3602 SCIP_CALL( focusnodeCleanupVars(blkmem, set, stat, eventqueue, transprob, origprob, tree, lp, branchcand, TRUE) );
3631 assert(tree->focusnode->active); /* otherwise, no children could be created at the focus node */
3675 assert(tree->focusnode->active); /* otherwise, no children could be created at the focus node */
3683 /* remove variables from the problem that are marked as deletable and were created at this node */
3684 SCIP_CALL( focusnodeCleanupVars(blkmem, set, stat, eventqueue, transprob, origprob, tree, lp, branchcand, FALSE) );
3727 assert(tree->focusnode->active); /* otherwise, no children could be created at the focus node */
3744 SCIP_CALL( SCIPlpCleanupNew(lp, blkmem, set, stat, eventqueue, eventfilter, (tree->focusnode->depth == 0)) );
3750 SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob, -1LL, FALSE, FALSE, TRUE, &lperror) );
3761 * - Something numerically weird happened after cleaning up or after resolving a diving or probing LP.
3771 "(node %"SCIP_LONGINT_FORMAT") numerical troubles: LP %"SCIP_LONGINT_FORMAT" not optimal -- convert node into junction instead of fork\n",
3776 SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, SCIPlpGetNRows(lp) - SCIPlpGetNNewrows(lp)) );
3779 SCIP_CALL( focusnodeToJunction(blkmem, set, stat, eventqueue, transprob, tree, lp, branchcand) );
3787 /* remove variables from the problem that are marked as deletable, were created at this node and are not contained in the LP */
3788 SCIP_CALL( focusnodeCleanupVars(blkmem, set, stat, eventqueue, transprob, origprob, tree, lp, branchcand, FALSE) );
3799 /* capture the LPI state of the root node to ensure that the LPI state of the root stays for the whole solving
3842 assert(tree->focusnode->active); /* otherwise, no children could be created at the focus node */
3861 SCIP_CALL( SCIPlpCleanupAll(lp, blkmem, set, stat, eventqueue, eventfilter, (tree->focusnode->depth == 0)) );
3873 SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob, -1LL, FALSE, FALSE, TRUE, &lperror) );
3894 "(node %"SCIP_LONGINT_FORMAT") numerical troubles: LP %"SCIP_LONGINT_FORMAT" not optimal -- convert node into junction instead of subroot\n",
3899 SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, SCIPlpGetNRows(lp) - SCIPlpGetNNewrows(lp)) );
3902 SCIP_CALL( focusnodeToJunction(blkmem, set, stat, eventqueue, transprob, tree, lp, branchcand) );
3910 /* remove variables from the problem that are marked as deletable, were created at this node and are not contained in the LP */
3911 SCIP_CALL( focusnodeCleanupVars(blkmem, set, stat, eventqueue, transprob, origprob, tree, lp, branchcand, FALSE) );
3951 SCIP_Real cutoffbound /**< cutoff bound: all nodes with lowerbound >= cutoffbound are cut off */
3963 /* convert node to LEAF and put it into leaves queue, or delete it if it's lower bound exceeds the cutoff bound */
3964 SCIP_CALL( nodeToLeaf(&nodes[i], blkmem, set, stat, eventqueue, tree, lp, lpstatefork, cutoffbound) );
4005 /* because CHILD.arraypos and SIBLING.arraypos are on the same position, we do not have to copy it */
4006 assert(&(tree->siblings[i]->data.sibling.arraypos) == &(tree->siblings[i]->data.child.arraypos));
4052 *node != NULL ? SCIPnodeGetNumber(*node) : -1, *node != NULL ? (int)SCIPnodeGetType(*node) : 0,
4055 /* remember old cutoff depth in order to know, whether the children and siblings can be deleted */
4062 SCIPdebugMessage("focus node: focusnodedepth=%d, forkdepth=%d, lpforkdepth=%d, lpstateforkdepth=%d, subrootdepth=%d, cutoff=%u\n",
4064 lpfork != NULL ? lpfork->depth : -1, lpstatefork != NULL ? lpstatefork->depth : -1, /*lint !e705 */
4091 /* we are in the same subtree with valid LP fork: the LP is correct at most upto the common fork depth */
4097 /* we are in a different subtree, or no valid LP fork exists: the LP is completely incorrect */
4103 /* if the LP state fork changed, the lpcount information for the new LP state fork is unknown */
4109 * @note because we might do a 'newstart' and converted cuts to constraints might have rendered the LP in the current
4114 SCIPdebugMessage(" -> deleting the %d children (in exitsolve) of the old focus node\n", tree->nchildren);
4115 SCIP_CALL( treeNodesToQueue(tree, blkmem, set, stat, eventqueue, lp, tree->children, &tree->nchildren, NULL, SCIP_REAL_MIN) );
4127 /* delete the focus node's children by converting them to leaves with a cutoffbound of SCIP_REAL_MIN;
4128 * we cannot delete them directly, because in SCIPnodeFree(), the children array is changed, which is the
4130 * the children don't have an LP fork, because the old focus node is not yet converted into a fork or subroot
4133 SCIP_CALL( treeNodesToQueue(tree, blkmem, set, stat, eventqueue, lp, tree->children, &tree->nchildren, NULL, SCIP_REAL_MIN) );
4138 /* delete the focus node's siblings by converting them to leaves with a cutoffbound of SCIP_REAL_MIN;
4139 * we cannot delete them directly, because in SCIPnodeFree(), the siblings array is changed, which is the
4144 SCIP_CALL( treeNodesToQueue(tree, blkmem, set, stat, eventqueue, lp, tree->siblings, &tree->nsiblings, tree->focuslpstatefork,
4169 #ifdef WITHSUBROOTS /** @todo test whether subroots should be created, decide: old focus node becomes fork or subroot */
4173 SCIP_CALL( focusnodeToSubroot(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, transprob, origprob, tree, lp, branchcand) );
4182 SCIP_CALL( focusnodeToFork(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, transprob, origprob, tree, lp, branchcand) );
4191 /* if a child of the old focus node was selected as new focus node, the old node becomes the new focus
4207 else if( tree->focuslpconstructed && (SCIPlpGetNNewcols(lp) > 0 || SCIPlpGetNNewrows(lp) > 0) )
4210 SCIP_CALL( focusnodeToPseudofork(blkmem, set, stat, eventqueue, transprob, origprob, tree, lp, branchcand) );
4217 /* if a child of the old focus node was selected as new focus node, the old node becomes the new focus LP fork */
4226 /* in case the LP was not constructed (due to the parameter settings for example) we have the finally remember the
4227 * old size of the LP (if it was constructed in an earlier node) before we change the current node into a junction
4232 SCIP_CALL( focusnodeToJunction(blkmem, set, stat, eventqueue, transprob, tree, lp, branchcand) );
4237 /* in case the LP was not constructed (due to the parameter settings for example) we have the finally remember the
4238 * old size of the LP (if it was constructed in an earlier node) before we change the current node into a junction
4244 SCIP_CALL( focusnodeToDeadend(blkmem, set, stat, eventqueue, transprob, origprob, tree, lp, branchcand) );
4264 SCIP_CALL( treeNodesToQueue(tree, blkmem, set, stat, eventqueue, lp, tree->siblings, &tree->nsiblings, tree->focuslpstatefork,
4268 SCIP_CALL( treeNodesToQueue(tree, blkmem, set, stat, eventqueue, lp, tree->children, &tree->nchildren, childrenlpstatefork,
4284 SCIP_CALL( treeNodesToQueue(tree, blkmem, set, stat, eventqueue, lp, tree->children, &tree->nchildren, childrenlpstatefork,
4290 SCIPdebugMessage("selected sibling node, lowerbound=%g, plungedepth=%d\n", (*node)->lowerbound, stat->plungedepth);
4294 /* reset plunging depth, if the selected node is better than all leaves; otherwise, increase plunging depth */
4302 SCIP_CALL( treeNodesToQueue(tree, blkmem, set, stat, eventqueue, lp, tree->siblings, &tree->nsiblings, tree->focuslpstatefork,
4311 SCIPdebugMessage("selected child node, lowerbound=%g, plungedepth=%d\n", (*node)->lowerbound, stat->plungedepth);
4316 SCIP_CALL( treeNodesToQueue(tree, blkmem, set, stat, eventqueue, lp, tree->siblings, &tree->nsiblings, tree->focuslpstatefork,
4320 SCIP_CALL( treeNodesToQueue(tree, blkmem, set, stat, eventqueue, lp, tree->children, &tree->nchildren, childrenlpstatefork,
4329 SCIPdebugMessage("selected leaf node, lowerbound=%g, plungedepth=%d\n", (*node)->lowerbound, stat->plungedepth);
4333 SCIPerrorMessage("selected node is neither sibling, child, nor leaf (nodetype=%d)\n", SCIPnodeGetType(*node));
4353 /* track the path from the old focus node to the new node, and perform domain and constraint set changes */
4354 SCIP_CALL( treeSwitchPath(tree, blkmem, set, stat, transprob, origprob, primal, lp, branchcand, conflict,
4375 /* promote the constraint set and bound changes up to the new effective root to be global changes */
4376 SCIPdebugMessage("effective root is now at depth %d: applying constraint set and bound changes to global problem\n",
4384 SCIP_CALL( SCIPconssetchgMakeGlobal(&tree->path[d]->conssetchg, blkmem, set, stat, transprob) );
4386 SCIP_CALL( SCIPdomchgApplyGlobal(tree->path[d]->domchg, blkmem, set, stat, lp, branchcand, eventqueue,
4533 /* we have to remove the captures of the variables within the pending bound change data structure */
4587 SCIP_CALL( SCIPnodeCreateChild(&tree->root, blkmem, set, stat, tree, 0.0, -SCIPsetInfinity(set)) );
4597 tree->root->repropsubtreemark++; /* this should produce an overflow and reset the value to 0 */
4607 SCIP_CALL( treeNodesToQueue(tree, blkmem, set, stat, eventqueue, lp, tree->children, &tree->nchildren, NULL,
4644 SCIP_CALL( SCIPnodeFocus(&tree->root, blkmem, set, messagehdlr, stat, transprob, origprob, primal, tree, lp, branchcand,
4678 SCIP_CALL( SCIPnodeFocus(&node, blkmem, set, messagehdlr, stat, transprob, origprob, primal, tree, lp, branchcand,
4701 /** sets the node selector used for sorting the nodes in the priority queue, and resorts the queue if necessary */
4722 "(node %"SCIP_LONGINT_FORMAT") switching to node selector <%s>\n", stat->nnodes, SCIPnodeselGetName(nodesel));
4737 SCIP_Real cutoffbound /**< cutoff bound: all nodes with lowerbound >= cutoffbound are cut off */
4747 /* if we are in diving mode, it is not allowed to cut off nodes, because this can lead to deleting LP rows which
4760 SCIP_CALL( SCIPnodepqBound(tree->leaves, blkmem, set, stat, eventqueue, tree, lp, cutoffbound) );
4762 /* cut off siblings: we have to loop backwards, because a removal leads to moving the last node in empty slot */
4768 SCIPdebugMessage("cut off sibling #%"SCIP_LONGINT_FORMAT" at depth %d with lowerbound=%g at position %d\n",
4775 /* cut off children: we have to loop backwards, because a removal leads to moving the last node in empty slot */
4781 SCIPdebugMessage("cut off child #%"SCIP_LONGINT_FORMAT" at depth %d with lowerbound=%g at position %d\n",
4791 /** calculates the node selection priority for moving the given variable's LP value to the given target value;
4799 SCIP_BRANCHDIR branchdir, /**< type of branching that was performed: upwards, downwards, or fixed
4914 /* since choosing the upwards direction is usually superior than the downwards direction (see results of
4941 /** calculates an estimate for the objective of the best feasible solution contained in the subtree after applying the given
4972 * = parentestimate - min{f_b * pscdown_b, (1-f_b) * pscup_b} + (targetvalue-oldvalue)*{pscdown_b or pscup_b}
4979 /* due to rounding errors estimateinc might be slightly negative; in this case return the parent node's estimate */
4990 * the variable is fixed to val (if not SCIP_INVALID) or a well chosen alternative in the current node,
5000 * if solution value is equal to one of the bounds and the other bound is infinite, only two child nodes
5014 SCIP_Real val, /**< value to branch on or SCIP_INVALID for branching on current LP/pseudo solution.
5016 SCIP_NODE** downchild, /**< pointer to return the left child with variable rounded down, or NULL */
5018 SCIP_NODE** upchild /**< pointer to return the right child with variable rounded up, or NULL */
5071 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED || SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR )
5073 SCIPerrorMessage("cannot branch on fixed or multi-aggregated variable <%s>\n", SCIPvarGetName(var));
5078 /* ensure, that branching on continuous variables will only be performed when a branching point is given. */
5081 SCIPerrorMessage("Cannot branch on continuous variables without a given branching value.\n", SCIPvarGetName(var));
5088 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
5089 assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, SCIPvarGetLbLocal(var)));
5090 assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, SCIPvarGetUbLocal(var)));
5096 /* if there was no explicit value given for branching, branch on current LP or pseudo solution value */
5120 (SCIPsetIsLT(set, 2.1*SCIPvarGetLbLocal(var), 2.1*val) && SCIPsetIsLT(set, 2.1*val, 2.1*SCIPvarGetUbLocal(var))) ); /* see comment in SCIPbranchVarVal */
5130 SCIPdebugMessage("fixing continuous variable <%s> with value %g and bounds [%.15g, %.15g], priority %d (current lower bound: %g)\n",
5131 SCIPvarGetName(var), val, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), SCIPvarGetBranchPriority(var), SCIPnodeGetLowerbound(tree->focusnode));
5135 if( SCIPsetIsGT(set, val, SCIPvarGetLbLocal(var)) && SCIPsetIsLT(set, val, SCIPvarGetUbLocal(var)) )
5137 SCIP_CALL( SCIPnodeAddBoundchg(tree->focusnode, blkmem, set, stat, transprob, origprob, tree, lp,
5139 SCIP_CALL( SCIPnodeAddBoundchg(tree->focusnode, blkmem, set, stat, transprob, origprob, tree, lp,
5144 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(tree), blkmem, set, stat, transprob, origprob,
5149 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(tree), blkmem, set, stat, transprob, origprob,
5153 else if( SCIPrelDiff(SCIPvarGetUbLocal(var), SCIPvarGetLbLocal(var)) <= 2.0 * SCIPsetEpsilon(set) )
5155 /* if the only way to branch is such that in both sides the relative domain width becomes smaller epsilon,
5158 * however, if one of the bounds is at infinity (and thus the other bound is at most 2eps away from the same infinity (in relative sense),
5161 SCIPdebugMessage("continuous branch on variable <%s> with bounds [%.15g, %.15g], priority %d (current lower bound: %g), node %p\n",
5162 SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), SCIPvarGetBranchPriority(var), SCIPnodeGetLowerbound(tree->focusnode), (void*)tree->focusnode);
5166 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(tree), blkmem, set, stat, transprob, origprob,
5172 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(tree), blkmem, set, stat, transprob, origprob,
5184 * a sophisticated user should have also chosen the branching value such that it is not very close to the bounds
5187 SCIPdebugMessage("continuous branch on variable <%s> with value %g, priority %d (current lower bound: %g)\n",
5188 SCIPvarGetName(var), val, SCIPvarGetBranchPriority(var), SCIPnodeGetLowerbound(tree->focusnode));
5201 /* if there was no explicit value given for branching, the variable has a finite domain and the current LP/pseudo
5239 SCIPdebugMessage("integral branch on variable <%s> with value %g, priority %d (current lower bound: %g)\n",
5240 SCIPvarGetName(var), val, SCIPvarGetBranchPriority(var), SCIPnodeGetLowerbound(tree->focusnode));
5248 SCIPdebugMessage("fractional branch on variable <%s> with value %g, root value %g, priority %d (current lower bound: %g)\n",
5249 SCIPvarGetName(var), val, SCIPvarGetRootSol(var), SCIPvarGetBranchPriority(var), SCIPnodeGetLowerbound(tree->focusnode));
5253 * set the node selection priority in a way, s.t. a node is preferred whose branching goes in the same direction
5259 priority = SCIPtreeCalcNodeselPriority(tree, set, stat, var, SCIP_BRANCHDIR_DOWNWARDS, downub);
5261 * otherwise we cannot expect a direct change in the best solution, so we keep the estimate of the parent node */
5269 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
5288 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
5293 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
5314 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
5326 /** branches a variable x using the given domain hole; two child nodes will be created (x <= left, x >= right) */
5340 SCIP_NODE** downchild, /**< pointer to return the left child with variable rounded down, or NULL */
5341 SCIP_NODE** upchild /**< pointer to return the right child with variable rounded up, or NULL */
5367 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED || SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR )
5369 SCIPerrorMessage("cannot branch on fixed or multi-aggregated variable <%s>\n", SCIPvarGetName(var));
5376 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
5377 assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, SCIPvarGetLbLocal(var)));
5378 assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, SCIPvarGetUbLocal(var)));
5401 * set the node selection priority in a way, s.t. a node is preferred whose branching goes in the same direction
5409 * otherwise we cannot expect a direct change in the best solution, so we keep the estimate of the parent node
5420 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
5440 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
5452 * Branches on variable x such that up to n/2 children are created on each side of the usual branching value.
5454 * If n is 2 or the variables local domain is too small for a branching into n pieces, SCIPtreeBranchVar() is called.
5455 * The parameters minwidth and widthfactor determine the domain width of the branching variable in the child nodes.
5456 * If n is odd, one child with domain width 'width' and having the branching value in the middle is created.
5457 * Otherwise, two children with domain width 'width' and being left and right of the branching value are created.
5458 * Next further nodes to the left and right are created, where width is multiplied by widthfactor with increasing distance from the first nodes.
5459 * The initial width is calculated such that n/2 nodes are created to the left and to the right of the branching value.
5460 * If this value is below minwidth, the initial width is set to minwidth, which may result in creating less than n nodes.
5462 * Giving a large value for widthfactor results in creating children with small domain when close to the branching value
5463 * and large domain when closer to the current variable bounds. That is, setting widthfactor to a very large value and n to 3
5464 * results in a ternary branching where the branching variable is mostly fixed in the middle child.
5465 * Setting widthfactor to 1.0 results in children where the branching variable always has the same domain width
5479 SCIP_Real val, /**< value to branch on or SCIP_INVALID for branching on current LP/pseudo solution.
5483 SCIP_Real widthfactor, /**< multiplier for children domain width with increasing distance from val, must be >= 1.0 */
5504 /* if binary branching is requested or we have not enough space for n children, delegate to SCIPtreeBranchVar */
5507 SCIPrelDiff(SCIPvarGetUbLocal(SCIPvarGetProbvar(var)), SCIPvarGetLbLocal(SCIPvarGetProbvar(var))) <= n * SCIPsetEpsilon(set) )
5513 SCIP_CALL( SCIPtreeBranchVar(tree, blkmem, set, stat, transprob, origprob, lp, branchcand, eventqueue, var, val,
5517 *nchildren = (downchild != NULL ? 1 : 0) + (fixchild != NULL ? 1 : 0) + (upchild != NULL ? 1 : 0);
5549 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED || SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR )
5551 SCIPerrorMessage("cannot branch on fixed or multi-aggregated variable <%s>\n", SCIPvarGetName(var));
5556 /* ensure, that branching on continuous variables will only be performed when a branching point is given. */
5559 SCIPerrorMessage("Cannot branch on continuous variables without a given branching value.\n", SCIPvarGetName(var));
5566 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
5567 assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, SCIPvarGetLbLocal(var)));
5568 assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, SCIPvarGetUbLocal(var)));
5574 /* if there was no explicit value given for branching, branch on current LP or pseudo solution value */
5598 (SCIPsetIsLT(set, 2.1*SCIPvarGetLbLocal(var), 2.1*val) && SCIPsetIsLT(set, 2.1*val, 2.1*SCIPvarGetUbLocal(var))) ); /* see comment in SCIPbranchVarVal */
5611 * if we have at least one finite bound, choose width such that we have roughly the same number of nodes left and right of val
5634 * <-> width * (1/2 + widthfactor * (widthfactor^(n/2) - 1) / (widthfactor - 1) = min(ub-val, val-lb)
5640 width /= 0.5 + widthfactor * (pow(widthfactor, (SCIP_Real)(n/2)) - 1.0) / (widthfactor - 1.0); /*lint !e653*/
5655 * if we are supposed to create an odd number of children, then create a child that has val in the middle of its domain */
5666 priority = SCIPtreeCalcNodeselPriority(tree, set, stat, var, SCIP_BRANCHDIR_FIXED, val); /* ????????????? how to compute priority for such a child? */
5668 * otherwise we cannot expect a direct change in the best solution, so we keep the estimate of the parent node */
5675 SCIPdebugMessage(" -> creating middle child: %g <= <%s> <= %g (priority: %g, estimate: %g, width: %g)\n",
5678 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
5680 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
5692 /* if it's a discrete variable, we can use left-1 and right+1 as upper and lower bounds for following nodes on the left and right, resp. */
5725 if( SCIPsetIsRelLT(set, SCIPvarGetLbLocal(var), left) || SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS )
5727 /* new lower bound should be variables lower bound, if we are in the last round or left - width is very close to lower bound
5743 priority = SCIPtreeCalcNodeselPriority(tree, set, stat, var, SCIP_BRANCHDIR_DOWNWARDS, bnd) / (i+1);
5745 * otherwise we cannot expect a direct change in the best solution, so we keep the estimate of the parent node */
5752 SCIPdebugMessage(" -> creating left child: %g <= <%s> <= %g (priority: %g, estimate: %g, width: %g)\n",
5757 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
5760 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
5774 if( SCIPsetIsRelGT(set, SCIPvarGetUbLocal(var), right) || SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS )
5776 /* new upper bound should be variables upper bound, if we are in the last round or right + width is very close to upper bound
5792 priority = SCIPtreeCalcNodeselPriority(tree, set, stat, var, SCIP_BRANCHDIR_UPWARDS, bnd) / (i+1);
5794 * otherwise we cannot expect a direct change in the best solution, so we keep the estimate of the parent node */
5801 SCIPdebugMessage(" -> creating right child: %g <= <%s> <= %g (priority: %g, estimate: %g, width: %g)\n",
5804 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
5808 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
5828 /** creates a probing child node of the current node, which must be the focus node, the current refocused node,
5829 * or another probing node; if the current node is the focus or a refocused node, the created probing node is
5891 SCIPdebugMessage("created probing child node #%"SCIP_LONGINT_FORMAT" at depth %d, probing depth %d\n",
5892 SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), SCIPnodeGetDepth(node) - SCIPnodeGetDepth(tree->probingroot));
5901 /* update the path LP size for the previous node and set the (initial) path LP size for the newly created node */
5907 assert(lp->firstnewrow == tree->pathnlprows[tree->pathlen-1]); /* marked LP size should be initial size of new node */
5931 SCIPdebugMessage("probing started in depth %d (LP flushed: %u, LP solved: %u, solstat: %d), probing root in depth %d\n",
5949 /**@todo could the lp state be worth storing if the LP is not flushed (and hence not solved)? */
6028 /* if there was no LP information stored in the probing nodes, use the one stored before probing started */
6096 int probingdepth /**< probing depth of the node in the probing path that should be reactivated,
6126 /* the correct LP size of the node to which we backtracked is stored as initial LP size for its child */
6140 SCIP_CALL( nodeDeactivate(tree->path[tree->pathlen-1], blkmem, set, stat, tree, lp, branchcand, eventqueue) );
6143 SCIP_CALL( SCIPnodeFree(&tree->path[tree->pathlen-1], blkmem, set, stat, eventqueue, tree, lp) );
6151 tree->pathnlpcols[tree->pathlen-1] = tree->path[tree->pathlen-1]->data.probingnode->ninitialcols;
6152 tree->pathnlprows[tree->pathlen-1] = tree->path[tree->pathlen-1]->data.probingnode->ninitialrows;
6168 /* if the highest cutoff or repropagation depth is inside the deleted part of the probing path,
6174 SCIP_CALL( treeApplyPendingBdchgs(tree, blkmem, set, stat, transprob, origprob, lp, branchcand, eventqueue) );
6189 * the changes of the probing node of the given probing depth are the last ones that remain active;
6203 int probingdepth /**< probing depth of the node in the probing path that should be reactivated */
6210 /* undo the domain and constraint set changes and free the temporary probing nodes below the given probing depth */
6211 SCIP_CALL( treeBacktrackProbing(tree, blkmem, set, stat, transprob, origprob, lp, branchcand, eventqueue, eventfilter, probingdepth) );
6219 /** switches back from probing to normal operation mode, frees all nodes on the probing path, restores bounds of all
6249 /* undo the domain and constraint set changes of the temporary probing nodes and free the probing nodes */
6250 SCIP_CALL( treeBacktrackProbing(tree, blkmem, set, stat, transprob, origprob, lp, branchcand, eventqueue, eventfilter, -1) );
6289 SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob, -1LL, FALSE, FALSE, FALSE, &lperror) );
6293 "(node %"SCIP_LONGINT_FORMAT") unresolved numerical troubles while resolving LP %"SCIP_LONGINT_FORMAT" after probing\n",
6310 SCIP_CALL( SCIPnodeUpdateLowerboundLP(tree->focusnode, set, stat, tree, transprob, origprob, lp) );
6319 /* if no LP was solved during probing and the LP before probing was not solved, then it should not be solved now */
6322 /* if the LP was solved (and hence flushed) before probing, then lp->solved should be TRUE unless we occured an error
6327 /* if the LP was not solved before probing it should be marked unsolved now; this can occur if a probing LP was
6336 /* if the LP was solved during probing, but had been unsolved before probing started, we discard the LP state */
6339 SCIPdebugMessage("clearing lp state at end of probing mode because LP was initially unsolved\n");
6355 SCIP_CALL( SCIPconshdlrsResetPropagationStatus(set, blkmem, set->conshdlrs, set->nconshdlrs) );
6363 /** gets the best child of the focus node w.r.t. the node selection priority assigned by the branching rule */
6389 /** gets the best sibling of the focus node w.r.t. the node selection priority assigned by the branching rule */
6479 /** gets the best node from the tree (child, sibling, or leaf) w.r.t. the node selection strategy */
6503 if( bestsibling != NULL && (bestnode == NULL || SCIPnodeselCompare(nodesel, set, bestsibling, bestnode) < 0) )
6505 if( bestleaf != NULL && (bestnode == NULL || SCIPnodeselCompare(nodesel, set, bestleaf, bestnode) < 0) )
6551 /** gets the node with minimal lower bound of all nodes in the tree (child, sibling, or leaf) */
6576 if( SCIPsetIsLT(set, tree->children[i]->lowerbound, lowerbound) || tree->childrenprio[i] > bestprio )
6591 if( SCIPsetIsLT(set, tree->siblings[i]->lowerbound, lowerbound) || tree->siblingsprio[i] > bestprio )
6737 /** gets the domain change information of the node, i.e., the information about the differences in the
6759 /** returns the set of variable branchings that were performed in the parent node to create this node */
6762 SCIP_VAR** branchvars, /**< array of variables on which the branching has been performed in the parent node */
6764 SCIP_BOUNDTYPE* boundtypes, /**< array of boundtypes which the branching in the parent node set */
6765 int* nbranchvars, /**< number of variables on which branching has been performed in the parent node
6793 /* count the number of branching decisions; branching decisions have to be in the beginning of the bound change
6823 /** returns the set of variable branchings that were performed in all ancestor nodes (nodes on the path to the root) to create this node */
6826 SCIP_VAR** branchvars, /**< array of variables on which the branchings has been performed in all ancestors */
6828 SCIP_BOUNDTYPE* boundtypes, /**< array of boundtypes which the branchings in all ancestors set */
6829 int* nbranchvars, /**< number of variables on which branchings have been performed in all ancestors
6853 SCIPnodeGetParentBranchings(node, &branchvars[start], &branchbounds[start], &boundtypes[start], &nodenbranchvars, size);
6889 (SCIP_BOUNDTYPE) boundchgs[i].boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", boundchgs[i].newbound);
6895 SCIPgmlWriteArc(file, (unsigned int)(size_t)nbranchings, (unsigned int)(size_t)(nbranchings-1), NULL, NULL);
6910 /* returns the set of variable branchings that were performed in all ancestor nodes (nodes on the path to the root) to create this node
6915 SCIP_VAR** branchvars, /**< array of variables on which the branchings has been performed in all ancestors */
6917 SCIP_BOUNDTYPE* boundtypes, /**< array of boundtypes which the branchings in all ancestors set */
6918 int* nbranchvars, /**< number of variables on which branchings have been performed in all ancestors
6922 int* nodeswitches, /**< marks, where in the arrays the branching decisions of the next node on the path
6946 /* calculate the start position for the current node and the maximum remaining slots in the arrays */
6953 SCIPnodeGetParentBranchings(node, &branchvars[start], &branchbounds[start], &boundtypes[start], &nodenbranchvars, size);
6961 /** checks for two nodes whether they share the same root path, i.e., whether one is an ancestor of the other */
7099 assert(tree->probingroot == NULL || (SCIP_NODETYPE)tree->probingroot->nodetype == SCIP_NODETYPE_PROBINGNODE);
7101 assert(tree->probingroot == NULL || tree->path[SCIPnodeGetDepth(tree->probingroot)] == tree->probingroot);
7112 assert(tree->probingroot == NULL || (SCIP_NODETYPE)tree->probingroot->nodetype == SCIP_NODETYPE_PROBINGNODE);
7114 assert(tree->probingroot == NULL || tree->path[SCIPnodeGetDepth(tree->probingroot)] == tree->probingroot);
7191 return (tree->focusnode != NULL && SCIPnodeGetType(tree->focusnode) == SCIP_NODETYPE_REFOCUSNODE);
7194 /** gets current node of the tree, i.e. the last node in the active path, or NULL if no current node exists */
7211 /** gets depth of current node in the tree, i.e. the length of the active path minus 1, or -1 if no current node exists */
7239 /** returns the current probing depth, i.e. the number of probing sub nodes existing in the probing path */
|