/** adds a new stable set, the set must be sorted descendingly, * attention: you need to check whether it is new before adding it */ SCIP_RETCODE COLORprobAddNewStableSet( SCIP* scip, /**< SCIP data structure */ int* stablesetnodes, /**< array of nodes in the stable set */ int nstablesetnodes, /**< number of nodes in the stable set */ int* setindex /**< return value: index of the stable set */ ) { SCIP_PROBDATA* probdata; int newsize; int i; assert(stablesetnodes != NULL); assert(scip != NULL); probdata = SCIPgetProbData(scip); assert(probdata != NULL); /* the set should be sorted descendingly */ #ifndef NDEBUG for ( i = 0; i < nstablesetnodes-2; i++ ) { assert(stablesetnodes[i]>stablesetnodes[i+1]); } #endif /* ensure that array is big enough */ if ( (probdata->nstablesets + 1) > probdata->maxstablesets) { newsize = 2* probdata->maxstablesets; assert(newsize > probdata->nstablesets + 1); SCIP_CALL( SCIPreallocMemoryArray(scip, &(probdata->stablesets), newsize) ); SCIP_CALL( SCIPreallocMemoryArray(scip, &(probdata->stablesetlengths), newsize) ); SCIP_CALL( SCIPreallocMemoryArray(scip, &(probdata->stablesetvars), newsize) ); probdata->maxstablesets = newsize; SCIPdebugMessage("Set-array resized: %d --> %d\n", newsize/2, newsize); } /* alloc memory for the new stable set */ SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(probdata->stablesets[probdata->nstablesets]), nstablesetnodes) ); /*lint !e866*/ probdata->stablesetlengths[probdata->nstablesets] = nstablesetnodes; probdata->stablesetvars[probdata->nstablesets] = NULL; for ( i = 0; i < nstablesetnodes; i++ ) { assert(stablesetnodes[i] >= 0); probdata->stablesets[probdata->nstablesets][i] = stablesetnodes[i]; } *setindex = probdata->nstablesets; probdata->nstablesets++; 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; }
/** 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; }
/** 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; }
/** reads a block section */ static SCIP_RETCODE readBlock( SCIP* scip, /**< SCIP data structure */ BLKINPUT* blkinput, /**< BLK reading data */ SCIP_READERDATA* readerdata /**< reader data */ ) { int blockid; assert(blkinput != NULL); blockid = blkinput->blocknr; while( getNextToken(blkinput) ) { SCIP_VAR* var; int varidx; int oldblock; /* check if we reached a new section */ if( isNewSection(scip, blkinput) ) return SCIP_OKAY; /* the token must be the name of an existing variable */ var = SCIPfindVar(scip, blkinput->token); if( var == NULL ) { syntaxError(scip, blkinput, "unknown variable in block section"); return SCIP_OKAY; } varidx = SCIPvarGetProbindex(var); oldblock = readerdata->varstoblock[varidx]; /* set the block number of the variable to the number of the current block */ if( oldblock == NOVALUE ) { SCIPdebugMessage("\tVar %s temporary in block %d.\n", SCIPvarGetName(var), blockid); readerdata->varstoblock[varidx] = blockid; ++(readerdata->nblockvars[blockid]); } /* variable was assigned to another (non-linking) block before, so it becomes a linking variable, now */ else if( (oldblock != LINKINGVALUE) ) { assert(oldblock != blockid); SCIPdebugMessage("\tVar %s is linking (old %d != %d new).\n", SCIPvarGetName(var), oldblock, blockid); readerdata->varstoblock[varidx] = LINKINGVALUE; /* decrease the number of variables in the old block and increase the number of linking variables */ --(readerdata->nblockvars[oldblock]); ++(readerdata->nlinkingvars); assert(readerdata->nlinkingvarsblocks[varidx] == 0); assert(readerdata->linkingvarsblocks[varidx] == NULL); SCIP_CALL( SCIPallocMemoryArray(scip, &readerdata->linkingvarsblocks[varidx], 2) ); /*lint !e506 !e866*/ readerdata->linkingvarsblocks[varidx][0] = oldblock; readerdata->linkingvarsblocks[varidx][1] = blockid; readerdata->nlinkingvarsblocks[varidx] = 2; } /* variable is a linking variable already, store the new block to which it belongs */ else { assert(oldblock == LINKINGVALUE); assert(readerdata->nlinkingvarsblocks[varidx] >= 2); assert(readerdata->linkingvarsblocks[varidx] != NULL); SCIP_CALL( SCIPreallocMemoryArray(scip, &readerdata->linkingvarsblocks[varidx], readerdata->nlinkingvarsblocks[varidx] + 1) ); /*lint !e866*/ readerdata->linkingvarsblocks[varidx][readerdata->nlinkingvarsblocks[varidx]] = blockid; ++(readerdata->nlinkingvarsblocks[varidx]); } } return SCIP_OKAY; }
/** reads an objective or constraint with name and coefficients */ static SCIP_RETCODE readCoefficients( SCIP* scip, /**< SCIP data structure */ LPINPUT* lpinput, /**< LP reading data */ SCIP_Bool isobjective, /**< indicates whether we are currently reading the coefficients of the objective */ char* name, /**< pointer to store the name of the line; must be at least of size * LP_MAX_LINELEN */ SCIP_VAR*** vars, /**< pointer to store the array with variables (must be freed by caller) */ SCIP_Real** coefs, /**< pointer to store the array with coefficients (must be freed by caller) */ int* ncoefs, /**< pointer to store the number of coefficients */ SCIP_Bool* newsection /**< pointer to store whether a new section was encountered */ ) { SCIP_Bool havesign; SCIP_Bool havevalue; SCIP_Real coef; int coefsign; int coefssize; assert(lpinput != NULL); assert(name != NULL); assert(vars != NULL); assert(coefs != NULL); assert(ncoefs != NULL); assert(newsection != NULL); *vars = NULL; *coefs = NULL; *name = '\0'; *ncoefs = 0; *newsection = FALSE; /* read the first token, which may be the name of the line */ if( getNextToken(scip, lpinput) ) { /* check if we reached a new section */ if( isNewSection(scip, lpinput) ) { *newsection = TRUE; return SCIP_OKAY; } /* remember the token in the token buffer */ swapTokenBuffer(lpinput); /* get the next token and check, whether it is a colon */ if( getNextToken(scip, lpinput) ) { if( strcmp(lpinput->token, ":") == 0 ) { /* the second token was a colon: the first token is the line name */ (void)SCIPmemccpy(name, lpinput->tokenbuf, '\0', LP_MAX_LINELEN); name[LP_MAX_LINELEN - 1] = '\0'; SCIPdebugMessage("(line %d) read constraint name: '%s'\n", lpinput->linenumber, name); } else { /* the second token was no colon: push the tokens back onto the token stack and parse them as coefficients */ pushToken(lpinput); pushBufferToken(lpinput); } } else { /* there was only one token left: push it back onto the token stack and parse it as coefficient */ pushBufferToken(lpinput); } } /* initialize buffers for storing the coefficients */ coefssize = LP_INIT_COEFSSIZE; SCIP_CALL( SCIPallocMemoryArray(scip, vars, coefssize) ); SCIP_CALL( SCIPallocMemoryArray(scip, coefs, coefssize) ); /* read the coefficients */ coefsign = +1; coef = 1.0; havesign = FALSE; havevalue = FALSE; *ncoefs = 0; while( getNextToken(scip, lpinput) ) { SCIP_VAR* var; /* check if we read a sign */ if( isSign(lpinput, &coefsign) ) { SCIPdebugMessage("(line %d) read coefficient sign: %+d\n", lpinput->linenumber, coefsign); havesign = TRUE; continue; } /* check if we read a value */ if( isValue(scip, lpinput, &coef) ) { SCIPdebugMessage("(line %d) read coefficient value: %g with sign %+d\n", lpinput->linenumber, coef, coefsign); if( havevalue ) { syntaxError(scip, lpinput, "two consecutive values."); return SCIP_OKAY; } havevalue = TRUE; continue; } /* check if we reached an equation sense */ if( isSense(lpinput, NULL) ) { if( isobjective ) { syntaxError(scip, lpinput, "no sense allowed in objective"); return SCIP_OKAY; } /* put the sense back onto the token stack */ pushToken(lpinput); break; } /* check if we reached a new section, that will be only allowed when having no current sign and value and if we * are not in the quadratic part */ if( (isobjective || (!havevalue && !havesign)) && isNewSection(scip, lpinput) ) { if( havesign && !havevalue ) { SCIPwarningMessage(scip, "skipped single sign %c without value or variable in objective\n", coefsign == 1 ? '+' : '-'); } else if( isobjective && havevalue && !SCIPisZero(scip, coef) ) { SCIPwarningMessage(scip, "constant term %+g in objective is skipped\n", coef * coefsign); } *newsection = TRUE; return SCIP_OKAY; } /* check if we start a quadratic part */ if( *lpinput->token == '[' ) { syntaxError(scip, lpinput, "diff reader does not support quadratic objective function."); return SCIP_READERROR; } /* all but the first coefficient need a sign */ if( *ncoefs > 0 && !havesign ) { syntaxError(scip, lpinput, "expected sign ('+' or '-') or sense ('<' or '>')."); return SCIP_OKAY; } /* check if the last variable should be squared */ if( *lpinput->token == '^' ) { syntaxError(scip, lpinput, "diff reader does not support quadratic objective function."); return SCIP_READERROR; } else { /* the token is a variable name: get the corresponding variable */ SCIP_CALL( getVariable(scip, lpinput->token, &var) ); } /* insert the linear coefficient */ SCIPdebugMessage("(line %d) read linear coefficient: %+g<%s>\n", lpinput->linenumber, coefsign * coef, SCIPvarGetName(var)); if( !SCIPisZero(scip, coef) ) { /* resize the vars and coefs array if needed */ if( *ncoefs >= coefssize ) { coefssize *= 2; coefssize = MAX(coefssize, (*ncoefs)+1); SCIP_CALL( SCIPreallocMemoryArray(scip, vars, coefssize) ); SCIP_CALL( SCIPreallocMemoryArray(scip, coefs, coefssize) ); } assert(*ncoefs < coefssize); /* add coefficient */ (*vars)[*ncoefs] = var; (*coefs)[*ncoefs] = coefsign * coef; (*ncoefs)++; } /* reset the flags and coefficient value for the next coefficient */ coefsign = +1; coef = 1.0; havesign = FALSE; havevalue = FALSE; } return SCIP_OKAY; }