/** node comparison method of breadth first search: nodes with lower depth are preferred; in case of a tie, the node * which was created earlier (and therefore has a smaller node number) is preferred */ static SCIP_DECL_NODESELCOMP(nodeselCompBreadthfirst) { /*lint --e{715}*/ int depth1; int depth2; assert(nodesel != NULL); assert(strcmp(SCIPnodeselGetName(nodesel), NODESEL_NAME) == 0); assert(scip != NULL); depth1 = SCIPnodeGetDepth(node1); depth2 = SCIPnodeGetDepth(node2); /* if depths differ, prefer node with smaller depth */ if( depth1 < depth2 ) return -1; else if( depth1 > depth2 ) return +1; else { /* depths are equal; prefer node with smaller number */ SCIP_Longint number1; SCIP_Longint number2; number1 = SCIPnodeGetNumber(node1); number2 = SCIPnodeGetNumber(node2); assert(number1 != number2); if( number1 < number2 ) return -1; else return +1; } }
/** node comparison method of node selector */ static SCIP_DECL_NODESELCOMP(nodeselCompDfs) { /*lint --e{715}*/ int depth1; int depth2; assert(nodesel != NULL); assert(strcmp(SCIPnodeselGetName(nodesel), NODESEL_NAME) == 0); assert(scip != NULL); depth1 = SCIPnodeGetDepth(node1); depth2 = SCIPnodeGetDepth(node2); if( depth1 > depth2 ) return -1; else if( depth1 < depth2 ) return +1; else { SCIP_Real lowerbound1; SCIP_Real lowerbound2; lowerbound1 = SCIPnodeGetLowerbound(node1); lowerbound2 = SCIPnodeGetLowerbound(node2); if( lowerbound1 < lowerbound2 ) return -1; else if( lowerbound1 > lowerbound2 ) return +1; else return 0; } }
/** node comparison method of node selector */ static SCIP_DECL_NODESELCOMP(nodeselCompHybridestim) { /*lint --e{715}*/ SCIP_NODESELDATA* nodeseldata; SCIP_Real score1; SCIP_Real score2; assert(nodesel != NULL); assert(strcmp(SCIPnodeselGetName(nodesel), NODESEL_NAME) == 0); assert(scip != NULL); nodeseldata = SCIPnodeselGetData(nodesel); assert(nodeseldata != NULL); score1 = getNodeselScore(node1, nodeseldata->estimweight); score2 = getNodeselScore(node2, nodeseldata->estimweight); if( (SCIPisInfinity(scip, score1) && SCIPisInfinity(scip, score2)) || (SCIPisInfinity(scip, -score1) && SCIPisInfinity(scip, -score2)) || SCIPisEQ(scip, score1, score2) ) { SCIP_NODETYPE nodetype1; SCIP_NODETYPE nodetype2; nodetype1 = SCIPnodeGetType(node1); nodetype2 = SCIPnodeGetType(node2); if( nodetype1 == SCIP_NODETYPE_CHILD && nodetype2 != SCIP_NODETYPE_CHILD ) return -1; else if( nodetype1 != SCIP_NODETYPE_CHILD && nodetype2 == SCIP_NODETYPE_CHILD ) return +1; else if( nodetype1 == SCIP_NODETYPE_SIBLING && nodetype2 != SCIP_NODETYPE_SIBLING ) return -1; else if( nodetype1 != SCIP_NODETYPE_SIBLING && nodetype2 == SCIP_NODETYPE_SIBLING ) return +1; else { int depth1; int depth2; depth1 = SCIPnodeGetDepth(node1); depth2 = SCIPnodeGetDepth(node2); if( depth1 < depth2 ) return -1; else if( depth1 > depth2 ) return +1; else return 0; } } if( SCIPisLT(scip, score1, score2) ) return -1; assert(SCIPisGT(scip, score1, score2)); return +1; }
/** copy method for node selector plugins (called when SCIP copies plugins) */ static SCIP_DECL_NODESELCOPY(nodeselCopyDfs) { /*lint --e{715}*/ assert(scip != NULL); assert(nodesel != NULL); assert(strcmp(SCIPnodeselGetName(nodesel), NODESEL_NAME) == 0); /* call inclusion method of node selector */ SCIP_CALL( SCIPincludeNodeselDfs(scip) ); return SCIP_OKAY; }
/** node comparison method of node selector */ static SCIP_DECL_NODESELCOMP(nodeselCompMaster) { assert(nodesel != NULL); assert(strcmp(SCIPnodeselGetName(nodesel), NODESEL_NAME) == 0); assert(scip != NULL); if( SCIPnodeGetNumber(node1) < SCIPnodeGetNumber(node2) ) return 1; else return -1; }
/** destructor of node selector to free user data (called when SCIP is exiting) */ static SCIP_DECL_NODESELFREE(nodeselFreeBfs) { /*lint --e{715}*/ SCIP_NODESELDATA* nodeseldata; assert(nodesel != NULL); assert(strcmp(SCIPnodeselGetName(nodesel), NODESEL_NAME) == 0); assert(scip != NULL); /* free user data of node selector */ nodeseldata = SCIPnodeselGetData(nodesel); assert(nodeseldata != NULL); SCIPfreeMemory(scip, &nodeseldata); SCIPnodeselSetData(nodesel, nodeseldata); return SCIP_OKAY; }
/** node selection method of node selector */ static SCIP_DECL_NODESELSELECT(nodeselSelectDfs) { /*lint --e{715}*/ assert(nodesel != NULL); assert(strcmp(SCIPnodeselGetName(nodesel), NODESEL_NAME) == 0); assert(scip != NULL); assert(selnode != NULL); *selnode = SCIPgetPrioChild(scip); if( *selnode == NULL ) { *selnode = SCIPgetPrioSibling(scip); if( *selnode == NULL ) { SCIPdebugMessage("select best leaf\n"); *selnode = SCIPgetBestLeaf(scip); } SCIPdebugMessage("select best sibling leaf\n"); } return SCIP_OKAY; }
/** node selection method of node selector */ static SCIP_DECL_NODESELSELECT(nodeselSelectBreadthfirst) { /*lint --e{715}*/ assert(nodesel != NULL); assert(strcmp(SCIPnodeselGetName(nodesel), NODESEL_NAME) == 0); assert(scip != NULL); assert(selnode != NULL); /* siblings come before leaves at the same level. Sometimes it can occur that no leaves are left except for children */ *selnode = SCIPgetBestSibling(scip); if( *selnode == NULL ) { *selnode = SCIPgetBestLeaf(scip); if( *selnode == NULL ) *selnode=SCIPgetBestChild(scip); } if( *selnode != NULL ) { SCIPdebugMessage("Selecting next node number %"SCIP_LONGINT_FORMAT" at depth %d\n", SCIPnodeGetNumber(*selnode), SCIPnodeGetDepth(*selnode)); } return SCIP_OKAY; }
/** node comparison method of node selector */ static SCIP_DECL_NODESELCOMP(nodeselCompBfs) { /*lint --e{715}*/ SCIP_Real lowerbound1; SCIP_Real lowerbound2; assert(nodesel != NULL); assert(strcmp(SCIPnodeselGetName(nodesel), NODESEL_NAME) == 0); assert(scip != NULL); lowerbound1 = SCIPnodeGetLowerbound(node1); lowerbound2 = SCIPnodeGetLowerbound(node2); if( SCIPisLT(scip, lowerbound1, lowerbound2) ) return -1; else if( SCIPisGT(scip, lowerbound1, lowerbound2) ) return +1; else { SCIP_Real estimate1; SCIP_Real estimate2; estimate1 = SCIPnodeGetEstimate(node1); estimate2 = SCIPnodeGetEstimate(node2); if( (SCIPisInfinity(scip, estimate1) && SCIPisInfinity(scip, estimate2)) || (SCIPisInfinity(scip, -estimate1) && SCIPisInfinity(scip, -estimate2)) || SCIPisEQ(scip, estimate1, estimate2) ) { SCIP_NODETYPE nodetype1; SCIP_NODETYPE nodetype2; nodetype1 = SCIPnodeGetType(node1); nodetype2 = SCIPnodeGetType(node2); if( nodetype1 == SCIP_NODETYPE_CHILD && nodetype2 != SCIP_NODETYPE_CHILD ) return -1; else if( nodetype1 != SCIP_NODETYPE_CHILD && nodetype2 == SCIP_NODETYPE_CHILD ) return +1; else if( nodetype1 == SCIP_NODETYPE_SIBLING && nodetype2 != SCIP_NODETYPE_SIBLING ) return -1; else if( nodetype1 != SCIP_NODETYPE_SIBLING && nodetype2 == SCIP_NODETYPE_SIBLING ) return +1; else { int depth1; int depth2; depth1 = SCIPnodeGetDepth(node1); depth2 = SCIPnodeGetDepth(node2); if( depth1 < depth2 ) return -1; else if( depth1 > depth2 ) return +1; else return 0; } } if( SCIPisLT(scip, estimate1, estimate2) ) return -1; assert(SCIPisGT(scip, estimate1, estimate2)); return +1; } }
/** node selection method of node selector */ static SCIP_DECL_NODESELSELECT(nodeselSelectBfs) { /*lint --e{715}*/ SCIP_NODESELDATA* nodeseldata; int minplungedepth; int maxplungedepth; int plungedepth; SCIP_Real maxplungequot; assert(nodesel != NULL); assert(strcmp(SCIPnodeselGetName(nodesel), NODESEL_NAME) == 0); assert(scip != NULL); assert(selnode != NULL); *selnode = NULL; /* get node selector user data */ nodeseldata = SCIPnodeselGetData(nodesel); assert(nodeseldata != NULL); /* calculate minimal and maximal plunging depth */ minplungedepth = nodeseldata->minplungedepth; maxplungedepth = nodeseldata->maxplungedepth; maxplungequot = nodeseldata->maxplungequot; if( minplungedepth == -1 ) { minplungedepth = SCIPgetMaxDepth(scip)/10; if( SCIPgetNStrongbranchLPIterations(scip) > 2*SCIPgetNNodeLPIterations(scip) ) minplungedepth += 10; if( maxplungedepth >= 0 ) minplungedepth = MIN(minplungedepth, maxplungedepth); } if( maxplungedepth == -1 ) maxplungedepth = SCIPgetMaxDepth(scip)/2; maxplungedepth = MAX(maxplungedepth, minplungedepth); /* check, if we exceeded the maximal plunging depth */ plungedepth = SCIPgetPlungeDepth(scip); if( plungedepth > maxplungedepth ) { /* we don't want to plunge again: select best node from the tree */ SCIPdebugMessage("plungedepth: [%d,%d], cur: %d -> abort plunging\n", minplungedepth, maxplungedepth, plungedepth); *selnode = SCIPgetBestNode(scip); SCIPdebugMessage(" -> best node : lower=%g\n", *selnode != NULL ? SCIPnodeGetLowerbound(*selnode) : SCIPinfinity(scip)); } else { SCIP_NODE* node; SCIP_Real maxbound; /* check, if plunging is forced at the current depth */ if( plungedepth < minplungedepth ) { maxbound = SCIPinfinity(scip); SCIPdebugMessage("plungedepth: [%d,%d], cur: %d => maxbound: infinity\n", minplungedepth, maxplungedepth, plungedepth); } else { SCIP_Real lowerbound; SCIP_Real cutoffbound; /* get global lower and cutoff bound */ lowerbound = SCIPgetLowerbound(scip); cutoffbound = SCIPgetCutoffbound(scip); /* if we didn't find a solution yet, the cutoff bound is usually very bad: * use only 20% of the gap as cutoff bound */ if( SCIPgetNSolsFound(scip) == 0 ) cutoffbound = lowerbound + 0.2 * (cutoffbound - lowerbound); /* calculate maximal plunging bound */ maxbound = lowerbound + maxplungequot * (cutoffbound - lowerbound); SCIPdebugMessage("plungedepth: [%d,%d], cur: %d, bounds: [%g,%g], maxbound: %g\n", minplungedepth, maxplungedepth, plungedepth, lowerbound, cutoffbound, maxbound); } /* we want to plunge again: prefer children over siblings, and siblings over leaves, * but only select a child or sibling, if its dual bound is small enough; * prefer using nodes with higher node selection priority assigned by the branching rule */ node = SCIPgetPrioChild(scip); if( node != NULL && SCIPnodeGetLowerbound(node) < maxbound ) { *selnode = node; SCIPdebugMessage(" -> selected prio child: lower=%g\n", SCIPnodeGetLowerbound(*selnode)); } else { node = SCIPgetBestChild(scip); if( node != NULL && SCIPnodeGetLowerbound(node) < maxbound ) { *selnode = node; SCIPdebugMessage(" -> selected best child: lower=%g\n", SCIPnodeGetLowerbound(*selnode)); } else { node = SCIPgetPrioSibling(scip); if( node != NULL && SCIPnodeGetLowerbound(node) < maxbound ) { *selnode = node; SCIPdebugMessage(" -> selected prio sibling: lower=%g\n", SCIPnodeGetLowerbound(*selnode)); } else { node = SCIPgetBestSibling(scip); if( node != NULL && SCIPnodeGetLowerbound(node) < maxbound ) { *selnode = node; SCIPdebugMessage(" -> selected best sibling: lower=%g\n", SCIPnodeGetLowerbound(*selnode)); } else { *selnode = SCIPgetBestNode(scip); SCIPdebugMessage(" -> selected best leaf: lower=%g\n", *selnode != NULL ? SCIPnodeGetLowerbound(*selnode) : SCIPinfinity(scip)); } } } } } return SCIP_OKAY; }
/** node selection method of node selector */ static SCIP_DECL_NODESELSELECT(nodeselSelectMaster) { SCIP_NODESELDATA* nodeseldata; SCIP_NODE** nodes; SCIP_CONS* origcons; SCIP_CONS* parentorigcons; SCIP_CONS* parentmastercons; SCIP* origscip; int nnodes; SCIP_Longint orignodenumber; assert(nodesel != NULL); assert(strcmp(SCIPnodeselGetName(nodesel), NODESEL_NAME) == 0); assert(scip != NULL); assert(selnode != NULL); nodeseldata = SCIPnodeselGetData(nodesel); assert(nodeseldata != NULL); origscip = GCGpricerGetOrigprob(scip); *selnode = NULL; orignodenumber = SCIPnodeGetNumber(SCIPgetCurrentNode(origscip)); if( orignodenumber != nodeseldata->lastorignodenumber ) { nodeseldata->lastorignodenumber = orignodenumber; origcons = GCGconsOrigbranchGetActiveCons(origscip); parentorigcons = GCGconsOrigbranchGetParentcons(origcons); /* check whether the current node is the root node and has no parent */ if( parentorigcons == NULL ) { assert((GCGconsOrigbranchGetNode(origcons) == SCIPgetRootNode(origscip)) || ( GCGconsOrigbranchGetNode(origcons) == NULL) ); assert(GCGconsOrigbranchGetMastercons(origcons) != NULL); assert((GCGconsMasterbranchGetNode(GCGconsOrigbranchGetMastercons(origcons)) == SCIPgetRootNode(scip)) || (GCGconsMasterbranchGetNode(GCGconsOrigbranchGetMastercons(origcons)) == NULL)); *selnode = SCIPgetRootNode(scip); SCIPdebugMessage("selected root node in the master program\n"); } else { parentmastercons = GCGconsOrigbranchGetMastercons(parentorigcons); assert(parentmastercons != NULL); assert( (GCGconsOrigbranchGetChild1cons(parentorigcons) == origcons) != (GCGconsOrigbranchGetChild2cons(parentorigcons) == origcons)); /* the original cons is the left child of its parentcons, select the left child of the corresponding parentcons in the master*/ if( GCGconsOrigbranchGetChild1cons(parentorigcons) == origcons ) { assert(GCGconsMasterbranchGetChild1cons(parentmastercons) != NULL); assert(GCGconsMasterbranchGetNode(GCGconsMasterbranchGetChild1cons(parentmastercons)) != NULL); *selnode = GCGconsMasterbranchGetNode(GCGconsMasterbranchGetChild1cons(parentmastercons)); SCIPdebugMessage("Master nodeselector selected node %"SCIP_LONGINT_FORMAT" corresponding to node %"SCIP_LONGINT_FORMAT" in the original program, since the parents (%"SCIP_LONGINT_FORMAT"/o, %"SCIP_LONGINT_FORMAT"/m) are linked\n", SCIPnodeGetNumber(*selnode), SCIPnodeGetNumber(GCGconsOrigbranchGetNode(origcons)), SCIPnodeGetNumber(GCGconsOrigbranchGetNode(parentorigcons)), SCIPnodeGetNumber(GCGconsMasterbranchGetNode(parentmastercons))); } /* the original cons is the right child of its parentcons, select the right child of the corresponding parentcons in the master */ else { assert(GCGconsOrigbranchGetChild2cons(parentorigcons) == origcons); assert(GCGconsMasterbranchGetChild2cons(parentmastercons) != NULL); assert(GCGconsMasterbranchGetNode(GCGconsMasterbranchGetChild2cons(parentmastercons)) != NULL); *selnode = GCGconsMasterbranchGetNode(GCGconsMasterbranchGetChild2cons(parentmastercons)); SCIPdebugMessage("Master nodeselector selected node %"SCIP_LONGINT_FORMAT" corresponding to node %"SCIP_LONGINT_FORMAT" in the original program, since the parents (%"SCIP_LONGINT_FORMAT"/o, %"SCIP_LONGINT_FORMAT"/m) are linked\n", SCIPnodeGetNumber(*selnode), SCIPnodeGetNumber(GCGconsOrigbranchGetNode(origcons)), SCIPnodeGetNumber(GCGconsOrigbranchGetNode(parentorigcons)), SCIPnodeGetNumber(GCGconsMasterbranchGetNode(parentmastercons))); } } if( *selnode == NULL ) { SCIPerrorMessage("nodesel_master could not find a node corresponding to the current original node!\n"); } assert(*selnode != NULL); /* set the dual bound to the lower bound of the corresponding original node */ SCIP_CALL( SCIPupdateNodeDualbound(scip, *selnode, SCIPgetNodeLowerbound(origscip, SCIPgetCurrentNode(origscip))) ); } else { SCIPdebugMessage("select random node\n"); if( SCIPgetNChildren(scip) > 0 ) { SCIP_CALL( SCIPgetChildren(scip, &nodes, &nnodes) ); *selnode = nodes[0]; } else if( SCIPgetNSiblings(scip) > 0 ) { SCIP_CALL( SCIPgetSiblings(scip, &nodes, &nnodes) ); *selnode = nodes[0]; } else if( SCIPgetNLeaves(scip) > 0 ) { SCIP_CALL( SCIPgetLeaves(scip, &nodes, &nnodes) ); *selnode = nodes[0]; } } #ifndef NDEBUG GCGconsOrigbranchCheckConsistency(origscip); GCGconsMasterbranchCheckConsistency(scip); #endif return SCIP_OKAY; }