/** parse resource capacities */ static SCIP_RETCODE getResourcesCapacities( SCIP* scip, /**< SCIP data structure */ int lineno, /**< current line number of input file */ char* linestr, /**< current line */ STATE* state, /**< pointer to current reading state */ SCIP_RCPSPDATA* rcpspdata /**< pointer to resources constrained project scheduling data */ ) { SCIP_Real value; int r; assert(linestr != NULL); assert(state != NULL); /* parse resources capacities */ for( r = 0; r < rcpspdata->nresources; ++r ) { if( SCIPstrToRealValue(linestr, &value, &linestr) ) rcpspdata->capacities[r] = (int)(value + 0.5); } *state = END; return SCIP_OKAY; }
/** parese number of resources */ static SCIP_RETCODE getNResources( SCIP* scip, /**< SCIP data structure */ int lineno, /**< current line number of input file */ char* linestr, /**< current line */ STATE* state, /**< pointer to current reading state */ SCIP_RCPSPDATA* rcpspdata /**< pointer to resources constrained project scheduling data */ ) { SCIP_Real nresources; char* endptr; char* number; assert(linestr != NULL); assert(state != NULL); if( strncmp(linestr, "RESOURCES", 4) == 0 ) return SCIP_OKAY; /* truncate the line via ':' and ignore the first part */ (void)SCIPstrtok(linestr, ":", &endptr); number = SCIPstrtok(NULL, ":", &endptr); if( !SCIPstrToRealValue(number, &nresources, &endptr) ) { parseError(scip, lineno, "expexted number of resources", linestr, state); return SCIP_OKAY; } rcpspdata->nresources = (int)(nresources + 0.5); SCIP_CALL( SCIPallocBufferArray(scip, &rcpspdata->capacities, nresources) ); SCIP_CALL( SCIPallocBufferArray(scip, &rcpspdata->resourcenames, nresources) ); *state = NEXT; return SCIP_OKAY; }
/** read fixed variable */ static SCIP_RETCODE getFixedVariable( SCIP* scip, /**< SCIP data structure */ CIPINPUT* cipinput /**< CIP parsing data */ ) { SCIP_Bool success; SCIP_VAR* var; char* buf; char* endptr; char name[SCIP_MAXSTRLEN]; 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 variable\n"); /* parse the variable */ SCIP_CALL( SCIPparseVar(scip, &var, buf, TRUE, FALSE, NULL, NULL, NULL, NULL, NULL, &endptr, &success) ); if( !success ) { SCIPerrorMessage("syntax error in variable information (line: %d):\n%s\n", cipinput->linenumber, cipinput->strbuf); cipinput->haserror = TRUE; return SCIP_OKAY; } /* skip intermediate stuff */ buf = endptr; while ( *buf != '\0' && (*buf == ' ' || *buf == ',') ) ++buf; /* check whether variable is fixed */ if ( strncmp(buf, "fixed:", 6) == 0 ) { SCIP_CALL( SCIPaddVar(scip, var) ); SCIPdebug( SCIP_CALL( SCIPprintVar(scip, var, NULL) ) ); } else if ( strncmp(buf, "negated:", 8) == 0 ) { SCIP_CONS* lincons; SCIP_VAR* negvar; SCIP_Real vals[2]; SCIP_VAR* vars[2]; buf += 8; /* we can just parse the next variable (ignoring all other information in between) */ SCIP_CALL( SCIPparseVarName(scip, buf, &negvar, &endptr) ); if ( negvar == NULL ) { SCIPerrorMessage("could not parse negated variable (line: %d):\n%s\n", cipinput->linenumber, cipinput->strbuf); cipinput->haserror = TRUE; return SCIP_OKAY; } assert(SCIPvarIsBinary(var)); assert(SCIPvarIsBinary(negvar)); SCIP_CALL( SCIPaddVar(scip, var) ); SCIPdebugMessage("creating negated variable <%s> (of <%s>) ...\n", SCIPvarGetName(var), SCIPvarGetName(negvar) ); SCIPdebug( SCIP_CALL( SCIPprintVar(scip, var, NULL) ) ); /* add linear constraint for negation */ (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "neg_%s", SCIPvarGetName(var) ); vars[0] = var; vars[1] = negvar; vals[0] = 1.0; vals[1] = 1.0; SCIPdebugMessage("coupling constraint:\n"); SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, name, 2, vars, vals, 1.0, 1.0, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE) ); SCIPdebugPrintCons(scip, lincons, NULL); SCIP_CALL( SCIPaddCons(scip, lincons) ); SCIP_CALL( SCIPreleaseCons(scip, &lincons) ); } else if ( strncmp(buf, "aggregated:", 11) == 0 ) { /* handle (multi-)aggregated variables */ SCIP_CONS* lincons; SCIP_Real* vals; SCIP_VAR** vars; SCIP_Real rhs = 0.0; const char* str; int nvarssize = 20; int requsize; int nvars; buf += 11; SCIPdebugMessage("parsing aggregated variable <%s> ...\n", SCIPvarGetName(var)); /* first parse constant */ if ( ! SCIPstrToRealValue(buf, &rhs, &endptr) ) { SCIPerrorMessage("expected constant when aggregated variable information (line: %d):\n%s\n", cipinput->linenumber, buf); cipinput->haserror = TRUE; return SCIP_OKAY; } /* check whether constant is 0.0 */ str = endptr; while ( *str != '\0' && isspace(*str) ) ++str; /* if next char is '<' we found a variable -> constant is 0 */ if ( *str != '<' ) { SCIPdebugMessage("constant: %f\n", rhs); buf = endptr; } else { /* otherwise keep buf */ rhs = 0.0; } /* initialize buffers for storing the variables and values */ SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvarssize) ); SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvarssize) ); vars[0] = var; vals[0] = -1.0; --nvarssize; /* parse linear sum to get variables and coefficients */ SCIP_CALL( SCIPparseVarsLinearsum(scip, buf, &(vars[1]), &(vals[1]), &nvars, nvarssize, &requsize, &endptr, &success) ); if ( success && requsize > nvarssize ) { /* realloc buffers and try again */ nvarssize = requsize; SCIP_CALL( SCIPreallocBufferArray(scip, &vars, nvarssize + 1) ); SCIP_CALL( SCIPreallocBufferArray(scip, &vals, nvarssize + 1) ); SCIP_CALL( SCIPparseVarsLinearsum(scip, buf, &(vars[1]), &(vals[1]), &nvars, nvarssize, &requsize, &endptr, &success) ); assert( ! success || requsize <= nvarssize); /* if successful, then should have had enough space now */ } if( success ) { /* add aggregated variable */ SCIP_CALL( SCIPaddVar(scip, var) ); /* special handling of variables that seem to be slack variables of indicator constraints */ str = SCIPvarGetName(var); if ( strncmp(str, "indslack", 8) == 0 ) { (void) strcpy(name, "indlin"); (void) strncat(name, str+8, SCIP_MAXSTRLEN-7); } else if ( strncmp(str, "t_indslack", 10) == 0 ) { (void) strcpy(name, "indlin"); (void) strncat(name, str+10, SCIP_MAXSTRLEN-7); } else (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s", SCIPvarGetName(var) ); /* add linear constraint for (multi-)aggregation */ SCIPdebugMessage("coupling constraint:\n"); SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, name, nvars + 1, vars, vals, -rhs, -rhs, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE) ); SCIPdebugPrintCons(scip, lincons, NULL); SCIP_CALL( SCIPaddCons(scip, lincons) ); SCIP_CALL( SCIPreleaseCons(scip, &lincons) ); } else { SCIPwarningMessage(scip, "Could not read (multi-)aggregated variable <%s>: dependent variables unkown - consider changing the order (line: %d):\n%s\n", SCIPvarGetName(var), cipinput->linenumber, buf); } SCIPfreeBufferArray(scip, &vals); SCIPfreeBufferArray(scip, &vars); } else { SCIPerrorMessage("unknown section when parsing variables (line: %d):\n%s\n", cipinput->linenumber, buf); cipinput->haserror = TRUE; return SCIP_OKAY; } SCIP_CALL( SCIPreleaseVar(scip, &var) ); return SCIP_OKAY; }
/** read objective sense, offset, and scale */ static SCIP_RETCODE getObjective( SCIP* scip, /**< SCIP data structure */ CIPINPUT* cipinput, /**< CIP parsing data */ SCIP_Real* objscale, /**< buffer where to multiply with objective scale */ SCIP_Real* objoffset /**< buffer where to add with objective offset */ ) { char* buf; char* name; assert(objscale != NULL); assert(objoffset != NULL); buf = cipinput->strbuf; if( strncmp(buf, "VARIABLES", 8) == 0 ) cipinput->section = CIP_VARS; else if( strncmp(buf, "FIXED", 5) == 0 ) cipinput->section = CIP_FIXEDVARS; else 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_OBJECTIVE ) return SCIP_OKAY; SCIPdebugMessage("parse objective information\n"); /* remove white space */ while ( isspace((unsigned char)* buf) ) ++buf; if( strncasecmp(buf, "Sense", 5) == 0 ) { SCIP_OBJSENSE objsense; name = strchr(buf, ':'); if( name == NULL ) { SCIPwarningMessage(scip, "did not find objective sense (line: %d):\n%s\n", cipinput->linenumber, cipinput->strbuf); return SCIP_OKAY; /* no error - might work with default */ } /* skip ':' */ ++name; /* remove white space in front of the name */ while( isspace((unsigned char)* name) ) ++name; if( strncasecmp(name, "minimize", 3) == 0 ) objsense = SCIP_OBJSENSE_MINIMIZE; else if( strncasecmp(name, "maximize", 3) == 0 ) objsense = SCIP_OBJSENSE_MAXIMIZE; else { SCIPwarningMessage(scip, "unknown objective sense '%s' (line: %d):\n%s\n", name, cipinput->linenumber, cipinput->strbuf); return SCIP_OKAY; /* no error - might work with default */ } /* set problem name */ SCIP_CALL( SCIPsetObjsense(scip, objsense) ); SCIPdebugMessage("objective sense <%s>\n", objsense == SCIP_OBJSENSE_MINIMIZE ? "minimize" : "maximize"); } else if( strncasecmp(buf, "Offset", 6) == 0 ) { SCIP_Real off = 0; char* endptr; name = strchr(buf, ':'); if( name == NULL ) { SCIPwarningMessage(scip, "did not find offset (line: %d)\n", cipinput->linenumber); return SCIP_OKAY; } /* skip ':' */ ++name; /* remove white space in front of the name */ while(isspace((unsigned char)*name)) ++name; if ( SCIPstrToRealValue(name, &off, &endptr) ) { *objoffset += off; SCIPdebugMessage("offset <%g> (total: %g)\n", off, *objoffset); } else { SCIPwarningMessage(scip, "could not parse offset (line: %d)\n%s\n", cipinput->linenumber, cipinput->strbuf); return SCIP_OKAY; } } else if( strncasecmp(buf, "Scale", 5) == 0 ) { SCIP_Real scale = 1.0; char* endptr; name = strchr(buf, ':'); if( name == NULL ) { SCIPwarningMessage(scip, "did not find scale (line: %d)\n", cipinput->linenumber); return SCIP_OKAY; } /* skip ':' */ ++name; /* remove white space in front of the name */ while(isspace((unsigned char)*name)) ++name; if ( SCIPstrToRealValue(name, &scale, &endptr) ) { *objscale *= scale; SCIPdebugMessage("objscale <%g> (total: %g)\n", scale, *objscale); } else { SCIPwarningMessage(scip, "could not parse objective scale (line: %d)\n%s\n", cipinput->linenumber, cipinput->strbuf); return SCIP_OKAY; } } return SCIP_OKAY; }