/** 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(nodeselCompMaster) { assert(nodesel != NULL); assert(strcmp(SCIPnodeselGetName(nodesel), NODESEL_NAME) == 0); assert(scip != NULL); if( SCIPnodeGetNumber(node1) < SCIPnodeGetNumber(node2) ) return 1; else return -1; }
/** constraint deactivation notification method of constraint handler */ static SCIP_DECL_CONSDEACTIVE(consDeactiveSamediff) { /*lint --e{715}*/ SCIP_CONSDATA* consdata; SCIP_PROBDATA* probdata; assert(scip != NULL); assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0); assert(cons != NULL); consdata = SCIPconsGetData(cons); assert(consdata != NULL); assert(consdata->propagated || SCIPgetNChildren(scip) == 0); probdata = SCIPgetProbData(scip); assert(probdata != NULL); /* check if all variables which are not fixed locally to zero are valid for this constraint/node */ assert( consdataCheck(scip, probdata, consdata) ); SCIPdebugMessage("deactivate constraint <%s> at node <%"SCIP_LONGINT_FORMAT"> in depth <%d>: ", SCIPconsGetName(cons), SCIPnodeGetNumber(consdata->node), SCIPnodeGetDepth(consdata->node)); SCIPdebug( consdataPrint(scip, consdata, NULL) ); /* set the number of propagated variables to current number of variables is SCIP */ consdata->npropagatedvars = SCIPprobdataGetNVars(probdata); /* check if all variables are valid for this constraint */ assert( consdataCheck(scip, probdata, consdata) ); return SCIP_OKAY; }
/** constraint activation notification method of constraint handler */ static SCIP_DECL_CONSACTIVE(consActiveSamediff) { /*lint --e{715}*/ SCIP_CONSDATA* consdata; assert(scip != NULL); assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0); assert(cons != NULL); consdata = SCIPconsGetData(cons); assert(consdata != NULL); assert(consdata->npropagatedvars <= SCIPprobdataGetNVars(SCIPgetProbData(scip))); SCIPdebugMessage("activate constraint <%s> at node <%"SCIP_LONGINT_FORMAT"> in depth <%d>: ", SCIPconsGetName(cons), SCIPnodeGetNumber(consdata->node), SCIPnodeGetDepth(consdata->node)); SCIPdebug( consdataPrint(scip, consdata, NULL) ); if( consdata->npropagatedvars != SCIPprobdataGetNVars(SCIPgetProbData(scip)) ) { SCIPdebugMessage("-> mark constraint to be repropagated\n"); consdata->propagated = FALSE; SCIP_CALL( SCIPrepropagateNode(scip, consdata->node) ); } return SCIP_OKAY; }
/** changes the color of the node to the color of nodes that were marked to be repropagated */ void SCIPvbcMarkedRepropagateNode( SCIP_VBC* vbc, /**< VBC information */ SCIP_STAT* stat, /**< problem statistics */ SCIP_NODE* node /**< node, that was marked to be repropagated */ ) { assert(node != NULL); /* vbc is disabled on probing nodes */ if( SCIPnodeGetType(node) == SCIP_NODETYPE_PROBINGNODE ) return; /* if the node number is zero, then SCIP is currently in probing and wants to mark a probing node; however this node * is not part of the search tree */ if( SCIPnodeGetNumber(node) > 0 ) vbcSetColor(vbc, stat, node, SCIP_VBCCOLOR_MARKREPROP); }
/** display constraints */ static void consdataPrint( SCIP* scip, /**< SCIP data structure */ SCIP_CONSDATA* consdata, /**< constraint data */ FILE* file /**< file stream */ ) { SCIP_PROBDATA* probdata; int* ids; probdata = SCIPgetProbData(scip); assert(probdata != NULL); ids = SCIPprobdataGetIds(probdata); assert(ids != NULL); SCIPinfoMessage(scip, file, "%s(%d,%d) at node %d\n", consdata->type == SAME ? "same" : "diff", ids[consdata->itemid1], ids[consdata->itemid2], SCIPnodeGetNumber(consdata->node) ); }
/** calculate score of a node given its feature and the policy weight vector */ void SCIPcalcNodeScore( SCIP_NODE* node, SCIP_FEAT* feat, SCIP_POLICY* policy ) { int offset = SCIPfeatGetOffset(feat); int i; SCIP_Real score = 0; SCIP_Real* weights = policy->weights; SCIP_Real* featvals = SCIPfeatGetVals(feat); if( (offset + SCIPfeatGetSize(feat)) > policy->size ) score = 0; else { for( i = 0; i < SCIPfeatGetSize(feat); i++ ) score += featvals[i] * weights[i+offset]; } SCIPnodeSetScore(node, score); SCIPdebugMessage("score of node #%"SCIP_LONGINT_FORMAT": %f\n", SCIPnodeGetNumber(node), SCIPnodeGetScore(node)); }
/** reduced cost propagation method for an LP solution */ static SCIP_DECL_PROPEXEC(propExecRedcost) { /*lint --e{715}*/ SCIP_PROPDATA* propdata; SCIP_COL** cols; SCIP_Real requiredredcost; SCIP_Real cutoffbound; SCIP_Real lpobjval; SCIP_Bool propbinvars; SCIP_Bool cutoff; int nchgbds; int ncols; int c; *result = SCIP_DIDNOTRUN; /* in case we have a zero objective function, we skip the reduced cost propagator */ if( SCIPgetNObjVars(scip) == 0 ) return SCIP_OKAY; /* propagator can only be applied during solving stage */ if( SCIPgetStage(scip) < SCIP_STAGE_SOLVING ) return SCIP_OKAY; /* we cannot apply reduced cost fixing, if we want to solve exactly */ /**@todo implement reduced cost fixing with interval arithmetics */ if( SCIPisExactSolve(scip) ) return SCIP_OKAY; /* only call propagator, if the current node has an LP */ if( !SCIPhasCurrentNodeLP(scip) ) return SCIP_OKAY; /* only call propagator, if an optimal LP solution is at hand */ if( SCIPgetLPSolstat(scip) != SCIP_LPSOLSTAT_OPTIMAL ) return SCIP_OKAY; /* only call propagator, if the current LP is a valid relaxation */ if( !SCIPisLPRelax(scip) ) return SCIP_OKAY; /* we cannot apply reduced cost strengthening, if no simplex basis is available */ if( !SCIPisLPSolBasic(scip) ) return SCIP_OKAY; /* get current cutoff bound */ cutoffbound = SCIPgetCutoffbound(scip); /* reduced cost strengthening can only be applied, if we have a finite cutoff */ if( SCIPisInfinity(scip, cutoffbound) ) return SCIP_OKAY; /* get LP columns */ cols = SCIPgetLPCols(scip); ncols = SCIPgetNLPCols(scip); /* do nothing if the LP has no columns (is empty) */ if( ncols == 0 ) return SCIP_OKAY; /* get propagator data */ propdata = SCIPpropGetData(prop); assert(propdata != NULL); /* chack if all integral variables are fixed and the continuous variables should not be propagated */ if( !propdata->continuous && SCIPgetNPseudoBranchCands(scip) == 0 ) return SCIP_OKAY; /* get LP objective value */ lpobjval = SCIPgetLPObjval(scip); /* check if binary variables should be propagated */ propbinvars = (SCIPgetDepth(scip) == 0) || (cutoffbound - lpobjval < 5 * propdata->maxredcost); /* skip the propagator if the problem has only binary variables and those should not be propagated */ if( !propbinvars && SCIPgetNVars(scip) == SCIPgetNBinVars(scip) ) return SCIP_OKAY; *result = SCIP_DIDNOTFIND; cutoff = FALSE; nchgbds = 0; /* compute the required reduced cost which are needed for a binary variable to be fixed */ requiredredcost = cutoffbound - lpobjval; SCIPdebugMessage("lpobjval <%g>, cutoffbound <%g>, max reduced <%g>, propgate binary %u, use implics %u\n", lpobjval, cutoffbound, propdata->maxredcost, propbinvars, propdata->usefullimplics); /* check reduced costs for non-basic columns */ for( c = 0; c < ncols && !cutoff; ++c ) { SCIP_VAR* var; var = SCIPcolGetVar(cols[c]); /* skip continuous variables in case the corresponding parameter is set */ if( !propdata->continuous && !SCIPvarIsIntegral(var) ) continue; if( SCIPvarIsBinary(var) ) { if( propbinvars ) { if( SCIPgetDepth(scip) == 0 ) { SCIP_CALL( propagateRootRedcostBinvar(scip, propdata, var, cols[c], cutoffbound, &nchgbds) ); } else { SCIP_CALL( propagateRedcostBinvar(scip, propdata, var, cols[c], requiredredcost, &nchgbds, &cutoff) ); } } } else { SCIP_CALL( propagateRedcostVar(scip, var, cols[c], lpobjval, cutoffbound, &nchgbds) ); } } if( cutoff ) { *result = SCIP_CUTOFF; SCIPdebugMessage("node %"SCIP_LONGINT_FORMAT": detected cutoff\n", SCIPnodeGetNumber(SCIPgetCurrentNode(scip))); } else if( nchgbds > 0 ) { *result = SCIP_REDUCEDDOM; SCIPdebugMessage("node %"SCIP_LONGINT_FORMAT": %d bound changes (max redcost <%g>)\n", SCIPnodeGetNumber(SCIPgetCurrentNode(scip)) , nchgbds, propdata->maxredcost); } 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; }
/** call writing method */ static SCIP_RETCODE writeBounds( SCIP* scip, /**< SCIP data structure */ FILE* file, /**< file to write to or NULL */ SCIP_Bool writesubmipdualbound/**< write dualbounds of submip roots for all open nodes */ ) { SCIP_NODE** opennodes; int nopennodes; int n; int v; assert(scip != NULL); nopennodes = -1; #ifdef LONGSTATS SCIPinfoMessage(scip, file, "Status after %"SCIP_LONGINT_FORMAT" processed nodes (%d open)\n", SCIPgetNNodes(scip), SCIPgetNNodesLeft(scip)); SCIPinfoMessage(scip, file, "Primalbound: %g\n", SCIPgetPrimalbound(scip)); SCIPinfoMessage(scip, file, "Dualbound: %g\n", SCIPgetDualbound(scip)); #else SCIPinfoMessage(scip, file, "PB %g\n", SCIPgetPrimalbound(scip)); #endif /* get all open nodes and therefor print all dualbounds */ for( v = 2; v >= 0; --v ) { SCIP_NODE* node; switch( v ) { case 2: SCIP_CALL( SCIPgetChildren(scip, &opennodes, &nopennodes) ); break; case 1: SCIP_CALL( SCIPgetSiblings(scip, &opennodes, &nopennodes) ); break; case 0: SCIP_CALL( SCIPgetLeaves(scip, &opennodes, &nopennodes) ); break; default: assert(0); break; } assert(nopennodes >= 0); /* print all node information */ for( n = nopennodes - 1; n >= 0 && !SCIPisStopped(scip); --n ) { node = opennodes[n]; if( writesubmipdualbound ) { SCIP* subscip; SCIP_Bool valid; SCIP_HASHMAP* varmap; /* mapping of SCIP variables to sub-SCIP variables */ SCIP_VAR** vars; /* original problem's variables */ int nvars; SCIP_Real submipdb; SCIP_Bool cutoff; SCIP_CALL( SCIPcreate(&subscip) ); SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) ); /* create the variable mapping hash map */ SCIP_CALL( SCIPhashmapCreate(&varmap, SCIPblkmem(subscip), SCIPcalcHashtableSize(5 * nvars)) ); submipdb = SCIP_INVALID; valid = FALSE; cutoff = FALSE; SCIP_CALL( SCIPcopy(scip, subscip, varmap, NULL, "__boundwriting", TRUE, FALSE, TRUE, &valid) ); if( valid ) { SCIP_VAR** branchvars; SCIP_Real* branchbounds; SCIP_BOUNDTYPE* boundtypes; int nbranchvars; int size; size = SCIPnodeGetDepth(node); /* allocate memory for all branching decisions */ SCIP_CALL( SCIPallocBufferArray(scip, &branchvars, size) ); SCIP_CALL( SCIPallocBufferArray(scip, &branchbounds, size) ); SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, size) ); /* we assume that we only have one branching decision at each node */ SCIPnodeGetAncestorBranchings( node, branchvars, branchbounds, boundtypes, &nbranchvars, size ); /* check if did not have enough memory */ if( nbranchvars > size ) { size = nbranchvars; SCIP_CALL( SCIPallocBufferArray(scip, &branchvars, size) ); SCIP_CALL( SCIPallocBufferArray(scip, &branchbounds, size) ); SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, size) ); /* now getting all information */ SCIPnodeGetAncestorBranchings( node, branchvars, branchbounds, boundtypes, &nbranchvars, size ); } /* apply all changes to the submip */ SCIP_CALL( applyDomainChanges(subscip, branchvars, branchbounds, boundtypes, nbranchvars, varmap) ); /* free memory for all branching decisions */ SCIPfreeBufferArray(scip, &boundtypes); SCIPfreeBufferArray(scip, &branchbounds); SCIPfreeBufferArray(scip, &branchvars); /* do not abort subproblem on CTRL-C */ SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) ); /* disable output to console */ SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) ); /* solve only root node */ SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", 1LL) ); /* set cutoffbound as objective limit for subscip */ SCIP_CALL( SCIPsetObjlimit(subscip, SCIPgetCutoffbound(scip)) ); SCIP_CALL( SCIPsolve(subscip) ); cutoff = (SCIPgetStatus(subscip) == SCIP_STATUS_INFEASIBLE); submipdb = SCIPgetDualbound(subscip) * SCIPgetTransObjscale(scip) + SCIPgetTransObjoffset(scip); } #ifdef LONGSTATS SCIPinfoMessage(scip, file, "Node %"SCIP_LONGINT_FORMAT" (depth %d): dualbound: %g, nodesubmiprootdualbound: %g %s\n", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), SCIPgetNodeDualbound(scip, node), submipdb, cutoff ? "(cutoff)" : ""); #else SCIPinfoMessage(scip, file, "%"SCIP_LONGINT_FORMAT" %d %g %g %s\n", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), SCIPgetNodeDualbound(scip, node), submipdb, cutoff ? "(cutoff)" : ""); #endif /* free hash map */ SCIPhashmapFree(&varmap); SCIP_CALL( SCIPfree(&subscip) ); } else { #ifdef LONGSTATS SCIPinfoMessage(scip, file, "Node %"SCIP_LONGINT_FORMAT" (depth %d): dualbound: %g\n", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), SCIPgetNodeDualbound(scip, node)); #else SCIPinfoMessage(scip, file, "%"SCIP_LONGINT_FORMAT" %d %g\n", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), SCIPgetNodeDualbound(scip, node)); #endif } } } #ifdef LONGSTATS SCIPinfoMessage(scip, file, "\n"); #endif return SCIP_OKAY; }
/** call writing method */ static SCIP_RETCODE writeBoundsFocusNode( SCIP* scip, /**< SCIP data structure */ SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */ ) { FILE* file; SCIP_Bool writesubmipdualbound; SCIP_NODE* node; assert(scip != NULL); assert(eventhdlrdata != NULL); file = eventhdlrdata->file; writesubmipdualbound = eventhdlrdata->writesubmipdualbound; node = SCIPgetCurrentNode(scip); /* do not process probing nodes */ if( SCIPnodeGetType(node) == SCIP_NODETYPE_PROBINGNODE ) return SCIP_OKAY; /* do not process cutoff nodes */ if( SCIPisInfinity(scip, SCIPgetNodeDualbound(scip, node)) ) return SCIP_OKAY; if( !SCIPisEQ(scip, eventhdlrdata->lastpb, SCIPgetPrimalbound(scip)) ) { #ifdef LONGSTATS SCIPinfoMessage(scip, file, "Status after %"SCIP_LONGINT_FORMAT" processed nodes (%d open)\n", SCIPgetNNodes(scip), SCIPgetNNodesLeft(scip)); SCIPinfoMessage(scip, file, "Primalbound: %g\n", SCIPgetPrimalbound(scip)); SCIPinfoMessage(scip, file, "Dualbound: %g\n", SCIPgetDualbound(scip)); #else SCIPinfoMessage(scip, file, "PB %g\n", SCIPgetPrimalbound(scip)); #endif eventhdlrdata->lastpb = SCIPgetPrimalbound(scip); } if( writesubmipdualbound ) { SCIP* subscip; SCIP_Bool valid; SCIP_Real submipdb; SCIP_Bool cutoff; SCIP_CALL( SCIPcreate(&subscip) ); submipdb = SCIP_INVALID; valid = FALSE; cutoff = FALSE; SCIP_CALL( SCIPcopy(scip, subscip, NULL, NULL, "__boundwriting", FALSE, FALSE, TRUE, &valid) ); if( valid ) { /* do not abort subproblem on CTRL-C */ SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) ); /* disable output to console */ SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) ); /* solve only root node */ SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", 1LL) ); #if 0 /* disable heuristics in subscip */ SCIP_CALL( SCIPsetHeuristics(subscip, SCIP_PARAMSETTING_OFF, TRUE) ); #endif /* set cutoffbound as objective limit for subscip */ SCIP_CALL( SCIPsetObjlimit(subscip, SCIPgetCutoffbound(scip)) ); SCIP_CALL( SCIPsolve(subscip) ); cutoff = (SCIPgetStatus(subscip) == SCIP_STATUS_INFEASIBLE); submipdb = SCIPgetDualbound(subscip) * SCIPgetTransObjscale(scip) + SCIPgetTransObjoffset(scip); } #ifdef LONGSTATS SCIPinfoMessage(scip, file, "Node %"SCIP_LONGINT_FORMAT" (depth %d): dualbound: %g, nodesubmiprootdualbound: %g %s\n", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), SCIPgetNodeDualbound(scip, node), submipdb, cutoff ? "(cutoff)" : ""); #else SCIPinfoMessage(scip, file, "%"SCIP_LONGINT_FORMAT" %d %g %g %s\n", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), SCIPgetNodeDualbound(scip, node), submipdb, cutoff ? "(cutoff)" : ""); #endif SCIP_CALL( SCIPfree(&subscip) ); } else { #ifdef LONGSTATS SCIPinfoMessage(scip, file, "Node %"SCIP_LONGINT_FORMAT" (depth %d): dualbound: %g\n", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), SCIPgetNodeDualbound(scip, node)); #else SCIPinfoMessage(scip, file, "%"SCIP_LONGINT_FORMAT" %d %g\n", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), SCIPgetNodeDualbound(scip, node)); #endif } #ifdef LONGSTATS SCIPinfoMessage(scip, file, "\n"); #endif 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; }
/** Execute the branching of nodes with additional constraints. */ static SCIP_RETCODE Exec( SCIP* scip, /**< SCIP data structure */ SCIP_RESULT* result /**< pointer to store the result */ ) { SCIP_REOPTNODE* reoptnode; SCIP_NODE* curnode; SCIP_REOPTTYPE reopttype; SCIP_Bool localrestart; unsigned int* childids; unsigned int curid; int naddedconss; int nchilds; int childnodessize; int ncreatednodes; int c; assert(scip != NULL ); assert(SCIPisReoptEnabled(scip)); curnode = SCIPgetCurrentNode(scip); assert(curnode != NULL); curid = SCIPnodeGetReoptID(curnode); assert(curid >= 1 || SCIPgetRootNode(scip) == curnode); /* calculate local similarity and delete the induced subtree if the similarity is to low */ localrestart = FALSE; SCIP_CALL( SCIPcheckReoptRestart(scip, curnode, &localrestart) ); ncreatednodes = 0; if( localrestart ) { *result = SCIP_DIDNOTRUN; goto TERMINATE; } SCIPdebugMessage("current node is %lld, ID %u:\n", SCIPnodeGetNumber(curnode), curid); /* get the corresponding node of the reoptimization tree */ reoptnode = SCIPgetReoptnode(scip, curid); assert(reoptnode != NULL); reopttype = (SCIP_REOPTTYPE)SCIPreoptnodeGetType(reoptnode); /* The current node is equal to the root and dual reductions were performed. Since the root has a special role * within the reoptimiziation we have to split the root node into several nodes and move all stored child nodes to * the one representing the root node including all dual reductions as before. * * @note If the type is infsubtree, there cannot exist a child node and the method SCIPapplyReopt adds a global valid * constraint only. */ if( curid == 0 ) { if( reopttype == SCIP_REOPTTYPE_STRBRANCHED || reopttype == SCIP_REOPTTYPE_INFSUBTREE ) { int ncreatedchilds; /* apply the reoptimization at the root node */ SCIP_CALL( SCIPsplitReoptRoot(scip, &ncreatedchilds, &naddedconss) ); if( reopttype == SCIP_REOPTTYPE_INFSUBTREE ) { assert(ncreatedchilds == 0); assert(naddedconss == 1); /* there is nothing to do */ *result = SCIP_DIDNOTRUN; goto TERMINATE; } assert(reopttype == SCIP_REOPTTYPE_STRBRANCHED); assert(ncreatedchilds >= 2); ncreatednodes += ncreatedchilds; /* We decrease the counter by one because after splitting the root node and moving all children to the node * representing the original root with all fixings (caused by dual reductions), we continue reactivating the * original children nodes of the root. Thus, the node containing all the fixings can be replaced by the children * nodes */ --ncreatednodes; } goto REVIVE; } /* if we reach this part of the code the current has to be different to the root node */ assert(curid >= 1); REVIVE: /* get the IDs of all child nodes */ childnodessize = SCIPreoptnodeGetNChildren(reoptnode); SCIP_CALL( SCIPallocBufferArray(scip, &childids, childnodessize) ); SCIP_CALL( SCIPgetReoptChildIDs(scip, curnode, childids, childnodessize, &nchilds) ); if( childnodessize < nchilds ) { childnodessize = SCIPreoptnodeGetNChildren(reoptnode); SCIP_CALL( SCIPreallocBufferArray(scip, &childids, childnodessize) ); SCIP_CALL( SCIPgetReoptChildIDs(scip, curnode, childids, childnodessize, &nchilds) ); } assert(nchilds <= childnodessize); naddedconss = 0; for(c = 0; c < nchilds; c++) { SCIP_NODE** childnodes; SCIP_Bool success; unsigned int childid; int ncreatedchilds; childid = childids[c]; assert(childid >= 1); SCIPdebugMessage("process child at ID %u\n", childid); reoptnode = SCIPgetReoptnode(scip, childid); assert(reoptnode != NULL); reopttype = (SCIP_REOPTTYPE)SCIPreoptnodeGetType(reoptnode); ncreatedchilds = 0; /* check whether node need to be split */ if( reopttype == SCIP_REOPTTYPE_STRBRANCHED || reopttype == SCIP_REOPTTYPE_INFSUBTREE ) { /* by default we assume the node get split into two node (because using a constraint to split the node is * the default case */ childnodessize = 2; } else { /* we only need to reconstruct the node */ childnodessize = 1; } /* allocate buffer */ SCIP_CALL( SCIPallocBufferArray(scip, &childnodes, childnodessize) ); /* apply the reoptimization */ SCIP_CALL( SCIPapplyReopt(scip, reoptnode, childid, SCIPnodeGetEstimate(curnode), childnodes, &ncreatedchilds, &naddedconss, childnodessize, &success) ); if( !success ) { assert(ncreatedchilds > childnodessize); /* reallocate buffer memory */ childnodessize = ncreatedchilds+1; SCIP_CALL( SCIPreallocBufferArray(scip, &childnodes, childnodessize) ); /* apply the reoptimization */ SCIP_CALL( SCIPapplyReopt(scip, reoptnode, childid, SCIPnodeGetEstimate(curnode), childnodes, &ncreatedchilds, &naddedconss, childnodessize, &success) ); } assert(success); /* free buffer memory */ SCIPfreeBufferArray(scip, &childnodes); ncreatednodes += ncreatedchilds; } if( ncreatednodes == 0 ) *result = SCIP_DIDNOTRUN; else *result = SCIP_BRANCHED; /* free the buffer memory */ SCIPfreeBufferArray(scip, &childids); TERMINATE: SCIPdebugMessage("**** finish reoptimizing %d child nodes of node %lld ****\n", ncreatednodes, SCIPnodeGetNumber(curnode)); return SCIP_OKAY; }
/** LP solution separation method of separator */ static SCIP_DECL_SEPAEXECLP(sepaExeclpClosecuts) { /*lint --e{715}*/ SCIP_SEPADATA* sepadata; SCIP_Longint currentnodenumber; SCIP_Bool isroot; assert( sepa != NULL ); assert( strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0 ); assert( result != NULL ); *result = SCIP_DIDNOTRUN; /* only call separator, if there are fractional variables */ if ( SCIPgetNLPBranchCands(scip) == 0 ) return SCIP_OKAY; sepadata = SCIPsepaGetData(sepa); assert( sepadata != NULL ); currentnodenumber = SCIPnodeGetNumber(SCIPgetCurrentNode(scip)); if ( sepadata->discardnode == currentnodenumber ) return SCIP_OKAY; isroot = FALSE; if (SCIPgetNNodes(scip) == 0) isroot = TRUE; /* only separate close cuts in the root if required */ if ( sepadata->separootonly || isroot ) { SCIP_SOL* point = NULL; SCIPdebugMessage("Separation method of closecuts separator.\n"); *result = SCIP_DIDNOTFIND; /* check whether we have to compute a relative interior point */ if ( sepadata->separelint ) { /* check if previous relative interior point should be forgotten, * otherwise it is computed only once and the same point is used for all nodes */ if ( sepadata->recomputerelint && sepadata->sepasol != NULL ) { SCIP_CALL( SCIPfreeSol(scip, &sepadata->sepasol) ); } if ( sepadata->sepasol == NULL ) { SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, 0, "Computing relative interior point (norm type: %c) ...\n", sepadata->relintnormtype); assert(sepadata->relintnormtype == 'o' || sepadata->relintnormtype == 's'); SCIP_CALL( SCIPcomputeLPRelIntPoint(scip, TRUE, sepadata->inclobjcutoff, sepadata->relintnormtype, &sepadata->sepasol) ); } } else { /* get best solution (NULL if not present) */ sepadata->sepasol = SCIPgetBestSol(scip); } /* separate close cuts */ if ( sepadata->sepasol != NULL ) { SCIPdebugMessage("Generating close cuts ... (combination value: %f)\n", sepadata->sepacombvalue); /* generate point to be separated */ SCIP_CALL( generateCloseCutPoint(scip, sepadata, &point) ); /* apply a separation round to generated point */ if ( point != NULL ) { int noldcuts; SCIP_Bool delayed; SCIP_Bool cutoff; noldcuts = SCIPgetNCuts(scip); SCIP_CALL( SCIPseparateSol(scip, point, isroot, FALSE, &delayed, &cutoff) ); SCIP_CALL( SCIPfreeSol(scip, &point) ); assert( point == NULL ); /* the cuts can be not violated by the current LP if the computed point is strange */ SCIP_CALL( SCIPremoveInefficaciousCuts(scip) ); if ( cutoff ) *result = SCIP_CUTOFF; else { if ( SCIPgetNCuts(scip) - noldcuts > sepadata->sepathreshold ) { sepadata->nunsuccessful = 0; *result = SCIP_NEWROUND; } else { if ( SCIPgetNCuts(scip) > noldcuts ) { sepadata->nunsuccessful = 0; *result = SCIP_SEPARATED; } else ++sepadata->nunsuccessful; } } SCIPdebugMessage("Separated close cuts: %d (enoughcuts: %d, unsuccessful: %d).\n", SCIPgetNCuts(scip) - noldcuts, SCIPgetNCuts(scip) - noldcuts > sepadata->sepathreshold, sepadata->nunsuccessful); if ( sepadata->maxunsuccessful >= 0 && sepadata->nunsuccessful > sepadata->maxunsuccessful ) { SCIPdebugMessage("Turn off close cut separation, because of %d unsuccessful calls.\n", sepadata->nunsuccessful); sepadata->discardnode = currentnodenumber; } } } } return SCIP_OKAY; }