/** 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; }
/** checks whether the current token is a section identifier, and if yes, switches to the corresponding section */ static SCIP_Bool isNewSection( SCIP* scip, /**< SCIP data structure */ BLKINPUT* blkinput /**< BLK reading data */ ) { SCIP_Bool iscolon; assert(blkinput != NULL); /* remember first token by swapping the token buffer */ swapTokenBuffer(blkinput); /* look at next token: if this is a ':', the first token is a name and no section keyword */ iscolon = FALSE; if( getNextToken(blkinput) ) { iscolon = (strcmp(blkinput->token, ":") == 0); pushToken(blkinput); } /* reinstall the previous token by swapping back the token buffer */ swapTokenBuffer(blkinput); /* check for ':' */ if( iscolon ) return FALSE; if( strcasecmp(blkinput->token, "PRESOLVED") == 0 ) { SCIPdebugMessage("(line %d) new section: PRESOLVED\n", blkinput->linenumber); blkinput->section = BLK_PRESOLVED; return TRUE; } if( strcasecmp(blkinput->token, "NBLOCKS") == 0 ) { SCIPdebugMessage("(line %d) new section: NBLOCKS\n", blkinput->linenumber); blkinput->section = BLK_NBLOCKS; return TRUE; } if( strcasecmp(blkinput->token, "BLOCK") == 0 ) { int blocknr; blkinput->section = BLK_BLOCK; if( getNextToken(blkinput) ) { /* read block number */ if( isInt(scip, blkinput, &blocknr) ) { assert(blocknr >= 0); assert(blocknr <= blkinput->nblocks); blkinput->blocknr = blocknr-1; } else syntaxError(scip, blkinput, "no block number after block keyword!\n"); } else syntaxError(scip, blkinput, "no block number after block keyword!\n"); SCIPdebugMessage("new section: BLOCK %d\n", blkinput->blocknr); return TRUE; } if( strcasecmp(blkinput->token, "MASTERCONSS") == 0 ) { blkinput->section = BLK_MASTERCONSS; SCIPdebugMessage("new section: MASTERCONSS\n"); return TRUE; } if( strcasecmp(blkinput->token, "END") == 0 ) { SCIPdebugMessage("(line %d) new section: END\n", blkinput->linenumber); blkinput->section = BLK_END; return TRUE; } return FALSE; }
/** checks whether the current token is a section identifier, and if yes, switches to the corresponding section */ static SCIP_Bool isNewSection( SCIP* scip, /**< SCIP data structure */ LPINPUT* lpinput /**< LP reading data */ ) { SCIP_Bool iscolon; size_t len; assert(lpinput != NULL); /* remember first token by swapping the token buffer */ swapTokenBuffer(lpinput); /* look at next token: if this is a ':', the first token is a name and no section keyword */ iscolon = FALSE; if( getNextToken(scip, lpinput) ) { iscolon = (*lpinput->token == ':'); pushToken(lpinput); } /* reinstall the previous token by swapping back the token buffer */ swapTokenBuffer(lpinput); /* check for ':' */ if( iscolon ) return FALSE; len = strlen(lpinput->token); assert(len < LP_MAX_LINELEN); /* the section keywords are at least 2 characters up to 8 or exactly 15 characters long */ if( len > 1 && (len < 9 || len == 15) ) { char token[16]; int c = 0; while( lpinput->token[c] != '\0' ) { token[c] = toupper(lpinput->token[c]); /*lint !e734*/ ++c; assert(c < 16); } token[c] = '\0'; if( (len == 3 && strcmp(token, "MIN") == 0) || (len == 7 && strcmp(token, "MINIMUM") == 0) || (len == 8 && strcmp(token, "MINIMIZE") == 0) ) { SCIPdebugMessage("(line %d) new section: OBJECTIVE\n", lpinput->linenumber); lpinput->section = LP_OBJECTIVE; lpinput->objsense = SCIP_OBJSENSE_MINIMIZE; return TRUE; } if( (len == 3 && strcmp(token, "MAX") == 0) || (len == 7 && strcmp(token, "MAXIMUM") == 0) || (len == 8 && strcmp(token, "MAXIMIZE") == 0) ) { SCIPdebugMessage("(line %d) new section: OBJECTIVE\n", lpinput->linenumber); lpinput->section = LP_OBJECTIVE; lpinput->objsense = SCIP_OBJSENSE_MAXIMIZE; return TRUE; } if( len == 3 && strcmp(token, "END") == 0 ) { SCIPdebugMessage("(line %d) new section: END\n", lpinput->linenumber); lpinput->section = LP_END; return TRUE; } } return FALSE; }