/** separation method of constraint handler for LP solutions */ static SCIP_DECL_CONSSEPALP(consSepalpStp) { /*lint --e{715}*/ SCIP_CONSHDLRDATA* conshdlrdata; int maxcuts; int ncuts = 0; int i; *result = SCIP_DIDNOTRUN; conshdlrdata = SCIPconshdlrGetData(conshdlr); assert(conshdlrdata != NULL); maxcuts = SCIPnodeGetDepth(SCIPgetCurrentNode(scip)) == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts; for( i = 0; i < nconss; ++i ) { SCIP_CONSDATA* consdata; consdata = SCIPconsGetData(conss[i]); SCIP_CALL( sep_flow(scip, conshdlr, conshdlrdata, consdata, maxcuts, &ncuts) ); SCIP_CALL( sep_2cut(scip, conshdlr, conshdlrdata, consdata, maxcuts, &ncuts) ); } if( ncuts > 0 ) *result = SCIP_SEPARATED; return SCIP_OKAY; }
/** branching execution method for not completely fixed pseudo solutions */ static SCIP_DECL_BRANCHEXECPS(branchExecpsnodereopt) {/*lint --e{715}*/ assert(branchrule != NULL ); assert(*result != SCIP_BRANCHED); *result = SCIP_DIDNOTRUN; if( SCIPisReoptEnabled(scip) && SCIPreoptimizeNode(scip, SCIPgetCurrentNode(scip)) ) { assert((SCIPnodeGetReoptID(SCIPgetCurrentNode(scip)) == 0 && SCIPnodeGetDepth(SCIPgetCurrentNode(scip)) == 0 ) || 1 <= SCIPnodeGetReoptID(SCIPgetCurrentNode(scip))); SCIP_CALL( Exec(scip, result) ); } 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; }
/** branching execution method for external candidates */ static SCIP_DECL_BRANCHEXECEXT(branchExecextPscost) { /*lint --e{715}*/ SCIP_BRANCHRULEDATA* branchruledata; SCIP_VAR** externcands; SCIP_Real* externcandssol; SCIP_Real* externcandsscore; int nprioexterncands; SCIP_VAR* brvar; SCIP_Real brpoint; int nchildren; assert(branchrule != NULL); assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0); assert(scip != NULL); assert(result != NULL); branchruledata = SCIPbranchruleGetData(branchrule); assert(branchruledata != NULL); SCIPdebugMessage("Execext method of pscost branching\n"); /* get branching candidates */ SCIP_CALL( SCIPgetExternBranchCands(scip, &externcands, &externcandssol, &externcandsscore, NULL, &nprioexterncands, NULL, NULL, NULL) ); assert(nprioexterncands > 0); /* get current update strategy for pseudo costs, if our multiplier rule is 'u' */ if( branchruledata->strategy == 'u' ) { SCIP_CALL( SCIPgetCharParam(scip, "branching/lpgainnormalize", &branchruledata->updatestrategy) ); } /* select branching variable */ SCIP_CALL( selectBranchVar(scip, branchrule, externcands, externcandssol, externcandsscore, nprioexterncands, &brvar, &brpoint) ); if( brvar == NULL ) { SCIPerrorMessage("branchExecextPscost failed to select a branching variable from %d candidates\n", nprioexterncands); *result = SCIP_DIDNOTRUN; return SCIP_OKAY; } assert(SCIPvarIsActive(SCIPvarGetProbvar(brvar))); SCIPdebugMessage("branching on variable <%s>: new intervals: [%g, %g] and [%g, %g]\n", SCIPvarGetName(brvar), SCIPvarGetLbLocal(brvar), SCIPadjustedVarUb(scip, brvar, brpoint), SCIPadjustedVarLb(scip, brvar, brpoint), SCIPvarGetUbLocal(brvar)); if( branchruledata->nchildren > 2 && SCIPnodeGetDepth(SCIPgetCurrentNode(scip)) <= branchruledata->narymaxdepth ) { /* do n-ary branching */ SCIP_Real minwidth; minwidth = 0.0; if( !SCIPisInfinity(scip, -SCIPvarGetLbGlobal(brvar)) && !SCIPisInfinity(scip, SCIPvarGetUbGlobal(brvar)) ) minwidth = branchruledata->naryminwidth * (SCIPvarGetUbGlobal(brvar) - SCIPvarGetLbGlobal(brvar)); SCIP_CALL( SCIPbranchVarValNary(scip, brvar, brpoint, branchruledata->nchildren, minwidth, branchruledata->narywidthfactor, &nchildren) ); } else { /* do binary branching */ SCIP_CALL( SCIPbranchVarValNary(scip, brvar, brpoint, 2, 0.0, 1.0, &nchildren) ); } if( nchildren > 1 ) { *result = SCIP_BRANCHED; } else { /* if there are no children, then variable should have been fixed by SCIPbranchVarVal */ assert(SCIPisEQ(scip, SCIPvarGetLbLocal(brvar), SCIPvarGetUbLocal(brvar))); *result = SCIP_REDUCEDDOM; } return SCIP_OKAY; }
/** 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 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; }
/** 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; }
/** checks whether given row is valid for the debugging solution */ SCIP_RETCODE SCIPdebugCheckRow( SCIP_SET* set, /**< global SCIP settings */ SCIP_ROW* row /**< row to check for validity */ ) { SCIP_COL** cols; SCIP_Real* vals; SCIP_Real lhs; SCIP_Real rhs; int nnonz; int i; SCIP_Real minactivity; SCIP_Real maxactivity; SCIP_Real solval; assert(set != NULL); assert(row != NULL); /* check if we are in the original problem and not in a sub MIP */ if( !isSolutionInMip(set) ) return SCIP_OKAY; /* check if the incumbent solution is at least as good as the debug solution, so we can stop to check the debug solution */ if( debugSolIsAchieved(set) ) return SCIP_OKAY; /* if the row is only locally valid, check whether the debugging solution is contained in the local subproblem */ if( SCIProwIsLocal(row) ) { SCIP_Bool solcontained; SCIP_CALL( isSolutionInNode(SCIPblkmem(set->scip), set, SCIPgetCurrentNode(set->scip), &solcontained) ); if( !solcontained ) return SCIP_OKAY; } cols = SCIProwGetCols(row); vals = SCIProwGetVals(row); nnonz = SCIProwGetNNonz(row); lhs = SCIProwGetLhs(row); rhs = SCIProwGetRhs(row); /* calculate row's activity on debugging solution */ minactivity = SCIProwGetConstant(row); maxactivity = minactivity; for( i = 0; i < nnonz; ++i ) { SCIP_VAR* var; /* get solution value of variable in debugging solution */ var = SCIPcolGetVar(cols[i]); SCIP_CALL( getSolutionValue(set, var, &solval) ); if( solval != SCIP_UNKNOWN ) /*lint !e777*/ { minactivity += vals[i] * solval; maxactivity += vals[i] * solval; } else if( vals[i] > 0.0 ) { minactivity += vals[i] * SCIPvarGetLbGlobal(var); maxactivity += vals[i] * SCIPvarGetUbGlobal(var); } else if( vals[i] < 0.0 ) { minactivity += vals[i] * SCIPvarGetUbGlobal(var); maxactivity += vals[i] * SCIPvarGetLbGlobal(var); } } SCIPdebugMessage("debugging solution on row <%s>: %g <= [%g,%g] <= %g\n", SCIProwGetName(row), lhs, minactivity, maxactivity, rhs); /* check row for violation */ if( SCIPsetIsFeasLT(set, maxactivity, lhs) || SCIPsetIsFeasGT(set, minactivity, rhs) ) { printf("***** debug: row <%s> violates debugging solution (lhs=%.15g, rhs=%.15g, activity=[%.15g,%.15g], local=%d)\n", SCIProwGetName(row), lhs, rhs, minactivity, maxactivity, SCIProwIsLocal(row)); SCIProwPrint(row, NULL); /* output row with solution values */ printf("\n\n"); printf("***** debug: violated row <%s>:\n", SCIProwGetName(row)); printf(" %.15g <= %.15g", lhs, SCIProwGetConstant(row)); for( i = 0; i < nnonz; ++i ) { /* get solution value of variable in debugging solution */ SCIP_CALL( getSolutionValue(set, SCIPcolGetVar(cols[i]), &solval) ); printf(" %+.15g<%s>[%.15g]", vals[i], SCIPvarGetName(SCIPcolGetVar(cols[i])), solval); } printf(" <= %.15g\n", rhs); SCIPABORT(); } return SCIP_OKAY; }