/** create and capture problem variable and associates the given variable data with the variable; * if variable is of integral type, fractional bounds are automatically rounded */ SCIP_RETCODE SCIPcreateObjVar( SCIP* scip, /**< SCIP data structure */ SCIP_VAR** var, /**< pointer to variable object */ const char* name, /**< name of variable, or NULL for automatic name creation */ SCIP_Real lb, /**< lower bound of variable */ SCIP_Real ub, /**< upper bound of variable */ SCIP_Real obj, /**< objective function value */ SCIP_VARTYPE vartype, /**< type of variable */ SCIP_Bool initial, /**< should var's column be present in the initial root LP? */ SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */ scip::ObjVardata* objvardata, /**< user variable data object */ SCIP_Bool deleteobject /**< should the user variable data object be deleted when variable is freed? */ ) { SCIP_VARDATA* vardata; /* create user variable data */ vardata = new SCIP_VARDATA; vardata->objvardata = objvardata; vardata->deleteobject = deleteobject; /* create variable */ SCIP_CALL( SCIPcreateVar(scip, var, name, lb, ub, obj, vartype, initial, removable, varDelorigObj, varTransObj, varDeltransObj, varCopyObj, vardata) ); /*lint !e429*/ return SCIP_OKAY; /*lint !e429*/ }
void SCIPSolver::add_in_constraint(LinearConstraint *con, double coef){ DBG("Creating a SCIP representation of a constriant%s\n", ""); double *weights = new double[con->_coefficients.size()]; SCIP_VAR** vars = new SCIP_VAR*[con->_variables.size()]; for(unsigned int i = 0; i < con->_variables.size(); ++i){ DBG("\tAdding variable to SCIP\n%s", ""); if(con->_variables[i]->_var == NULL){ SCIP_VAR* var_ptr; SCIP_VARTYPE type; if(con->_variables[i]->_continuous) type = SCIP_VARTYPE_CONTINUOUS; else type = SCIP_VARTYPE_INTEGER; SCIP_CALL_EXC(SCIPcreateVar(_scip, &var_ptr, "SCIP_Var", con->_variables[i]->_lower, // LB con->_variables[i]->_upper, // UB coef * con->_coefficients[i], // ective type, TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) ); SCIP_CALL_EXC( SCIPaddVar(_scip, var_ptr) ); con->_variables[i]->_var = (void*) var_ptr; vars[i] = var_ptr; weights[i] = con->_coefficients[i]; } else { vars[i] = (SCIP_VAR*) con->_variables[i]->_var; weights[i] = con->_coefficients[i]; } } SCIP_CONS *scip_con; SCIP_CALL_EXC( SCIPcreateConsLinear(_scip, &scip_con,"constraint", con->_variables.size(), // # vars vars, // variables weights, // values con->_lhs, // LHS con->_rhs, // RHS TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) ); SCIP_CALL_EXC( SCIPaddCons(_scip, scip_con) ); }
/** creates variable */ SCIP_RETCODE SCIPcreateVarBinpacking( SCIP* scip, /**< SCIP data structure */ SCIP_VAR** var, /**< pointer to variable object */ const char* name, /**< name of variable, or NULL for automatic name creation */ SCIP_Real obj, /**< objective function value */ SCIP_Bool initial, /**< should var's column be present in the initial root LP? */ SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */ SCIP_VARDATA* vardata /**< user data for this specific variable */ ) { SCIP_CALL( SCIPcreateVar(scip, var, name, 0.0, 1.0, obj, SCIP_VARTYPE_BINARY, initial, removable, vardataDelOrig, vardataTrans, vardataDelTrans, vardataCopy, vardata) ); SCIPvarMarkDeletable(*var); SCIPdebug(SCIPprintVar(scip, *var, NULL) ); return SCIP_OKAY; }
/** 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; }
/** presolving execution method */ static SCIP_DECL_PRESOLEXEC(presolExecInttobinary) { /*lint --e{715}*/ SCIP_VAR** scipvars; SCIP_VAR** vars; int nbinvars; int nintvars; int v; assert(result != NULL); *result = SCIP_DIDNOTRUN; if( SCIPdoNotAggr(scip) ) return SCIP_OKAY; /* get the problem variables */ scipvars = SCIPgetVars(scip); nbinvars = SCIPgetNBinVars(scip); nintvars = SCIPgetNIntVars(scip); if( nintvars == 0 ) return SCIP_OKAY; *result = SCIP_DIDNOTFIND; /* copy the integer variables into an own array, since adding binary variables affects the left-most slots in the * array and thereby interferes with our search loop */ SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &scipvars[nbinvars], nintvars) ); /* scan the integer variables for possible conversion into binaries; * we have to collect the variables first in an own */ for( v = 0; v < nintvars; ++v ) { SCIP_Real lb; SCIP_Real ub; assert(SCIPvarGetType(vars[v]) == SCIP_VARTYPE_INTEGER); /* get variable's bounds */ lb = SCIPvarGetLbGlobal(vars[v]); ub = SCIPvarGetUbGlobal(vars[v]); /* check if bounds are exactly one apart */ if( SCIPisEQ(scip, lb, ub - 1.0) ) { SCIP_VAR* binvar; char binvarname[SCIP_MAXSTRLEN]; SCIP_Bool infeasible; SCIP_Bool redundant; SCIP_Bool aggregated; SCIPdebugMessage("converting <%s>[%g,%g] into binary variable\n", SCIPvarGetName(vars[v]), lb, ub); /* create binary variable */ (void) SCIPsnprintf(binvarname, SCIP_MAXSTRLEN, "%s_bin", SCIPvarGetName(vars[v])); SCIP_CALL( SCIPcreateVar(scip, &binvar, binvarname, 0.0, 1.0, 0.0, SCIP_VARTYPE_BINARY, SCIPvarIsInitial(vars[v]), SCIPvarIsRemovable(vars[v]), NULL, NULL, NULL, NULL, NULL) ); SCIP_CALL( SCIPaddVar(scip, binvar) ); /* aggregate integer and binary variable */ SCIP_CALL( SCIPaggregateVars(scip, vars[v], binvar, 1.0, -1.0, lb, &infeasible, &redundant, &aggregated) ); /* release binary variable */ SCIP_CALL( SCIPreleaseVar(scip, &binvar) ); /* it can be the case that this aggregation detects an infeasibility; for example, during the copy of the * variable bounds from the integer variable to the binary variable, infeasibility can be detected; this can * happen because an upper bound or a lower bound of such a variable bound variable was "just" changed and the * varbound constraint handler, who would detect that infeasibility (since it was creating it from a varbound * constraint), was called before that bound change was detected due to the presolving priorities; */ if( infeasible ) { *result = SCIP_CUTOFF; break; } assert(redundant); assert(aggregated); (*nchgvartypes)++; *result = SCIP_SUCCESS; } } /* free temporary memory */ SCIPfreeBufferArray(scip, &vars); return SCIP_OKAY; }
/** creates the objective value inequality and the objective value variable, if not yet existing */ static SCIP_RETCODE createObjRow( SCIP* scip, /**< SCIP data structure */ SCIP_SEPA* sepa, /**< separator */ SCIP_SEPADATA* sepadata /**< separator data */ ) { assert(sepadata != NULL); if( sepadata->objrow == NULL ) { SCIP_VAR** vars; SCIP_Real obj; SCIP_Real intobjval; int nvars; int v; SCIP_Bool attendobjvarbound; attendobjvarbound = FALSE; /* create and add objective value variable */ if( sepadata->objvar == NULL ) { SCIP_CALL( SCIPcreateVar(scip, &sepadata->objvar, "objvar", -SCIPinfinity(scip), SCIPinfinity(scip), 0.0, SCIP_VARTYPE_IMPLINT, FALSE, TRUE, NULL, NULL, NULL, NULL, NULL) ); SCIP_CALL( SCIPaddVar(scip, sepadata->objvar) ); SCIP_CALL( SCIPaddVarLocks(scip, sepadata->objvar, +1, +1) ); } else attendobjvarbound = TRUE; /* get problem variables */ vars = SCIPgetOrigVars(scip); nvars = SCIPgetNOrigVars(scip); /* create objective value inequality */ if( SCIPgetObjsense(scip) == SCIP_OBJSENSE_MINIMIZE ) { if( attendobjvarbound ) intobjval = SCIPceil(scip, SCIPgetDualbound(scip)) - SCIPvarGetLbGlobal(sepadata->objvar); else intobjval = SCIPceil(scip, SCIPgetDualbound(scip)); SCIP_CALL( SCIPcreateEmptyRowSepa(scip, &sepadata->objrow, sepa, "objrow", intobjval, SCIPinfinity(scip), FALSE, !SCIPallVarsInProb(scip), TRUE) ); sepadata->setoff = intobjval; } else { if( attendobjvarbound ) intobjval = SCIPceil(scip, SCIPgetDualbound(scip)) - SCIPvarGetUbGlobal(sepadata->objvar); else intobjval = SCIPfloor(scip, SCIPgetDualbound(scip)); SCIP_CALL( SCIPcreateEmptyRowSepa(scip, &sepadata->objrow, sepa, "objrow", -SCIPinfinity(scip), intobjval, FALSE, !SCIPallVarsInProb(scip), TRUE) ); sepadata->setoff = intobjval; } SCIP_CALL( SCIPcacheRowExtensions(scip, sepadata->objrow) ); for( v = 0; v < nvars; ++v ) { obj = SCIPvarGetObj(vars[v]); if( !SCIPisZero(scip, obj) ) { SCIP_CALL( SCIPaddVarToRow(scip, sepadata->objrow, vars[v], obj) ); } } SCIP_CALL( SCIPaddVarToRow(scip, sepadata->objrow, sepadata->objvar, -1.0) ); SCIP_CALL( SCIPflushRowExtensions(scip, sepadata->objrow) ); SCIPdebugMessage("created objective value row: "); SCIPdebug( SCIP_CALL( SCIPprintRow(scip, sepadata->objrow, NULL) ) ); } return SCIP_OKAY; }
/** presolving execution method */ static SCIP_DECL_PRESOLEXEC(presolExecBoundshift) { /*lint --e{715}*/ SCIP_PRESOLDATA* presoldata; SCIP_VAR** scipvars; SCIP_VAR** vars; int nbinvars; int nvars; int v; assert(scip != NULL); assert(presol != NULL); assert(strcmp(SCIPpresolGetName(presol), PRESOL_NAME) == 0); assert(result != NULL); *result = SCIP_DIDNOTRUN; /* get presolver data */ presoldata = SCIPpresolGetData(presol); assert(presoldata != NULL); /* get the problem variables */ scipvars = SCIPgetVars(scip); nbinvars = SCIPgetNBinVars(scip); nvars = SCIPgetNVars(scip) - nbinvars; if( nvars == 0 ) return SCIP_OKAY; if( SCIPdoNotAggr(scip) ) return SCIP_OKAY; *result = SCIP_DIDNOTFIND; /* copy the integer variables into an own array, since adding new integer variables affects the left-most slots in * the array and thereby interferes with our search loop */ SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &scipvars[nbinvars], nvars) ); /* scan the integer, implicit, and continuous variables for possible conversion */ for( v = nvars - 1; v >= 0; --v ) { SCIP_VAR* var = vars[v]; SCIP_Real lb; SCIP_Real ub; assert(SCIPvarGetType(var) != SCIP_VARTYPE_BINARY); /* get current variable's bounds */ lb = SCIPvarGetLbGlobal(var); ub = SCIPvarGetUbGlobal(var); assert( SCIPisLE(scip, lb, ub) ); if( SCIPisEQ(scip, lb, ub) ) continue; if( presoldata->integer && !SCIPisIntegral(scip, ub - lb) ) continue; /* check if bounds are shiftable */ if( !SCIPisEQ(scip, lb, 0.0) && /* lower bound != 0.0 */ SCIPisLT(scip, ub, SCIPinfinity(scip)) && /* upper bound != infinity */ SCIPisGT(scip, lb, -SCIPinfinity(scip)) && /* lower bound != -infinity */ #if 0 SCIPisLT(scip, ub - lb, SCIPinfinity(scip)) && /* interval length less than SCIPinfinity(scip) */ #endif SCIPisLT(scip, ub - lb, (SCIP_Real) presoldata->maxshift) ) /* less than max shifting */ { SCIP_VAR* newvar; char newvarname[SCIP_MAXSTRLEN]; SCIP_Bool infeasible; SCIP_Bool redundant; SCIP_Bool aggregated; SCIPdebugMessage("convert range <%s>[%g,%g] to [%g,%g]\n", SCIPvarGetName(var), lb, ub, 0.0, (ub - lb) ); /* create new variable */ (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_shift", SCIPvarGetName(var)); SCIP_CALL( SCIPcreateVar(scip, &newvar, newvarname, 0.0, (ub - lb), 0.0, SCIPvarGetType(var), SCIPvarIsInitial(var), SCIPvarIsRemovable(var), NULL, NULL, NULL, NULL, NULL) ); SCIP_CALL( SCIPaddVar(scip, newvar) ); /* aggregate old variable with new variable */ if( presoldata->flipping ) { if( REALABS(ub) < REALABS(lb) ) { SCIP_CALL( SCIPaggregateVars(scip, var, newvar, 1.0, 1.0, ub, &infeasible, &redundant, &aggregated) ); } else { SCIP_CALL( SCIPaggregateVars(scip, var, newvar, 1.0, -1.0, lb, &infeasible, &redundant, &aggregated) ); } } else { SCIP_CALL( SCIPaggregateVars(scip, var, newvar, 1.0, -1.0, lb, &infeasible, &redundant, &aggregated) ); } assert(!infeasible); assert(redundant); assert(aggregated); SCIPdebugMessage("var <%s> with bounds [%f,%f] has obj %f\n", SCIPvarGetName(newvar),SCIPvarGetLbGlobal(newvar),SCIPvarGetUbGlobal(newvar),SCIPvarGetObj(newvar)); /* release variable */ SCIP_CALL( SCIPreleaseVar(scip, &newvar) ); /* take care of statistic */ (*naggrvars)++; *result = SCIP_SUCCESS; } } /* free temporary memory */ SCIPfreeBufferArray(scip, &vars); 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; }
/** problem reading method of reader */ static SCIP_DECL_READERREAD(readerReadCip) { /*lint --e{715}*/ CIPINPUT cipinput; SCIP_Real objscale; SCIP_Real objoffset; SCIP_Bool initialconss; SCIP_Bool dynamicconss; SCIP_Bool dynamiccols; SCIP_Bool dynamicrows; SCIP_Bool initialvar; SCIP_Bool removablevar; SCIP_RETCODE retcode; if( NULL == (cipinput.file = SCIPfopen(filename, "r")) ) { SCIPerrorMessage("cannot open file <%s> for reading\n", filename); SCIPprintSysError(filename); return SCIP_NOFILE; } cipinput.len = 131071; SCIP_CALL( SCIPallocBufferArray(scip, &(cipinput.strbuf), cipinput.len) ); cipinput.linenumber = 0; cipinput.section = CIP_START; cipinput.haserror = FALSE; cipinput.endfile = FALSE; cipinput.readingsize = 65535; SCIP_CALL( SCIPcreateProb(scip, filename, NULL, NULL, NULL, NULL, NULL, NULL, NULL) ); SCIP_CALL( SCIPgetBoolParam(scip, "reading/initialconss", &initialconss) ); SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamiccols", &dynamiccols) ); SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicconss", &dynamicconss) ); SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicrows", &dynamicrows) ); initialvar = !dynamiccols; removablevar = dynamiccols; objscale = 1.0; objoffset = 0.0; while( cipinput.section != CIP_END && !cipinput.haserror ) { /* get next input string */ SCIP_CALL( getInputString(scip, &cipinput) ); if( cipinput.endfile ) break; switch( cipinput.section ) { case CIP_START: getStart(scip, &cipinput); break; case CIP_STATISTIC: SCIP_CALL( getStatistics(scip, &cipinput) ); break; case CIP_OBJECTIVE: SCIP_CALL( getObjective(scip, &cipinput, &objscale, &objoffset) ); break; case CIP_VARS: retcode = getVariable(scip, &cipinput, initialvar, removablevar, objscale); if( retcode == SCIP_READERROR ) { cipinput.haserror = TRUE; goto TERMINATE; } SCIP_CALL(retcode); break; case CIP_FIXEDVARS: retcode = getFixedVariable(scip, &cipinput); if( retcode == SCIP_READERROR ) { cipinput.haserror = TRUE; goto TERMINATE; } SCIP_CALL(retcode); break; case CIP_CONSTRAINTS: retcode = getConstraint(scip, &cipinput, initialconss, dynamicconss, dynamicrows); if( retcode == SCIP_READERROR ) { cipinput.haserror = TRUE; goto TERMINATE; } SCIP_CALL(retcode); break; default: SCIPerrorMessage("invalid CIP state\n"); SCIPABORT(); return SCIP_INVALIDDATA; /*lint !e527*/ } /*lint !e788*/ } if( !SCIPisZero(scip, objoffset) && !cipinput.haserror ) { SCIP_VAR* objoffsetvar; objoffset *= objscale; SCIP_CALL( SCIPcreateVar(scip, &objoffsetvar, "objoffset", objoffset, objoffset, 1.0, SCIP_VARTYPE_CONTINUOUS, TRUE, TRUE, NULL, NULL, NULL, NULL, NULL) ); SCIP_CALL( SCIPaddVar(scip, objoffsetvar) ); SCIP_CALL( SCIPreleaseVar(scip, &objoffsetvar) ); SCIPdebugMessage("added variables <objoffset> for objective offset of <%g>\n", objoffset); } if( cipinput.section != CIP_END && !cipinput.haserror ) { SCIPerrorMessage("unexpected EOF\n"); } TERMINATE: /* close file stream */ SCIPfclose(cipinput.file); SCIPfreeBufferArray(scip, &cipinput.strbuf); if( cipinput.haserror ) return SCIP_READERROR; /* successfully parsed cip format */ *result = SCIP_SUCCESS; return SCIP_OKAY; }
/** initializes the pricing problem for the given capacity */ static SCIP_RETCODE initPricing( SCIP* scip, /**< SCIP data structure */ SCIP_PRICERDATA* pricerdata, /**< pricer data */ SCIP* subscip, /**< pricing SCIP data structure */ SCIP_VAR** vars, /**< variable array for the items */ int b /**< the bin we are looking at */ ) { SCIP_CONS** conss; SCIP_Longint* vals; SCIP_CONS* cons; SCIP_VAR* var; SCIP_Longint* weights; SCIP_Longint* values; SCIP_Longint* capacities; SCIP_Real dual; int nitems; int nbins; int nvars; int c; assert(SCIPgetStage(subscip) == SCIP_STAGE_PROBLEM); assert(pricerdata != NULL); nitems = pricerdata->nitems; conss = pricerdata->conss; weights = pricerdata->weights; capacities = pricerdata->capacities; values = pricerdata->values; nbins = pricerdata->nbins; nvars = 0; SCIP_CALL(SCIPallocBufferArray(subscip, &vals, nitems)); /* create for each order, which is not assigned yet, a variable with objective coefficient */ for (c = 0; c < nitems; ++c) { cons = conss[c]; /* check if each constraint is setppc constraint */ assert(!strncmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), "setppc", 6)); /* constraints which are (locally) disabled/redundant are not of * interest since the corresponding job is assigned to a packing */ if (!SCIPconsIsEnabled(cons)) { // SCIPwarningMessage("TROUBLE!"); continue; } if (SCIPgetNFixedonesSetppc(scip, cons) == 1) { /* disable constraint locally */ SCIP_CALL(SCIPdelConsLocal(scip, cons)); // SCIPwarningMessage("TROUBLE!"); continue; } /* dual value in original SCIP */ dual = -SCIPgetDualsolSetppc(scip, cons); //assert(dual >= 0); // TODO: Edit when correct objsense SCIP_CALL(SCIPcreateVar(subscip, &var, SCIPconsGetName(cons), 0.0, 1.0, values[c]-dual, SCIP_VARTYPE_BINARY, TRUE, FALSE, NULL, NULL, NULL, NULL, NULL)); SCIP_CALL(SCIPaddVar(subscip, var)); vals[nvars] = weights[c]; vars[nvars] = var; nvars++; /* release variable */ SCIP_CALL(SCIPreleaseVar(subscip, &var)); } /* create capacity constraint */ SCIP_CALL(SCIPcreateConsKnapsack(subscip, &cons, "capacity", nvars, vars, vals, capacities[b], TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE)); SCIP_CALL(SCIPaddCons(subscip, cons)); SCIP_CALL(SCIPreleaseCons(subscip, &cons)); /* add constraint of the branching decisions */ SCIP_CALL(addBranchingDecisionConss(scip, subscip, vars, pricerdata->conshdlr)); /* avoid to generate columns which are fixed to zero */ SCIP_CALL(addFixedVarsConss(scip, subscip, vars, conss, nitems)); SCIPfreeBufferArray(subscip, &vals); return SCIP_OKAY; }
/** creates a cumulative scheduling problem */ SCIP_RETCODE SCIPcreateSchedulingProblem( SCIP* scip, /**< SCIP data structure */ const char* problemname, /**< problem name */ const char** jobnames, /**< job names, or NULL */ const char** resourcenames, /**< resource names, or NULL */ int** demands, /**< demand matrix resource job demand */ SCIP_DIGRAPH* precedencegraph, /**< direct graph to store the precedence conditions */ int* durations, /**< array to store the processing for each job */ int* capacities, /**< array to store the different capacities */ int njobs, /**< number of jobs to be parsed */ int nresources /**< number of capacities to be parsed */ ) { SCIP_VAR** jobs; SCIP_VAR** vars; SCIP_VAR* var; SCIP_CONS* cons; char name[SCIP_MAXSTRLEN]; int* consdurations; int* consdemands; int nvars; int ubmakespan; int i; int j; int r; assert( scip != NULL ); assert( njobs >= 0 ); SCIPdebugMessage( "start method SCIPcreateSchedulingSMProblem\n"); /* create SCIP data structure */ SCIP_CALL( SCIPcreateProb(scip, problemname, NULL, NULL, NULL, NULL, NULL, NULL, NULL) ); /* compute a feasible upper bound on the makespan */ ubmakespan = computeUbmakespan(durations, njobs); ubmakespan *= 100; /* allocate buffer for jobs and precedence constraints */ SCIP_CALL( SCIPallocBufferArray(scip, &jobs, njobs) ); /* create an activity constraint for each activity */ for( j = 0; j < njobs - 1; ++j ) /* but not for last job which is the makespan (-1) */ { /* construct variable name */ if( jobnames != NULL ) (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "start_%s", jobnames[j]); else (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "start_%d", j); /* create integer starting variable */ SCIP_CALL( SCIPcreateVar(scip, &var, name, 0.0, (SCIP_Real)ubmakespan, 0.0, SCIP_VARTYPE_INTEGER, TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) ); SCIP_CALL( SCIPaddVar(scip, var) ); SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, var) ); jobs[j] = var; SCIP_CALL( SCIPreleaseVar(scip, &var) ); } /* create makespan variable */ SCIP_CALL( SCIPcreateVar(scip, &var, "makespan", 0.0, (SCIP_Real)ubmakespan, 1.0, SCIP_VARTYPE_INTEGER, TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) ); SCIP_CALL( SCIPaddVar(scip, var) ); SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, var) ); jobs[njobs-1] = var; SCIP_CALL( SCIPreleaseVar(scip, &var) ); /* precedence constraints */ for( j = 0; j < njobs - 1; ++j ) { SCIP_VAR* predvar; int nsuccessors; nsuccessors = SCIPdigraphGetNSuccessors(precedencegraph, j); predvar = jobs[j]; assert(predvar != NULL); if( nsuccessors > 0 ) { int* successors; void** distances; successors = SCIPdigraphGetSuccessors(precedencegraph, j); distances = SCIPdigraphGetSuccessorsDatas(precedencegraph, j); for( i = 0; i < nsuccessors; ++i ) { SCIP_VAR* succvar; int distance; succvar = jobs[successors[i]]; assert(succvar != NULL); (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "precedences_(%d,%d)", j, successors[i]); distance = (int)(size_t)distances[i]; if( distance == INT_MAX ) distance = durations[j]; SCIP_CALL( SCIPcreateConsVarbound(scip, &cons, name, predvar, succvar, -1.0, -SCIPinfinity(scip), -distance, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) ); SCIP_CALL( SCIPaddCons(scip, cons) ); SCIP_CALL( SCIPreleaseCons(scip, &cons) ); } } else { /* add precedence constraints for those jobs without successor */ (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "precedences_(%d,%d)", j, njobs); SCIP_CALL( SCIPcreateConsVarbound(scip, &cons, name, predvar, jobs[njobs-1], -1.0, -SCIPinfinity(scip), -durations[j], TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) ); SCIP_CALL( SCIPaddCons(scip, cons) ); SCIP_CALL( SCIPreleaseCons(scip, &cons) ); } } SCIP_CALL( SCIPallocBufferArray(scip, &vars, njobs) ); SCIP_CALL( SCIPallocBufferArray(scip, &consdemands, njobs) ); SCIP_CALL( SCIPallocBufferArray(scip, &consdurations, njobs) ); /* create resource constraints */ for( r = 0; r < nresources; ++r ) { nvars = 0; for( j = 0; j < njobs; ++j ) /* also makespan constraint! */ { if( demands[j][r] > 0 ) { vars[nvars] = jobs[j]; consdemands[nvars] = demands[j][r]; consdurations[nvars] = durations[j]; nvars++; } } if( nvars > 0 ) { /* construct constraint name */ if( resourcenames != NULL ) (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "R%s", resourcenames[r]); else (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "R%d", r); SCIP_CALL( SCIPcreateConsCumulative(scip, &cons, name, nvars, vars, consdurations, consdemands, capacities[r], TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) ); SCIP_CALL( SCIPaddCons(scip, cons) ); SCIP_CALL( SCIPreleaseCons(scip, &cons) ); } } /* initialize the problem specific heuristic */ SCIP_CALL( SCIPinitializeHeurListScheduling(scip, precedencegraph, jobs, durations, demands, capacities, njobs, nresources) ); /* free buffer array */ SCIPfreeBufferArray(scip, &consdurations); SCIPfreeBufferArray(scip, &consdemands); SCIPfreeBufferArray(scip, &vars); SCIPfreeBufferArray(scip, &jobs); return SCIP_OKAY; }