/** reads the masterconss section */ static SCIP_RETCODE readMasterconss( SCIP* scip, /**< SCIP data structure */ BLKINPUT* blkinput, /**< BLK reading data */ SCIP_READERDATA* readerdata /**< reader data */ ) { assert(blkinput != NULL); while( getNextToken(blkinput) ) { SCIP_CONS* cons; /* check if we reached a new section */ if( isNewSection(scip, blkinput) ) return SCIP_OKAY; /* the token must be the name of an existing constraint */ cons = SCIPfindCons(scip, blkinput->token); if( cons == NULL ) { syntaxError(scip, blkinput, "unknown constraint in masterconss section"); return SCIP_OKAY; } else { assert(SCIPhashmapGetImage(readerdata->constoblock, cons) == (void*)(size_t)NOVALUE); SCIP_CALL( SCIPhashmapSetImage(readerdata->constoblock, cons, (void*)(size_t) (blkinput->nblocks +1)) ); } } return SCIP_OKAY; }
/** reads the nblocks section */ static SCIP_RETCODE readNBlocks( SCIP* scip, /**< SCIP data structure */ BLKINPUT* blkinput /**< BLK reading data */ ) { int nblocks; assert(scip != NULL); assert(blkinput != NULL); while( getNextToken(blkinput) ) { /* check if we reached a new section */ if( isNewSection(scip, blkinput) ) { if( blkinput->nblocks == NOVALUE ) syntaxError(scip, blkinput, "no integer value in nblocks section"); else return SCIP_OKAY; } /* read number of blocks */ if( isInt(scip, blkinput, &nblocks) ) { if( blkinput->nblocks == NOVALUE ) blkinput->nblocks = nblocks; else syntaxError(scip, blkinput, "2 integer values in nblocks section"); SCIPdebugMessage("Number of blocks = %d\n", blkinput->nblocks); } } return SCIP_OKAY; }
/** reads the presolved section */ static SCIP_RETCODE readPresolved( SCIP* scip, /**< SCIP data structure */ BLKINPUT* blkinput /**< DEC reading data */ ) { int presolved; assert(scip != NULL); assert(blkinput != NULL); while( getNextToken(blkinput) ) { /* check if we reached a new section */ if( isNewSection(scip, blkinput) ) return SCIP_OKAY; /* read number of blocks */ if( isInt(scip, blkinput, &presolved) ) { blkinput->haspresolvesection = TRUE; if( presolved == 1 ) blkinput->presolved = TRUE; else if ( presolved == 0 ) blkinput->presolved = FALSE; else syntaxError(scip, blkinput, "presolved parameter must be 0 or 1"); SCIPdebugMessage("Decomposition is%s from presolved problem\n", blkinput->presolved ? "" : " not"); } } return SCIP_OKAY; }
/** reads the header of the file */ static SCIP_RETCODE readStart( SCIP* scip, /**< SCIP data structure */ BLKINPUT* blkinput /**< BLK reading data */ ) { assert(blkinput != NULL); /* everything before first section is treated as comment */ do { /* get token */ if( !getNextToken(blkinput) ) return SCIP_OKAY; } while( !isNewSection(scip, blkinput) ); 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; }
/** 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; }
/** reads the blocks section */ static SCIP_RETCODE readBlock( SCIP* scip, /**< SCIP data structure */ DECINPUT* decinput, /**< DEC reading data */ SCIP_READERDATA* readerdata /**< reader data */ ) { int oldblock; int varidx; int consindex; int i; int blockid; int nvars; SCIP_CONS* cons; SCIP_VAR** vars; SCIP_Bool conshasvar; assert(decinput != NULL); assert(readerdata != NULL); while( getNextToken(decinput) ) { /* check if we reached a new section */ if( isNewSection(scip, decinput) ) break; /* the token must be the name of an existing cons */ cons = SCIPfindCons(scip, decinput->token); if( cons == NULL ) { syntaxError(scip, decinput, "unknown constraint in block section"); break; } conshasvar = FALSE; /* get all vars for the specific constraint */ nvars = SCIPgetNVarsXXX(scip, cons); vars = NULL; if( nvars > 0 ) { SCIP_CALL( SCIPallocMemoryArray(scip, &vars, nvars) ); SCIP_CALL( SCIPgetVarsXXX(scip, cons, vars, nvars) ); } blockid = decinput->blocknr; for( i = 0; i < nvars; i ++ ) { SCIP_VAR* var; assert(vars != NULL); /* for flexelint */ if( decinput->presolved ) { var = SCIPvarGetProbvar(vars[i]); if( !SCIPisVarRelevant(var) ) continue; } else var = vars[i]; conshasvar = TRUE; /* store for each var whether it is in none, one or more blocks */ varidx = SCIPvarGetProbindex(var); assert(varidx >= 0 && varidx < SCIPgetNVars(scip)); oldblock = readerdata->varstoblock[varidx]; assert(oldblock == NOVALUE || oldblock == LINKINGVALUE || (oldblock >= 0 && oldblock < decinput->nblocks)); /* variable was assigned to no block before, just assign it to the new block */ if( oldblock == NOVALUE ) { SCIPdebugMessage("\tVar %s temporary in block %d.\n", SCIPvarGetName(vars[i]), 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) && oldblock != blockid ) { SCIPdebugMessage("\tVar %s is linking (old %d != %d new).\n", SCIPvarGetName(vars[i]), oldblock, blockid); assert(oldblock != blockid); readerdata->varstoblock[varidx] = LINKINGVALUE; /* decrease the value again if it is a linking var */ --(readerdata->nblockvars[oldblock]); ++(readerdata->nlinkingvars); } } SCIPfreeMemoryArrayNull(scip, &vars); if( !conshasvar ) { assert(!SCIPhashmapExists(readerdata->constoblock, cons)); SCIPwarningMessage(scip, "Cons <%s> has been deleted by presolving, skipping.\n", SCIPconsGetName(cons)); continue; } /* * saving block <-> constraint */ /** @todo check if linking constraints are not in the subscipcons */ consindex = readerdata->nblockconss[blockid]; readerdata->blockconss[blockid][consindex] = cons; ++(readerdata->nblockconss[blockid]); assert(SCIPhashmapGetImage(readerdata->constoblock, cons) == (void*)(size_t) LINKINGVALUE); SCIPdebugMessage("cons %s is in block %d\n", SCIPconsGetName(cons), blockid); SCIP_CALL( SCIPhashmapSetImage(readerdata->constoblock, cons, (void*) ((size_t) blockid)) ); --(readerdata->nlinkingconss); } return SCIP_OKAY; }