/** branching execution method for not completely fixed pseudo solutions */ static SCIP_DECL_BRANCHEXECPS(branchExecpsAllfullstrong) { /*lint --e{715}*/ assert(result != NULL); SCIPdebugMessage("Execps method of allfullstrong branching\n"); *result = SCIP_DIDNOTRUN; if( SCIPhasCurrentNodeLP(scip) ) { SCIP_CALL( branch(scip, branchrule, allowaddcons, result) ); } return SCIP_OKAY; }
/** copies the given separator to a new scip */ SCIP_RETCODE SCIPsepaCopyInclude( SCIP_SEPA* sepa, /**< separator */ SCIP_SET* set /**< SCIP_SET of SCIP to copy to */ ) { assert(sepa != NULL); assert(set != NULL); assert(set->scip != NULL); if( sepa->sepacopy != NULL ) { SCIPdebugMessage("including separator %s in subscip %p\n", SCIPsepaGetName(sepa), (void*)set->scip); SCIP_CALL( sepa->sepacopy(set->scip, sepa) ); } return SCIP_OKAY; }
/** copies the given presolver to a new scip */ SCIP_RETCODE SCIPpresolCopyInclude( SCIP_PRESOL* presol, /**< presolver */ SCIP_SET* set /**< SCIP_SET of SCIP to copy to */ ) { assert(presol != NULL); assert(set != NULL); assert(set->scip != NULL); if( presol->presolcopy != NULL ) { SCIPdebugMessage("including presolver %s in subscip %p\n", SCIPpresolGetName(presol), (void*)set->scip); SCIP_CALL( presol->presolcopy(set->scip, presol) ); } return SCIP_OKAY; }
/** adds all constraints in conjunction constraints to the problem; disables unmodifiable conjunction constraints */ static SCIP_RETCODE addAllConss( SCIP* scip, /**< SCIP data structure */ SCIP_CONS** conss, /**< active conjunction constraints */ int nconss, /**< number of active conjunction constraints */ SCIP_RESULT* result /**< pointer to store the result */ ) { SCIP_CONSDATA* consdata; int c; int i; assert(result != NULL); for( c = 0; c < nconss; ++c ) { consdata = SCIPconsGetData(conss[c]); assert(consdata != NULL); /* add all inactive constraints to local subproblem */ for( i = 0; i < consdata->nconss; ++i ) { /* update check flag for sub constraints when upgrade takes place */ if( SCIPconsIsChecked(conss[c]) ) { /* make sure, the constraint is checked for feasibility */ SCIP_CALL( SCIPsetConsChecked(scip, consdata->conss[i], TRUE) ); } if( !SCIPconsIsActive(consdata->conss[i]) ) { SCIPdebugMessage("adding constraint <%s> from add conjunction <%s>\n", SCIPconsGetName(consdata->conss[i]), SCIPconsGetName(conss[c])); SCIP_CALL( SCIPaddConsLocal(scip, consdata->conss[i], NULL) ); *result = SCIP_CONSADDED; } } /* disable conjunction constraint, if it is unmodifiable */ if( !SCIPconsIsModifiable(conss[c]) ) { SCIP_CALL( SCIPdelConsLocal(scip, conss[c]) ); } } return SCIP_OKAY; }
/** exit method of constraint handler (called before problem is free transformed) */ static SCIP_DECL_CONSEXIT(consExitOrigbranch) { /*lint --e{715}*/ SCIP_CONSHDLRDATA* conshdlrdata; assert(conshdlr != NULL); assert(scip != NULL); conshdlrdata = SCIPconshdlrGetData(conshdlr); assert(conshdlrdata != NULL); SCIPdebugMessage("exiting transformed branch orig constraint handler\n"); if( conshdlrdata->rootcons != NULL ) { SCIP_CALL( SCIPreleaseCons(scip, &conshdlrdata->rootcons) ); conshdlrdata->rootcons = NULL; } return SCIP_OKAY; }
/** copies the given primal heuristic to a new scip */ SCIP_RETCODE SCIPheurCopyInclude( SCIP_HEUR* heur, /**< primal heuristic */ SCIP_SET* set /**< SCIP_SET of SCIP to copy to */ ) { assert(heur != NULL); assert(set != NULL); assert(set->scip != NULL); if( heur->heurcopy != NULL ) { SCIPdebugMessage("including heur %s in subscip %p\n", SCIPheurGetName(heur), (void*)set->scip); SCIP_CALL( heur->heurcopy(set->scip, heur) ); } return SCIP_OKAY; }
/** copies the given tree compression to a new scip */ SCIP_RETCODE SCIPcomprCopyInclude( SCIP_COMPR* compr, /**< tree compression */ SCIP_SET* set /**< SCIP_SET of SCIP to copy to */ ) { assert(compr != NULL); assert(set != NULL); assert(set->scip != NULL); if( compr->comprcopy != NULL ) { SCIPdebugMessage("including compr %s in subscip %p\n", SCIPcomprGetName(compr), (void*)set->scip); SCIP_CALL( compr->comprcopy(set->scip, compr) ); } return SCIP_OKAY; }
/** clears the separation storage without adding the cuts to the LP */ SCIP_RETCODE SCIPsepastoreClearCuts( SCIP_SEPASTORE* sepastore, /**< separation storage */ BMS_BLKMEM* blkmem, /**< block memory */ SCIP_SET* set, /**< global SCIP settings */ SCIP_EVENTQUEUE* eventqueue, /**< event queue */ SCIP_EVENTFILTER* eventfilter, /**< event filter for global events */ SCIP_LP* lp /**< LP data */ ) { int c; assert(sepastore != NULL); SCIPdebugMessage("clearing %d cuts\n", sepastore->nforcedcuts + sepastore->ncuts); /* release cuts */ for( c = 0; c < sepastore->ncuts; ++c ) { /* check, if the row deletions from separation storage events are tracked * if so, issue ROWDELETEDSEPA event */ if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDSEPA) != 0 ) { SCIP_EVENT* event; SCIP_CALL( SCIPeventCreateRowDeletedSepa(&event, blkmem, sepastore->cuts[c]) ); SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) ); } SCIP_CALL( SCIProwRelease(&sepastore->cuts[c], blkmem, set, lp) ); } /* reset counters */ sepastore->ncuts = 0; sepastore->nforcedcuts = 0; sepastore->ncutsfoundround = 0; /* if we have just finished the initial LP construction, free the (potentially large) cuts array */ if( sepastore->initiallp ) { BMSfreeMemoryArrayNull(&sepastore->cuts); sepastore->cutssize = 0; } return SCIP_OKAY; }
/** copies the given pricer to a new scip */ SCIP_RETCODE SCIPpricerCopyInclude( SCIP_PRICER* pricer, /**< pricer */ SCIP_SET* set, /**< SCIP_SET of SCIP to copy to */ SCIP_Bool* valid /**< was the copying process valid? */ ) { assert(pricer != NULL); assert(set != NULL); assert(valid != NULL); assert(set->scip != NULL); if( pricer->pricercopy != NULL ) { SCIPdebugMessage("including pricer %s in subscip %p\n", SCIPpricerGetName(pricer), (void*)set->scip); SCIP_CALL( pricer->pricercopy(set->scip, pricer, valid) ); } return SCIP_OKAY; }
/** reads the masterconss section */ static SCIP_RETCODE readMasterconss( SCIP* scip, /**< SCIP data structure */ DECINPUT* decinput, /**< DEC reading data */ SCIP_READERDATA* readerdata /**< reader data */ ) { assert(scip != NULL); assert(decinput != NULL); assert(readerdata != NULL); while( getNextToken(decinput) ) { SCIP_CONS* cons; /* check if we reached a new section */ if( isNewSection(scip, decinput) ) break; /* the token must be the name of an existing constraint */ cons = SCIPfindCons(scip, decinput->token); if( cons == NULL ) { syntaxError(scip, decinput, "unknown constraint in masterconss section"); break; } else { if( !SCIPhashmapExists( readerdata->constoblock, cons) ) { SCIPwarningMessage(scip, "Cons <%s> has been deleted by presolving, skipping.\n", SCIPconsGetName(cons)); continue; } assert(SCIPhashmapGetImage(readerdata->constoblock, cons) == (void*)(size_t) LINKINGVALUE); SCIPdebugMessage("cons %s is linking constraint\n", decinput->token); } } return SCIP_OKAY; }
/** adds a bound change on an original variable found by propagation in the original problem * to the given origbranch constraint so that it will be transferred to the master problem */ SCIP_RETCODE GCGconsOrigbranchAddPropBoundChg( SCIP* scip, /**< SCIP data structure */ SCIP_CONS* cons, /**< origbranch constraint to which the bound change is added */ SCIP_VAR* var, /**< variable on which the bound change was performed */ SCIP_BOUNDTYPE boundtype, /**< bound type of the bound change */ SCIP_Real newbound /**< new bound of the variable after the bound change */ ) { SCIP_CONSDATA* consdata; assert(scip != NULL); assert(cons != NULL); assert(var != NULL); consdata = SCIPconsGetData(cons); assert(consdata != NULL); /* realloc the arrays, if needed */ if( consdata->npropbounds >= consdata->maxpropbounds ) { consdata->maxpropbounds = consdata->npropbounds+5; SCIP_CALL( SCIPreallocMemoryArray(scip, &(consdata->propvars), consdata->maxpropbounds) ); SCIP_CALL( SCIPreallocMemoryArray(scip, &(consdata->propboundtypes), consdata->maxpropbounds) ); SCIP_CALL( SCIPreallocMemoryArray(scip, &(consdata->propbounds), consdata->maxpropbounds) ); } SCIPdebugMessage("Bound change stored at branch orig constraint: <%s>.\n", SCIPconsGetName(cons)); /* store the new bound change */ consdata->propvars[consdata->npropbounds] = var; consdata->propboundtypes[consdata->npropbounds] = boundtype; consdata->propbounds[consdata->npropbounds] = newbound; consdata->npropbounds++; /* mark the corresponding master node to be repropagated */ if( consdata->mastercons != NULL ) { SCIP_CALL( SCIPrepropagateNode(GCGrelaxGetMasterprob(scip), GCGconsMasterbranchGetNode(consdata->mastercons)) ); } return SCIP_OKAY; }
/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */ static SCIP_DECL_CONSEXITSOL(consExitsolOrigbranch) { /*lint --e{715}*/ SCIP_CONSHDLRDATA* conshdlrData; assert(scip != NULL); assert(conshdlr != NULL); assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0); conshdlrData = SCIPconshdlrGetData(conshdlr); assert(conshdlrData != NULL); assert(conshdlrData->nstack <= 1); SCIPdebugMessage("exiting solution process branch orig constraint handler\n"); /* free stack */ SCIPfreeMemoryArray(scip, &conshdlrData->stack); conshdlrData->stack = NULL; return SCIP_OKAY; }
/** frees a buffer */ void SCIPbufferFreeMem( SCIP_BUFFER* buffer, /**< memory buffer storage */ void** ptr, /**< pointer to the allocated memory buffer */ int dummysize /**< used to get a safer define for SCIPsetFreeBufferSize/Array */ ) { /*lint --e{715}*/ #ifndef SCIP_NOBUFFERMEM int bufnum; assert(buffer != NULL); assert(buffer->firstfree <= buffer->ndata); assert(buffer->firstfree >= 1); assert(dummysize == 0); /* Search the pointer in the buffer list * Usually, buffers are allocated and freed like a stack, such that the freed pointer is * most likely at the end of the buffer list. */ for( bufnum = buffer->firstfree-1; bufnum >= 0 && buffer->data[bufnum] != *ptr; --bufnum ) { } assert(bufnum >= 0); assert(buffer->data[bufnum] == *ptr); assert(buffer->used[bufnum]); *ptr = NULL; buffer->used[bufnum] = FALSE; while( buffer->firstfree > 0 && !buffer->used[buffer->firstfree-1] ) buffer->firstfree--; SCIPdebugMessage("freed buffer %d/%d at %p of size %d for pointer %p, first free is %d\n", bufnum, buffer->ndata, buffer->data[bufnum], buffer->size[bufnum], (void*)ptr, buffer->firstfree); #else BMSfreeMemory(ptr); #endif }
/** execution method of event handler */ static SCIP_DECL_EVENTEXEC(eventExecProbdatavardeleted) { SCIP_VAR* var; SCIP_PROBDATA* probdata; int idx; assert(SCIPeventGetType(event) == SCIP_EVENTTYPE_VARDELETED); var = SCIPeventGetVar(event); probdata = (SCIP_PROBDATA*) eventdata; assert(probdata != NULL); assert(var != NULL); /* get index of variable in stablesets array */ idx = (int)(size_t) SCIPvarGetData(var); SCIPdebugMessage("remove variable %s [%d] from list of stable sets\n", SCIPvarGetName(var), idx); assert(probdata->stablesetvars[idx] == var); /* remove variable from stablesets array and release it */ SCIPfreeBlockMemoryArray(scip, &(probdata->stablesets[idx]), probdata->stablesetlengths[idx]); /*lint !e866*/ SCIP_CALL( SCIPreleaseVar(scip, &(probdata->stablesetvars[idx])) ); /* move all subsequent variables to the front */ for( ; idx < probdata->nstablesets - 1; idx++) { probdata->stablesets[idx] = probdata->stablesets[idx + 1]; probdata->stablesetlengths[idx] = probdata->stablesetlengths[idx + 1]; probdata->stablesetvars[idx] = probdata->stablesetvars[idx + 1]; SCIPvarSetData(probdata->stablesetvars[idx], (SCIP_VARDATA*) (size_t) idx); /*lint !e571*/ } probdata->nstablesets--; return SCIP_OKAY; }/*lint !e715*/
/** reset variables' bounds violated by zero to its original value */ SCIP_RETCODE SCIPpricestoreResetBounds( SCIP_PRICESTORE* pricestore, /**< pricing storage */ BMS_BLKMEM* blkmem, /**< block memory */ SCIP_SET* set, /**< global SCIP settings */ SCIP_STAT* stat, /**< problem statistics */ SCIP_LP* lp, /**< LP data */ SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */ SCIP_EVENTQUEUE* eventqueue /**< event queue */ ) { SCIP_VAR* var; int v; assert(pricestore != NULL); assert(set != NULL); assert(lp != NULL); assert(pricestore->nvars == 0); assert(pricestore->naddedbdviolvars == pricestore->nbdviolvars); /* reset variables' bounds, release them, and clear the boundviolation storage; * the inference information is unimportant in these removals of temporary bound changes */ for( v = 0; v < pricestore->nbdviolvars; ++v ) { var = pricestore->bdviolvars[v]; assert(var != NULL); SCIPdebugMessage("resetting bounds of <%s> from [%g,%g] to [%g,%g]\n", var->name, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), pricestore->bdviolvarslb[v], pricestore->bdviolvarsub[v]); SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, pricestore->bdviolvarslb[v]) ); SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, pricestore->bdviolvarsub[v]) ); SCIP_CALL( SCIPvarRelease(&pricestore->bdviolvars[v], blkmem, set, eventqueue, lp) ); } pricestore->naddedbdviolvars = 0; pricestore->nbdviolvars = 0; 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; }
/** adds given variable to the problem data */ SCIP_RETCODE SCIPprobdataAddVar( SCIP* scip, /**< SCIP data structure */ SCIP_PROBDATA* probdata, /**< problem data */ SCIP_VAR* var /**< variables to add */ ) { /* check if enough memory is left */ if( probdata->varssize == probdata->nvars ) { probdata->varssize = MAX(100, probdata->varssize * 2); SCIP_CALL( SCIPreallocMemoryArray(scip, &probdata->vars, probdata->varssize) ); } /* caputure variables */ SCIP_CALL( SCIPcaptureVar(scip, var) ); probdata->vars[probdata->nvars] = var; probdata->nvars++; SCIPdebugMessage("added variable to probdata; nvars = %d\n", probdata->nvars); return SCIP_OKAY; }
/** 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)); }
/* exec the event handler * * we interrupt the solution process */ static SCIP_DECL_EVENTEXEC(eventExecLocalbranching) { SCIP_HEURDATA* heurdata; assert(eventhdlr != NULL); assert(eventdata != NULL); assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0); assert(event != NULL); assert(SCIPeventGetType(event) & SCIP_EVENTTYPE_LPSOLVED); heurdata = (SCIP_HEURDATA*)eventdata; assert(heurdata != NULL); /* interrupt solution process of sub-SCIP */ if( SCIPgetNLPs(scip) > heurdata->lplimfac * heurdata->nodelimit ) { SCIPdebugMessage("interrupt after %"SCIP_LONGINT_FORMAT" LPs\n",SCIPgetNLPs(scip)); SCIP_CALL( SCIPinterruptSolve(scip) ); } return SCIP_OKAY; }
/** branching execution method for not completely fixed pseudo solutions */ static SCIP_DECL_BRANCHEXECPS(branchExecpsInference) { /*lint --e{715}*/ SCIP_BRANCHRULEDATA* branchruledata; SCIP_VAR** cands; int ncands; SCIPdebugMessage("Execps method of inference branching\n"); /* get branching rule data */ branchruledata = SCIPbranchruleGetData(branchrule); assert(branchruledata != NULL); /* get pseudo candidates (non-fixed integer variables) */ SCIP_CALL( SCIPgetPseudoBranchCands(scip, &cands, NULL, &ncands) ); /* perform the branching */ SCIP_CALL( performBranching(scip, cands, NULL, ncands, branchruledata->conflictweight, branchruledata->inferenceweight, branchruledata->cutoffweight, branchruledata->reliablescore, branchruledata->useweightedsum, result) ); return SCIP_OKAY; }
/** applies an upper bound change */ static SCIP_RETCODE sepastoreApplyUb( SCIP_SEPASTORE* sepastore, /**< separation storage */ BMS_BLKMEM* blkmem, /**< block memory */ SCIP_SET* set, /**< global SCIP settings */ SCIP_STAT* stat, /**< problem statistics */ SCIP_TREE* tree, /**< branch and bound tree */ SCIP_LP* lp, /**< LP data */ SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */ SCIP_EVENTQUEUE* eventqueue, /**< event queue */ SCIP_VAR* var, /**< problem variable */ SCIP_Real bound, /**< new upper bound of variable */ SCIP_Bool* cutoff /**< pointer to store TRUE, if an infeasibility has been detected */ ) { assert(sepastore != NULL); assert(cutoff != NULL); if( SCIPsetIsLT(set, bound, SCIPvarGetUbLocal(var)) ) { SCIPdebugMessage(" -> applying bound change: <%s>: [%g,%g] -> [%g,%g]\n", SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), SCIPvarGetLbLocal(var), bound); if( SCIPsetIsFeasGE(set, bound, SCIPvarGetLbLocal(var)) ) { SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(tree), blkmem, set, stat, tree, lp, branchcand, eventqueue, var, bound, SCIP_BOUNDTYPE_UPPER, FALSE) ); } else *cutoff = TRUE; if( !sepastore->initiallp ) sepastore->ncutsapplied++; } return SCIP_OKAY; }
/** calls reduced cost pricing method of variable pricer */ SCIP_RETCODE SCIPpricerRedcost( SCIP_PRICER* pricer, /**< variable pricer */ SCIP_SET* set, /**< global SCIP settings */ SCIP_PROB* prob, /**< transformed problem */ SCIP_Real* lowerbound, /**< local lower bound computed by the pricer */ SCIP_RESULT* result /**< result of the pricing process */ ) { int oldnvars; assert(pricer != NULL); assert(pricer->active); assert(pricer->pricerredcost != NULL); assert(set != NULL); assert(prob != NULL); assert(lowerbound != NULL); assert(result != NULL); SCIPdebugMessage("executing reduced cost pricing of variable pricer <%s>\n", pricer->name); oldnvars = prob->nvars; /* start timing */ SCIPclockStart(pricer->pricerclock, set); /* call external method */ SCIP_CALL( pricer->pricerredcost(set->scip, pricer, lowerbound, result) ); /* stop timing */ SCIPclockStop(pricer->pricerclock, set); /* evaluate result */ pricer->ncalls++; pricer->nvarsfound += prob->nvars - oldnvars; return SCIP_OKAY; }
/** execution method of event handler */ static SCIP_DECL_EVENTEXEC(eventExecBestsol) { /*lint --e{715}*/ SCIP_SOL* bestsol; SCIP_Real solvalue; assert(eventhdlr != NULL); assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0); assert(event != NULL); assert(scip != NULL); assert(SCIPeventGetType(event) == SCIP_EVENTTYPE_BESTSOLFOUND); SCIPdebugMessage("exec method of event handler for best solution found\n"); bestsol = SCIPgetBestSol(scip); assert(bestsol != NULL); solvalue = SCIPgetSolOrigObj(scip, bestsol); /* print best solution value */ SCIPinfoMessage(scip, NULL, "found new best solution with solution value <%g> in SCIP <%s>\n", solvalue, SCIPgetProbName(scip) ); return SCIP_OKAY; }
/** read fixed variables */ static SCIP_RETCODE getFixedVariables( SCIP* scip, /**< SCIP data structure */ CIPINPUT* cipinput /**< CIP parsing data */ ) { char* buf; buf = cipinput->strbuf; if( strncmp(buf, "CONSTRAINTS", 11) == 0 ) cipinput->section = CIP_CONSTRAINTS; else if( strncmp(buf, "END", 3) == 0 ) cipinput->section = CIP_END; if( cipinput->section != CIP_FIXEDVARS ) return SCIP_OKAY; SCIPdebugMessage("parse fixed variables\n"); /* @todo implement parsing of fixed variables, in case of some constraints that use these variables */ return SCIP_OKAY; }
/** calls Farkas pricing method of variable pricer */ SCIP_RETCODE SCIPpricerFarkas( SCIP_PRICER* pricer, /**< variable pricer */ SCIP_SET* set, /**< global SCIP settings */ SCIP_PROB* prob /**< transformed problem */ ) { int oldnvars; assert(pricer != NULL); assert(pricer->active); assert(set != NULL); assert(prob != NULL); /* check, if pricer implemented a Farkas pricing algorithm */ if( pricer->pricerfarkas == NULL ) return SCIP_OKAY; SCIPdebugMessage("executing Farkas pricing of variable pricer <%s>\n", pricer->name); oldnvars = prob->nvars; /* start timing */ SCIPclockStart(pricer->pricerclock, set); /* call external method */ SCIP_CALL( pricer->pricerfarkas(set->scip, pricer) ); /* stop timing */ SCIPclockStop(pricer->pricerclock, set); /* evaluate result */ pricer->ncalls++; pricer->nvarsfound += prob->nvars - oldnvars; return SCIP_OKAY; }
/** adds priced variables to the LP */ SCIP_RETCODE SCIPpricestoreApplyVars( SCIP_PRICESTORE* pricestore, /**< pricing storage */ BMS_BLKMEM* blkmem, /**< block memory buffers */ SCIP_SET* set, /**< global SCIP settings */ SCIP_STAT* stat, /**< dynamic problem statistics */ SCIP_EVENTQUEUE* eventqueue, /**< event queue */ SCIP_PROB* prob, /**< transformed problem after presolve */ SCIP_TREE* tree, /**< branch and bound tree */ SCIP_LP* lp /**< LP data */ ) { SCIP_VAR* var; SCIP_COL* col; int v; assert(pricestore != NULL); assert(pricestore->naddedbdviolvars <= pricestore->nbdviolvars); assert(set != NULL); assert(prob != NULL); assert(lp != NULL); assert(tree != NULL); assert(SCIPtreeIsFocusNodeLPConstructed(tree)); SCIPdebugMessage("adding %d variables (%d bound violated and %d priced vars) to %d LP columns\n", SCIPpricestoreGetNVars(pricestore), pricestore->nbdviolvars - pricestore->naddedbdviolvars, pricestore->nvars, SCIPlpGetNCols(lp)); /* add the variables with violated bounds to LP */ for( v = pricestore->naddedbdviolvars; v < pricestore->nbdviolvars; ++v ) { var = pricestore->bdviolvars[v]; assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN); assert(SCIPvarGetProbindex(var) >= 0); assert(var->nuses >= 2); /* at least used in pricing storage and in problem */ if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE ) { /* transform loose variable into column variable */ SCIP_CALL( SCIPvarColumn(var, blkmem, set, stat, prob, lp) ); } assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN); col = SCIPvarGetCol(var); assert(col != NULL); assert(col->lppos == -1); SCIPdebugMessage("adding bound violated variable <%s> (lb=%g, ub=%g)\n", SCIPvarGetName(var), pricestore->bdviolvarslb[v], pricestore->bdviolvarsub[v]); SCIP_CALL( SCIPlpAddCol(lp, set, col, SCIPtreeGetCurrentDepth(tree)) ); if( !pricestore->initiallp ) pricestore->nvarsapplied++; } pricestore->naddedbdviolvars = pricestore->nbdviolvars; /* add the selected pricing variables to LP */ for( v = 0; v < pricestore->nvars; ++v ) { var = pricestore->vars[v]; assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN); assert(SCIPvarGetProbindex(var) >= 0); assert(var->nuses >= 2); /* at least used in pricing storage and in problem */ /* transform variable into column variable, if needed */ if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE ) { SCIP_CALL( SCIPvarColumn(var, blkmem, set, stat, prob, lp) ); } assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN); col = SCIPvarGetCol(var); assert(col != NULL); assert(col->lppos == -1); SCIPdebugMessage("adding priced variable <%s> (score=%g)\n", SCIPvarGetName(var), pricestore->scores[v]); SCIP_CALL( SCIPlpAddCol(lp, set, col, SCIPtreeGetCurrentDepth(tree)) ); /* release the variable */ SCIP_CALL( SCIPvarRelease(&pricestore->vars[v], blkmem, set, eventqueue, lp) ); if( !pricestore->initiallp ) pricestore->nvarsapplied++; } /* clear the pricing storage */ pricestore->nvars = 0; return SCIP_OKAY; }
/** adds problem variables with negative reduced costs to pricing storage */ SCIP_RETCODE SCIPpricestoreAddProbVars( SCIP_PRICESTORE* pricestore, /**< pricing storage */ BMS_BLKMEM* blkmem, /**< block memory buffers */ SCIP_SET* set, /**< global SCIP settings */ SCIP_STAT* stat, /**< dynamic problem statistics */ SCIP_PROB* prob, /**< transformed problem after presolve */ SCIP_TREE* tree, /**< branch and bound tree */ SCIP_LP* lp, /**< LP data */ SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */ SCIP_EVENTQUEUE* eventqueue /**< event queue */ ) { SCIP_VAR* var; SCIP_COL* col; SCIP_Bool root; SCIP_Bool added; int v; int abortpricevars; int maxpricevars; int nfoundvars; assert(pricestore != NULL); assert(set != NULL); assert(stat != NULL); assert(prob != NULL); assert(lp != NULL); assert(lp->solved); assert(tree != NULL); assert(SCIPtreeHasCurrentNodeLP(tree)); assert(prob->nvars >= SCIPlpGetNCols(lp)); /* if all problem variables of status COLUMN are already in the LP, nothing has to be done */ if( prob->ncolvars == SCIPlpGetNCols(lp) ) return SCIP_OKAY; root = (SCIPtreeGetCurrentDepth(tree) == 0); maxpricevars = SCIPsetGetPriceMaxvars(set, root); assert(maxpricevars >= 1); abortpricevars = (int)(set->price_abortfac * maxpricevars); assert(abortpricevars >= maxpricevars); /**@todo test pricing: is abortpricevars a good idea? -> like strong branching, lookahead, ... */ pricestore->nprobpricings++; /* start timing */ SCIPclockStart(pricestore->probpricingtime, set); /* price already existing problem variables */ nfoundvars = 0; for( v = 0; v < prob->nvars && nfoundvars < abortpricevars; ++v ) { var = prob->vars[v]; if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN ) { col = SCIPvarGetCol(var); assert(col != NULL); assert(col->var == var); assert(col->len >= 0); assert(col->lppos >= -1); assert(col->lpipos >= -1); assert(SCIPcolIsInLP(col) == (col->lpipos >= 0)); if( !SCIPcolIsInLP(col) ) { SCIPdebugMessage("price column variable <%s> in bounds [%g,%g]\n", SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)); /* add variable to pricing storage, if zero is not best bound w.r.t. objective function */ SCIP_CALL( addBoundViolated(pricestore, blkmem, set, stat, tree, lp, branchcand, eventqueue, var, &added) ); if( added ) { pricestore->nprobvarsfound++; nfoundvars++; } else if( SCIPcolGetNNonz(col) > 0 ) { SCIP_Real feasibility; /* a column not in LP that doesn't have zero in its bounds was added by bound checking above */ assert(!SCIPsetIsPositive(set, SCIPvarGetLbLocal(col->var))); assert(!SCIPsetIsNegative(set, SCIPvarGetUbLocal(col->var))); if( SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_INFEASIBLE ) { /* The LP was proven infeasible, so we have an infeasibility proof by the dual Farkas multipliers y. * The valid inequality y^T A x >= y^T b is violated by all x, especially by the (for this * inequality most feasible solution) x' defined by * x'_i = ub_i, if y^T A_i > 0 * x'_i = lb_i, if y^T A_i <= 0. * Pricing in this case means to add variables i with positive Farkas value, i.e. y^T A_i x'_i > 0 */ feasibility = -SCIPcolGetFarkasValue(col, stat, lp); SCIPdebugMessage(" <%s> Farkas feasibility: %e\n", SCIPvarGetName(col->var), feasibility); } else { /* The dual LP is feasible, and we have a feasible dual solution. Pricing in this case means to * add variables with negative feasibility, that is * - positive reduced costs for variables with negative lower bound * - negative reduced costs for variables with positive upper bound */ feasibility = SCIPcolGetFeasibility(col, set, stat, lp); SCIPdebugMessage(" <%s> reduced cost feasibility: %e\n", SCIPvarGetName(col->var), feasibility); } /* the score is -feasibility / (#nonzeros in column + 1) to prefer short columns * we must add variables with negative feasibility, but in order to not get a too large lower bound * due to missing columns, we better also add variables, that have a very small feasibility */ if( !SCIPsetIsPositive(set, feasibility) ) { SCIP_CALL( SCIPpricestoreAddVar(pricestore, blkmem, set, eventqueue, lp, var, -feasibility / (col->len+1), root) ); pricestore->nprobvarsfound++; nfoundvars++; } } } } } /* stop timing */ SCIPclockStop(pricestore->probpricingtime, set); return SCIP_OKAY; }
/** adds variable to pricing storage and capture it */ SCIP_RETCODE SCIPpricestoreAddVar( SCIP_PRICESTORE* pricestore, /**< pricing storage */ BMS_BLKMEM* blkmem, /**< block memory */ SCIP_SET* set, /**< global SCIP settings */ SCIP_EVENTQUEUE* eventqueue, /**< event queue */ SCIP_LP* lp, /**< LP data */ SCIP_VAR* var, /**< priced variable */ SCIP_Real score, /**< pricing score of variable (the larger, the better the variable) */ SCIP_Bool root /**< are we at the root node? */ ) { int maxpricevars; int v; assert(pricestore != NULL); assert(set != NULL); assert(var != NULL); #ifndef NDEBUG /* check if we add this variables to the same scip, where we created it */ if( var->scip != set->scip ) { SCIPerrorMessage("try to add a variable of another scip instance\n"); return SCIP_INVALIDDATA; } #endif SCIPdebugMessage("adding variable <%s> (lb=%g, ub=%g) to pricing storage (initiallp=%u)\n", SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), pricestore->initiallp); if( pricestore->initiallp ) maxpricevars = INT_MAX; else { pricestore->nvarsfound++; maxpricevars = SCIPsetGetPriceMaxvars(set, root); } assert(maxpricevars >= 1); assert(pricestore->nvars <= maxpricevars); /* check, if variable belongs to the best "maxpricevars" pricing variables */ if( pricestore->nvars < maxpricevars || score > pricestore->scores[maxpricevars-1] ) { /* capture variable */ SCIPvarCapture(var); /* if the array consists of "maxpricevars" variables, release the worst variables */ if( pricestore->nvars == maxpricevars ) { SCIP_CALL( SCIPvarRelease(&pricestore->vars[pricestore->nvars-1], blkmem, set, eventqueue, lp) ); pricestore->nvars--; } assert(pricestore->nvars < maxpricevars); /* get enough memory to store additional variable */ SCIP_CALL( pricestoreEnsureVarsMem(pricestore, set, pricestore->nvars+1) ); assert(pricestore->nvars <= pricestore->varssize); /* insert the variable at the correct position in sorted arrays */ for( v = pricestore->nvars; v > 0 && score > pricestore->scores[v-1]; --v ) { pricestore->vars[v] = pricestore->vars[v-1]; pricestore->scores[v] = pricestore->scores[v-1]; } pricestore->vars[v] = var; pricestore->scores[v] = score; pricestore->nvars++; } return SCIP_OKAY; }
/** domain propagation method of constraint handler */ static SCIP_DECL_CONSPROP(consPropSamediff) { /*lint --e{715}*/ SCIP_PROBDATA* probdata; SCIP_CONSDATA* consdata; SCIP_VAR** vars; int nvars; int c; assert(scip != NULL); assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0); SCIPdebugMessage("propagation constraints of constraint handler <"CONSHDLR_NAME">\n"); probdata = SCIPgetProbData(scip); assert(probdata != NULL); vars = SCIPprobdataGetVars(probdata); nvars = SCIPprobdataGetNVars(probdata); *result = SCIP_DIDNOTFIND; for( c = 0; c < nconss; ++c ) { consdata = SCIPconsGetData(conss[c]); #ifndef NDEBUG { /* check if there are no equal consdatas */ SCIP_CONSDATA* consdata2; int i; for( i = c+1; i < nconss; ++i ) { consdata2 = SCIPconsGetData(conss[i]); assert( !(consdata->itemid1 == consdata2->itemid1 && consdata->itemid2 == consdata2->itemid2 && consdata->type == consdata2->type) ); assert( !(consdata->itemid1 == consdata2->itemid2 && consdata->itemid2 == consdata2->itemid1 && consdata->type == consdata2->type) ); } } #endif if( !consdata->propagated ) { SCIPdebugMessage("propagate constraint <%s> ", SCIPconsGetName(conss[c])); SCIPdebug( consdataPrint(scip, consdata, NULL) ); SCIP_CALL( consdataFixVariables(scip, consdata, vars, nvars, result) ); consdata->npropagations++; if( *result != SCIP_CUTOFF ) { consdata->propagated = TRUE; consdata->npropagatedvars = nvars; } else break; } /* check if constraint is completely propagated */ assert( consdataCheck(scip, probdata, consdata) ); } return SCIP_OKAY; }
/** fixes a variable to zero if the corresponding packings are not valid for this constraint/node (due to branching) */ static SCIP_RETCODE checkVariable( SCIP* scip, /**< SCIP data structure */ SCIP_CONSDATA* consdata, /**< constraint data */ SCIP_VAR* var, /**< variables to check */ int* nfixedvars, /**< pointer to store the number of fixed variables */ SCIP_Bool* cutoff /**< pointer to store if a cutoff was detected */ ) { SCIP_VARDATA* vardata; int* consids; int nconsids; SCIP_Bool existid1; SCIP_Bool existid2; CONSTYPE type; SCIP_Bool fixed; SCIP_Bool infeasible; int pos; assert(scip != NULL); assert(consdata != NULL); assert(var != NULL); assert(nfixedvars != NULL); assert(cutoff != NULL); /* if variables is locally fixed to zero continue */ if( SCIPvarGetUbLocal(var) < 0.5 ) return SCIP_OKAY; /* check if the packing which corresponds to the variable feasible for this constraint */ vardata = SCIPvarGetData(var); nconsids = SCIPvardataGetNConsids(vardata); consids = SCIPvardataGetConsids(vardata); existid1 = SCIPsortedvecFindInt(consids, consdata->itemid1, nconsids, &pos); existid2 = SCIPsortedvecFindInt(consids, consdata->itemid2, nconsids, &pos); type = consdata->type; if( (type == SAME && existid1 != existid2) || (type == DIFFER && existid1 && existid2) ) { SCIP_CALL( SCIPfixVar(scip, var, 0.0, &infeasible, &fixed) ); if( infeasible ) { assert( SCIPvarGetLbLocal(var) > 0.5 ); SCIPdebugMessage("-> cutoff\n"); (*cutoff) = TRUE; } else { assert(fixed); (*nfixedvars)++; } } return SCIP_OKAY; }