/** reads problem from file */ SCIP_RETCODE SCIPreadDiff( SCIP* scip, /**< SCIP data structure */ SCIP_READER* reader, /**< the file reader itself */ const char* filename, /**< full path and name of file to read, or NULL if stdin should be used */ SCIP_RESULT* result /**< pointer to store the result of the file reading call */ ) { /*lint --e{715}*/ LPINPUT lpinput; int i; /* initialize LP input data */ lpinput.file = NULL; lpinput.linebuf[0] = '\0'; lpinput.probname[0] = '\0'; lpinput.objname[0] = '\0'; SCIP_CALL( SCIPallocMemoryArray(scip, &lpinput.token, LP_MAX_LINELEN) ); /*lint !e506*/ lpinput.token[0] = '\0'; SCIP_CALL( SCIPallocMemoryArray(scip, &lpinput.tokenbuf, LP_MAX_LINELEN) ); /*lint !e506*/ lpinput.tokenbuf[0] = '\0'; for( i = 0; i < LP_MAX_PUSHEDTOKENS; ++i ) { SCIP_CALL( SCIPallocMemoryArray(scip, &(lpinput.pushedtokens[i]), LP_MAX_LINELEN) ); /*lint !e866 !e506*/ } lpinput.npushedtokens = 0; lpinput.linenumber = 0; lpinput.linepos = 0; lpinput.section = LP_START; lpinput.objsense = SCIP_OBJSENSE_MINIMIZE; lpinput.haserror = FALSE; lpinput.comment = FALSE; lpinput.endline = FALSE; /* read the file */ SCIP_CALL( readDiffFile(scip, &lpinput, filename) ); /* free dynamically allocated memory */ SCIPfreeMemoryArray(scip, &lpinput.token); SCIPfreeMemoryArray(scip, &lpinput.tokenbuf); for( i = 0; i < LP_MAX_PUSHEDTOKENS; ++i ) { SCIPfreeMemoryArray(scip, &lpinput.pushedtokens[i]); } /* evaluate the result */ if( lpinput.haserror ) return SCIP_READERROR; else { /* set objective sense */ SCIP_CALL( SCIPsetObjsense(scip, lpinput.objsense) ); *result = SCIP_SUCCESS; } return SCIP_OKAY; }
SCIPSolver::SCIPSolver(){ DBG("create a scip solver\n%s", ""); var_counter = 0; _verbosity = 0; has_been_added = false; // Load up SCIP SCIP_CALL_EXC( SCIPcreate(& _scip) ); // load default plugins linke separators, heuristics, etc. SCIP_CALL_EXC( SCIPincludeDefaultPlugins(_scip) ); // create an empty problem SCIP_CALL_EXC( SCIPcreateProb(_scip, "Numberjack Model", NULL, NULL, NULL, NULL, NULL, NULL, NULL) ); // set the objective sense to maximize, default is minimize SCIP_CALL_EXC( SCIPsetObjsense(_scip, SCIP_OBJSENSE_MAXIMIZE) ); }
/** create linear ordering problem model */ SCIP_RETCODE LOPgenerateModel( SCIP* scip /**< SCIP data structure */ ) { SCIP_PROBDATA* probdata; SCIP_CONS* cons; int i, j; /* get problem data */ probdata = SCIPgetProbData(scip); assert( probdata != NULL ); /* generate variables */ SCIP_CALL( SCIPallocMemoryArray(scip, &probdata->vars, probdata->n) ); for (i = 0; i < probdata->n; ++i) { SCIP_CALL( SCIPallocMemoryArray(scip, &(probdata->vars[i]), probdata->n) ); /*lint !e866*/ for (j = 0; j < probdata->n; ++j) { if (j != i) { char s[SCIP_MAXSTRLEN]; (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "x#%d#%d", i, j); SCIP_CALL( SCIPcreateVar(scip, &(probdata->vars[i][j]), s, 0.0, 1.0, probdata->W[i][j], SCIP_VARTYPE_BINARY, TRUE, FALSE, NULL, NULL, NULL, NULL, NULL)); SCIP_CALL( SCIPaddVar(scip, probdata->vars[i][j]) ); } else probdata->vars[i][j] = NULL; } } /* generate linear ordering constraint */ SCIP_CALL( SCIPcreateConsLinearOrdering(scip, &cons, "LOP", probdata->n, probdata->vars, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE)); SCIP_CALL( SCIPaddCons(scip, cons) ); SCIP_CALL( SCIPreleaseCons(scip, &cons) ); /* set maximization */ SCIP_CALL( SCIPsetObjsense(scip, SCIP_OBJSENSE_MAXIMIZE) ); return SCIP_OKAY; }
/* Read SAT formula in "CNF File Format". * * The specification is taken from the * * Satisfiability Suggested Format * * Online available at http://www.intellektik.informatik.tu-darmstadt.de/SATLIB/Benchmarks/SAT/satformat.ps * * The method reads all files of CNF format. Other formats (SAT, SATX, SATE) are not supported. */ static SCIP_RETCODE readCnf( SCIP* scip, /**< SCIP data structure */ SCIP_FILE* file /**< input file */ ) { SCIP_RETCODE retcode; SCIP_VAR** vars; SCIP_VAR** clausevars; SCIP_CONS* cons; int* varsign; char* tok; char* nexttok; char line[MAXLINELEN]; char format[SCIP_MAXSTRLEN]; char varname[SCIP_MAXSTRLEN]; char s[SCIP_MAXSTRLEN]; SCIP_Bool dynamicconss; SCIP_Bool dynamiccols; SCIP_Bool dynamicrows; SCIP_Bool useobj; int linecount; int clauselen; int clausenum; int nvars; int nclauses; int varnum; int v; assert(scip != NULL); assert(file != NULL); retcode = SCIP_OKAY; linecount = 0; /* read header */ SCIP_CALL( readCnfLine(scip, file, line, (int) sizeof(line), &linecount) ); if( *line != 'p' ) { readError(scip, linecount, "problem declaration line expected"); return SCIP_READERROR; } if( sscanf(line, "p %8s %d %d", format, &nvars, &nclauses) != 3 ) { readError(scip, linecount, "invalid problem declaration (must be 'p cnf <nvars> <nclauses>')"); return SCIP_READERROR; } if( strcmp(format, "cnf") != 0 ) { (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "invalid format tag <%s> (must be 'cnf')", format); readError(scip, linecount, s); return SCIP_READERROR; } if( nvars <= 0 ) { (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "invalid number of variables <%d> (must be positive)", nvars); readError(scip, linecount, s); return SCIP_READERROR; } if( nclauses <= 0 ) { (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "invalid number of clauses <%d> (must be positive)", nclauses); readError(scip, linecount, s); return SCIP_READERROR; } /* get parameter values */ SCIP_CALL( SCIPgetBoolParam(scip, "reading/cnfreader/dynamicconss", &dynamicconss) ); SCIP_CALL( SCIPgetBoolParam(scip, "reading/cnfreader/dynamiccols", &dynamiccols) ); SCIP_CALL( SCIPgetBoolParam(scip, "reading/cnfreader/dynamicrows", &dynamicrows) ); SCIP_CALL( SCIPgetBoolParam(scip, "reading/cnfreader/useobj", &useobj) ); /* get temporary memory */ SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) ); SCIP_CALL( SCIPallocBufferArray(scip, &clausevars, nvars) ); SCIP_CALL( SCIPallocBufferArray(scip, &varsign, nvars) ); /* create the variables */ for( v = 0; v < nvars; ++v ) { (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "x%d", v+1); SCIP_CALL( SCIPcreateVar(scip, &vars[v], varname, 0.0, 1.0, 0.0, SCIP_VARTYPE_BINARY, !dynamiccols, dynamiccols, NULL, NULL, NULL, NULL, NULL) ); SCIP_CALL( SCIPaddVar(scip, vars[v]) ); varsign[v] = 0; } /* read clauses */ clausenum = 0; clauselen = 0; do { retcode = readCnfLine(scip, file, line, (int) sizeof(line), &linecount); if( retcode != SCIP_OKAY ) goto TERMINATE; if( *line != '\0' && *line != '%' ) { tok = SCIPstrtok(line, " \f\n\r\t", &nexttok); while( tok != NULL ) { /* parse literal and check for errors */ if( sscanf(tok, "%d", &v) != 1 ) { (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "invalid literal <%s>", tok); readError(scip, linecount, s); retcode = SCIP_READERROR; goto TERMINATE; } /* interpret literal number: v == 0: end of clause, v < 0: negated literal, v > 0: positive literal */ if( v == 0 ) { /* end of clause: construct clause and add it to SCIP */ if( clauselen == 0 ) readWarning(scip, linecount, "empty clause detected in line -- problem infeasible"); clausenum++; (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "c%d", clausenum); if( SCIPfindConshdlr(scip, "logicor") != NULL ) { /* if the constraint handler logicor exit create a logicor constraint */ SCIP_CALL( SCIPcreateConsLogicor(scip, &cons, s, clauselen, clausevars, !dynamicrows, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, dynamicconss, dynamicrows, FALSE) ); } else if( SCIPfindConshdlr(scip, "setppc") != NULL ) { /* if the constraint handler logicor does not exit but constraint * handler setppc create a setppc constraint */ SCIP_CALL( SCIPcreateConsSetcover(scip, &cons, s, clauselen, clausevars, !dynamicrows, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, dynamicconss, dynamicrows, FALSE) ); } else { /* if none of the previous constraint handler exits create a linear * constraint */ SCIP_Real* vals; int i; SCIP_CALL( SCIPallocBufferArray(scip, &vals, clauselen) ); for( i = 0; i < clauselen; ++i ) vals[i] = 1.0; SCIP_CALL( SCIPcreateConsLinear(scip, &cons, s, clauselen, clausevars, vals, 1.0, SCIPinfinity(scip), !dynamicrows, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, dynamicconss, dynamicrows, FALSE) ); SCIPfreeBufferArray(scip, &vals); } SCIP_CALL( SCIPaddCons(scip, cons) ); SCIP_CALL( SCIPreleaseCons(scip, &cons) ); clauselen = 0; } else if( v >= -nvars && v <= nvars ) { if( clauselen >= nvars ) { readError(scip, linecount, "too many literals in clause"); retcode = SCIP_READERROR; goto TERMINATE; } /* add literal to clause */ varnum = ABS(v)-1; if( v < 0 ) { SCIP_CALL( SCIPgetNegatedVar(scip, vars[varnum], &clausevars[clauselen]) ); varsign[varnum]--; } else { clausevars[clauselen] = vars[varnum]; varsign[varnum]++; } clauselen++; } else { (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "invalid variable number <%d>", ABS(v)); readError(scip, linecount, s); retcode = SCIP_READERROR; goto TERMINATE; } /* get next token */ tok = SCIPstrtok(NULL, " \f\n\r\t", &nexttok); } } } while( *line != '\0' && *line != '%' ); /* check for additional literals */ if( clauselen > 0 ) { SCIPwarningMessage(scip, "found %d additional literals after last clause\n", clauselen); } /* check number of clauses */ if( clausenum != nclauses ) { SCIPwarningMessage(scip, "expected %d clauses, but found %d\n", nclauses, clausenum); } TERMINATE: /* change objective values and release variables */ SCIP_CALL( SCIPsetObjsense(scip, SCIP_OBJSENSE_MAXIMIZE) ); if( useobj ) { for( v = 0; v < nvars; ++v ) { SCIP_CALL( SCIPchgVarObj(scip, vars[v], (SCIP_Real)varsign[v]) ); SCIP_CALL( SCIPreleaseVar(scip, &vars[v]) ); } } /* free temporary memory */ SCIPfreeBufferArray(scip, &varsign); SCIPfreeBufferArray(scip, &clausevars); SCIPfreeBufferArray(scip, &vars); return retcode; }
/** sets up the problem data */ SCIP_RETCODE SCIPprobdataCreate( SCIP* scip, /**< SCIP data structure */ const char* probname, /**< problem name */ int* ids, /**< array of item ids */ SCIP_Longint* weights, /**< array containing the item weights */ int nitems, /**< number of items */ SCIP_Longint capacity /**< bin capacity */ ) { SCIP_PROBDATA* probdata; SCIP_CONS** conss; char name[SCIP_MAXSTRLEN]; int i; assert(scip != NULL); /* create event handler if it does not exist yet */ if( SCIPfindEventhdlr(scip, EVENTHDLR_NAME) == NULL ) { SCIP_CALL( SCIPincludeEventhdlrBasic(scip, NULL, EVENTHDLR_NAME, EVENTHDLR_DESC, eventExecAddedVar, NULL) ); } /* create problem in SCIP and add non-NULL callbacks via setter functions */ SCIP_CALL( SCIPcreateProbBasic(scip, probname) ); SCIP_CALL( SCIPsetProbDelorig(scip, probdelorigBinpacking) ); SCIP_CALL( SCIPsetProbTrans(scip, probtransBinpacking) ); SCIP_CALL( SCIPsetProbDeltrans(scip, probdeltransBinpacking) ); SCIP_CALL( SCIPsetProbInitsol(scip, probinitsolBinpacking) ); SCIP_CALL( SCIPsetProbExitsol(scip, probexitsolBinpacking) ); /* set objective sense */ SCIP_CALL( SCIPsetObjsense(scip, SCIP_OBJSENSE_MINIMIZE) ); /* tell SCIP that the objective will be always integral */ SCIP_CALL( SCIPsetObjIntegral(scip) ); SCIP_CALL( SCIPallocBufferArray(scip, &conss, nitems) ); /* create set covering constraints for each item */ for( i = 0; i < nitems; ++i ) { (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "item_%d", ids[i]); SCIP_CALL( SCIPcreateConsBasicSetcover(scip, &conss[i], name, 0, NULL) ); /* declare constraint modifiable for adding variables during pricing */ SCIP_CALL( SCIPsetConsModifiable(scip, conss[i], TRUE) ); SCIP_CALL( SCIPaddCons(scip, conss[i]) ); } /* create problem data */ SCIP_CALL( probdataCreate(scip, &probdata, NULL, conss, weights, ids, 0, nitems, capacity) ); SCIP_CALL( createInitialColumns(scip, probdata) ); /* set user problem data */ SCIP_CALL( SCIPsetProbData(scip, probdata) ); SCIP_CALL( SCIPpricerBinpackingActivate(scip, conss, weights, ids, nitems, capacity) ); /* free local buffer arrays */ SCIPfreeBufferArray(scip, &conss); return SCIP_OKAY; }
/* standard "main" method for mex interface */ void mexFunction( int nlhs, /* number of expected outputs */ mxArray* plhs[], /* array of pointers to output arguments */ int nrhs, /* number of inputs */ const mxArray* prhs[] /* array of pointers to input arguments */ ) { SCIP* scip; SCIP_VAR** vars; SCIP_Real* objs; SCIP_Real* lhss; SCIP_Real* rhss; SCIP_Real* lbs; SCIP_Real* ubs; SCIP_Real* matrix; SCIP_Real* bestsol; SCIP_Real* objval; char* vartypes; char objsense[SCIP_MAXSTRLEN]; int nvars; int nconss; int stringsize; int i; if( SCIPmajorVersion() < 2 ) { mexErrMsgTxt("SCIP versions less than 2.0 are not supported\n"); return; } /* initialize SCIP */ SCIP_CALL_ABORT( SCIPcreate(&scip) ); /* output SCIP information */ SCIPprintVersion(scip, NULL); /* include default SCIP plugins */ SCIP_CALL_ABORT( SCIPincludeDefaultPlugins(scip) ); if( nlhs != 2 || nrhs != 8 ) mexErrMsgTxt("invalid number of parameters. Call as [bestsol, objval] = matscip(matrix, lhs, rhs, obj, lb, ub, vartype, objsense)\n"); if( mxIsSparse(prhs[0]) ) mexErrMsgTxt("sparse matrices are not supported yet"); /* ???????? of course this has to change */ /* get linear constraint coefficient matrix */ matrix = mxGetPr(prhs[0]); if( matrix == NULL ) mexErrMsgTxt("matrix must not be NULL"); if( mxGetNumberOfDimensions(prhs[0]) != 2 ) mexErrMsgTxt("matrix must have exactly two dimensions"); /* get dimensions of matrix */ nconss = mxGetM(prhs[0]); nvars = mxGetN(prhs[0]); assert(nconss > 0); assert(nvars > 0); /* get left hand sides of linear constraints */ lhss = mxGetPr(prhs[1]); if( mxGetM(prhs[1]) != nconss ) mexErrMsgTxt("dimension of left hand side vector does not match matrix dimension"); assert(lhss != NULL); /* get right hand sides of linear constraints */ rhss = mxGetPr(prhs[2]); if( mxGetM(prhs[2]) != nconss ) mexErrMsgTxt("dimension of right hand side vector does not match matrix dimension"); assert(rhss != NULL); /* get objective coefficients */ objs = mxGetPr(prhs[3]); if( mxGetM(prhs[3]) != nvars ) mexErrMsgTxt("dimension of objective coefficient vector does not match matrix dimension"); /* get lower bounds of variables */ lbs = mxGetPr(prhs[4]); if( mxGetM(prhs[4]) != nvars ) mexErrMsgTxt("dimension of lower bound vector does not match matrix dimension"); /* get upper bounds of variables */ ubs = mxGetPr(prhs[5]); if( mxGetM(prhs[5]) != nvars ) mexErrMsgTxt("dimension of upper bound vector does not match matrix dimension"); /* allocate memory for variable type characters */ SCIP_CALL_ABORT( SCIPallocMemoryArray(scip, &vartypes, nvars+1) ); /* get variable types */ if( mxGetString(prhs[6], vartypes, nvars+1) != 0 ) mexErrMsgTxt("Error when parsing variable types, maybe a wrong vector dimension?"); /* get objective sense */ stringsize = mxGetNumberOfElements(prhs[7]); if( stringsize != 3 ) mexErrMsgTxt("objective sense must be a three character word: \"max\" or \"min\""); if( mxGetString(prhs[7], objsense, stringsize+1) != 0) mexErrMsgTxt("Error when parsing objective sense string"); if( strcmp(objsense,"max") != 0 && strcmp(objsense,"min") != 0 ) mexErrMsgTxt("objective sense must be either \"max\" or \"min\""); /* get output parameters */ plhs[0] = mxCreateDoubleMatrix(nvars, 1, mxREAL); bestsol = mxGetPr(plhs[0]); plhs[1] = mxCreateDoubleScalar(mxREAL); objval = mxGetPr(plhs[1]); /* create SCIP problem */ SCIP_CALL_ABORT( SCIPcreateProb(scip, "mex_prob", NULL, NULL, NULL, NULL, NULL, NULL, NULL) ); /* allocate memory for variable array */ SCIP_CALL_ABORT( SCIPallocMemoryArray(scip, &vars, nvars) ); /* create variables */ for( i = 0; i < nvars; ++i) { SCIP_VARTYPE vartype; char varname[SCIP_MAXSTRLEN]; /* convert vartype character to SCIP vartype */ if( vartypes[i] == 'i' ) vartype = SCIP_VARTYPE_INTEGER; else if( vartypes[i] == 'b' ) vartype = SCIP_VARTYPE_BINARY; else if( vartypes[i] == 'c' ) vartype = SCIP_VARTYPE_CONTINUOUS; else mexErrMsgTxt("unkown variable type"); /* variables get canonic names x_i */ (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "x_%d", i); /* create variable object and add it to SCIP */ SCIP_CALL_ABORT( SCIPcreateVar(scip, &vars[i], varname, lbs[i], ubs[i], objs[i], vartype, TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) ); assert(vars[i] != NULL); SCIP_CALL_ABORT( SCIPaddVar(scip, vars[i]) ); } /* create linear constraints */ for( i = 0; i < nconss; ++i ) { SCIP_CONS* cons; char consname[SCIP_MAXSTRLEN]; int j; /* constraints get canonic names cons_i */ (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "cons_%d", i); /* create empty linear constraint */ SCIP_CALL_ABORT( SCIPcreateConsLinear(scip, &cons, consname, 0, NULL, NULL, lhss[i], rhss[i], TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) ); /* add non-zero coefficients to linear constraint */ for( j = 0; j < nvars; ++j ) { if( !SCIPisFeasZero(scip, matrix[i+j*nconss]) ) { SCIP_CALL_ABORT( SCIPaddCoefLinear(scip, cons, vars[j], matrix[i+j*nconss]) ); } } /* add constraint to SCIP and release it */ SCIP_CALL_ABORT( SCIPaddCons(scip, cons) ); SCIP_CALL_ABORT( SCIPreleaseCons(scip, &cons) ); } /* set objective sense in SCIP */ if( strcmp(objsense,"max") == 0) { SCIP_CALL_ABORT( SCIPsetObjsense(scip, SCIP_OBJSENSE_MAXIMIZE) ); } else if( strcmp(objsense,"min") == 0) { SCIP_CALL_ABORT( SCIPsetObjsense(scip, SCIP_OBJSENSE_MINIMIZE) ); } else /* this should have been caught earlier when parsing objsense */ mexErrMsgTxt("unkown objective sense"); /* solve SCIP problem */ SCIP_CALL_ABORT( SCIPsolve(scip) ); /* if SCIP found a solution, pass it back into MATLAB output parameters */ if( SCIPgetNSols > 0 ) { SCIP_SOL* scipbestsol; /* get incumbent solution vector */ scipbestsol = SCIPgetBestSol(scip); assert(scipbestsol != NULL); /* get objective value of incumbent solution */ *objval = SCIPgetSolOrigObj(scip, scipbestsol); assert(!SCIPisInfinity(scip, REALABS(*objval))); /* copy solution values into output vector */ for( i = 0; i < nvars; ++i ) bestsol[i] = SCIPgetSolVal(scip,scipbestsol,vars[i]); } /* release variables */ for( i = 0; i < nvars; ++i ) { SCIP_CALL_ABORT( SCIPreleaseVar(scip, &vars[i]) ); } /* free memory for variable arrays */ SCIPfreeMemoryArray(scip, &vartypes); SCIPfreeMemoryArray(scip, &vars); /* deinitialize SCIP */ SCIP_CALL_ABORT( SCIPfree(&scip) ); /* check for memory leaks */ BMScheckEmptyMemory(); return; }
/** 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; }
/** reduced cost pricing method of variable pricer for feasible LPs */ static SCIP_DECL_PRICERREDCOST(pricerRedcostBinpacking) { /*lint --e{715}*/ SCIP* subscip; SCIP_PRICERDATA* pricerdata; SCIP_CONS** conss; SCIP_VAR** vars; int* ids; SCIP_Bool addvar; SCIP_SOL** sols; int nsols; int s; int nitems; SCIP_Longint capacity; SCIP_Real timelimit; SCIP_Real memorylimit; assert(scip != NULL); assert(pricer != NULL); (*result) = SCIP_DIDNOTRUN; /* get the pricer data */ pricerdata = SCIPpricerGetData(pricer); assert(pricerdata != NULL); capacity = pricerdata->capacity; conss = pricerdata->conss; ids = pricerdata->ids; nitems = pricerdata->nitems; /* get the remaining time and memory limit */ SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) ); if( !SCIPisInfinity(scip, timelimit) ) timelimit -= SCIPgetSolvingTime(scip); SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memorylimit) ); if( !SCIPisInfinity(scip, memorylimit) ) memorylimit -= SCIPgetMemUsed(scip)/1048576.0; /* initialize SCIP */ SCIP_CALL( SCIPcreate(&subscip) ); SCIP_CALL( SCIPincludeDefaultPlugins(subscip) ); /* create problem in sub SCIP */ SCIP_CALL( SCIPcreateProbBasic(subscip, "pricing") ); SCIP_CALL( SCIPsetObjsense(subscip, SCIP_OBJSENSE_MAXIMIZE) ); /* do not abort subproblem on CTRL-C */ SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) ); /* disable output to console */ SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) ); /* set time and memory limit */ SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", timelimit) ); SCIP_CALL( SCIPsetRealParam(subscip, "limits/memory", memorylimit) ); SCIP_CALL( SCIPallocMemoryArray(subscip, &vars, nitems) ); /* initialization local pricing problem */ SCIP_CALL( initPricing(scip, pricerdata, subscip, vars) ); SCIPdebugMessage("solve pricer problem\n"); /* solve sub SCIP */ SCIP_CALL( SCIPsolve(subscip) ); sols = SCIPgetSols(subscip); nsols = SCIPgetNSols(subscip); addvar = FALSE; /* loop over all solutions and create the corresponding column to master if the reduced cost are negative for master, * that is the objective value i greater than 1.0 */ for( s = 0; s < nsols; ++s ) { SCIP_Bool feasible; SCIP_SOL* sol; /* the soultion should be sorted w.r.t. the objective function value */ assert(s == 0 || SCIPisFeasGE(subscip, SCIPgetSolOrigObj(subscip, sols[s-1]), SCIPgetSolOrigObj(subscip, sols[s]))); sol = sols[s]; assert(sol != NULL); /* check if solution is feasible in original sub SCIP */ SCIP_CALL( SCIPcheckSolOrig(subscip, sol, &feasible, FALSE, FALSE ) ); if( !feasible ) { SCIPwarningMessage(scip, "solution in pricing problem (capacity <%d>) is infeasible\n", capacity); continue; } /* check if the solution has a value greater than 1.0 */ if( SCIPisFeasGT(subscip, SCIPgetSolOrigObj(subscip, sol), 1.0) ) { SCIP_VAR* var; SCIP_VARDATA* vardata; int* consids; char strtmp[SCIP_MAXSTRLEN]; char name[SCIP_MAXSTRLEN]; int nconss; int o; int v; SCIPdebug( SCIP_CALL( SCIPprintSol(subscip, sol, NULL, FALSE) ) ); nconss = 0; (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "items"); SCIP_CALL( SCIPallocBufferArray(scip, &consids, nitems) ); /* check which variables are fixed -> which item belongs to this packing */ for( o = 0, v = 0; o < nitems; ++o ) { if( !SCIPconsIsEnabled(conss[o]) ) continue; assert(SCIPgetNFixedonesSetppc(scip, conss[o]) == 0); if( SCIPgetSolVal(subscip, sol, vars[v]) > 0.5 ) { (void) SCIPsnprintf(strtmp, SCIP_MAXSTRLEN, "_%d", ids[o]); strcat(name, strtmp); consids[nconss] = o; nconss++; } else assert( SCIPisFeasEQ(subscip, SCIPgetSolVal(subscip, sol, vars[v]), 0.0) ); v++; } SCIP_CALL( SCIPvardataCreateBinpacking(scip, &vardata, consids, nconss) ); /* create variable for a new column with objective function coefficient 0.0 */ SCIP_CALL( SCIPcreateVarBinpacking(scip, &var, name, 1.0, FALSE, TRUE, vardata) ); /* add the new variable to the pricer store */ SCIP_CALL( SCIPaddPricedVar(scip, var, 1.0) ); addvar = TRUE; /* change the upper bound of the binary variable to lazy since the upper bound is already enforced due to * the objective function the set covering constraint; The reason for doing is that, is to avoid the bound * of x <= 1 in the LP relaxation since this bound constraint would produce a dual variable which might have * a positive reduced cost */ SCIP_CALL( SCIPchgVarUbLazy(scip, var, 1.0) ); /* check which variable are fixed -> which orders belong to this packing */ for( v = 0; v < nconss; ++v ) { assert(SCIPconsIsEnabled(conss[consids[v]])); SCIP_CALL( SCIPaddCoefSetppc(scip, conss[consids[v]], var) ); } SCIPdebug(SCIPprintVar(scip, var, NULL) ); SCIP_CALL( SCIPreleaseVar(scip, &var) ); SCIPfreeBufferArray(scip, &consids); } else break; } /* free pricer MIP */ SCIPfreeMemoryArray(subscip, &vars); if( addvar || SCIPgetStatus(subscip) == SCIP_STATUS_OPTIMAL ) (*result) = SCIP_SUCCESS; /* free sub SCIP */ SCIP_CALL( SCIPfree(&subscip) ); 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"); if( strncmp(buf, " Sense", 7) == 0 ) { SCIP_OBJSENSE objsense; name = strchr(buf, ':'); if( name == NULL ) { SCIPwarningMessage(scip, "did not find objective sense\n"); 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( strncmp(name, "minimize", 3) == 0 ) objsense = SCIP_OBJSENSE_MINIMIZE; else if( strncmp(name, "maximize", 3) == 0 ) objsense = SCIP_OBJSENSE_MAXIMIZE; else { SCIPwarningMessage(scip, "unknown objective sense, %s\n", name); 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( strncmp(buf, " Offset", 7) == 0 ) { char* endptr; name = strchr(buf, ':'); if( name == NULL ) { SCIPwarningMessage(scip, "did not find offset\n"); return SCIP_OKAY; } /* skip ':' */ ++name; /* remove white space in front of the name */ while(isspace((unsigned char)*name)) name++; *objoffset += strtod(name, &endptr); } else if( strncmp(buf, " Scale", 7) == 0 ) { char* endptr; name = strchr(buf, ':'); if( name == NULL ) { SCIPwarningMessage(scip, "did not find scale\n"); return SCIP_OKAY; } /* skip ':' */ ++name; /* remove white space in front of the name */ while(isspace((unsigned char)*name)) name++; *objscale *= strtod(name, &endptr); } return SCIP_OKAY; }