/** adds initial constraint to root node */ SCIP_RETCODE SCIPconsOrigbranchAddRootCons( SCIP* scip /**< SCIP data structure */ ) { SCIP_CONSHDLR* conshdlr; SCIP_CONSHDLRDATA* conshdlrdata; SCIP_CONS* cons; assert(scip != NULL); conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME); if( conshdlr == NULL ) { SCIPerrorMessage("origbranch constraint handler not found\n"); return SCIP_ERROR; } conshdlrdata = SCIPconshdlrGetData(conshdlr); assert(conshdlrdata != NULL); if( conshdlrdata->rootcons == NULL ) { SCIP_CALL( GCGcreateConsOrigbranch(scip, &cons, "root-origbranch", NULL, NULL, NULL, NULL) ); SCIP_CALL( SCIPaddConsNode(scip, SCIPgetRootNode(scip), cons, SCIPgetRootNode(scip)) ); conshdlrdata->rootcons = cons; } /* check consistency */ GCGconsOrigbranchCheckConsistency(scip); return SCIP_OKAY; }
/** branching execution method for fractional LP solutions */ static SCIP_DECL_BRANCHEXECLP(branchExeclpnodereopt) {/*lint --e{715}*/ assert(branchrule != NULL ); assert(*result != SCIP_BRANCHED); *result = SCIP_DIDNOTRUN; if( SCIPisReoptEnabled(scip) && SCIPreoptimizeNode(scip, SCIPgetCurrentNode(scip)) ) { SCIP_VAR** branchcands; SCIP_Real* branchcandssol; SCIP_Real* branchcandsfrac; int nbranchcands; SCIP_Bool sbinit; SCIP_Real objsimrootlp; SCIP_CALL( SCIPgetBoolParam(scip, "reoptimization/strongbranchinginit", &sbinit) ); SCIP_CALL( SCIPgetRealParam(scip, "reoptimization/objsimrootLP", &objsimrootlp) ); if( sbinit && SCIPgetCurrentNode(scip) == SCIPgetRootNode(scip) && SCIPgetReoptSimilarity(scip, SCIPgetNReoptRuns(scip), SCIPgetNReoptRuns(scip)) <= objsimrootlp ) /* check objsimrootlp */ { /* get branching candidates */ SCIP_CALL( SCIPgetLPBranchCands(scip, &branchcands, &branchcandssol, &branchcandsfrac, NULL, &nbranchcands, NULL) ); /* run strong branching initialization */ if( nbranchcands > 0 ) { SCIP_CALL( SCIPexecRelpscostBranching(scip, TRUE, branchcands, branchcandssol, branchcandsfrac, nbranchcands, FALSE, result) ); assert(*result == SCIP_DIDNOTRUN || *result == SCIP_CUTOFF || *result == SCIP_REDUCEDDOM); } } if( *result != SCIP_CUTOFF && *result != SCIP_REDUCEDDOM) { assert((SCIPnodeGetReoptID(SCIPgetCurrentNode(scip)) == 0 && SCIPnodeGetDepth(SCIPgetCurrentNode(scip)) == 0 ) || 1 <= SCIPnodeGetReoptID(SCIPgetCurrentNode(scip))); SCIP_CALL( Exec(scip, result) ); } } return SCIP_OKAY; }
/** constraint activation notification method of constraint handler */ static SCIP_DECL_CONSACTIVE(consActiveOrigbranch) { /*lint --e{715}*/ SCIP_CONSHDLRDATA* conshdlrData; assert(scip != NULL); assert(conshdlr != NULL); assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0); assert(cons != NULL); conshdlrData = SCIPconshdlrGetData(conshdlr); assert(conshdlrData != NULL); assert(conshdlrData->stack != NULL); assert(SCIPconsGetData(cons) != NULL); if( SCIPconsGetData(cons)->node == NULL ) SCIPconsGetData(cons)->node = SCIPgetRootNode(scip); SCIPdebugMessage("Activating branch orig constraint: <%s>[stack size: %d].\n", SCIPconsGetName(cons), conshdlrData->nstack+1); /* put constraint on the stack */ if( conshdlrData->nstack >= conshdlrData->maxstacksize ) { SCIP_CALL( SCIPreallocMemoryArray(scip, &(conshdlrData->stack), 2*(conshdlrData->maxstacksize)) ); conshdlrData->maxstacksize = 2*(conshdlrData->maxstacksize); SCIPdebugMessage("reallocating Memory for stack! %d --> %d\n", conshdlrData->maxstacksize/2, conshdlrData->maxstacksize); } /* put constraint on the stack */ assert(conshdlrData->stack != NULL); conshdlrData->stack[conshdlrData->nstack] = cons; ++(conshdlrData->nstack); 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; }
/** 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; }