GamsScip::~GamsScip() { SCIP_CALL_ABORT( freeSCIP() ); #ifdef GAMS_BUILD if( pal != NULL ) palFree(&pal); #endif }
/* 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; }
int GamsScip::callSolver() { assert(gmo != NULL); assert(gev != NULL); assert(scip != NULL); /* set interface type so we see =B= and =X= equations */ gmoInterfaceSet(gmo, gmoIFace_Raw); if( gmoGetEquTypeCnt(gmo, gmoequ_C) || gmoGetEquTypeCnt(gmo, gmoequ_B) || gmoGetEquTypeCnt(gmo, gmoequ_X) ) { gevLogStat(gev, "ERROR: Conic and logic constraints and external functions not supported by SCIP interface.\n"); gmoSolveStatSet(gmo, gmoSolveStat_Capability); gmoModelStatSet(gmo, gmoModelStat_NoSolutionReturned); return 1; } // set number of threads for linear algebra routines used in Ipopt setNumThreads(gev, gevThreads(gev)); // update error printing callback in SCIP to use current gev SCIPmessageSetErrorPrinting(printErrorGev, (void*)gev); SCIP_RETCODE scipret; // let GMO reader setup SCIP parameters and read options file // do this here already so we know how to assemble dialog scipret = SCIPreadParamsReaderGmo(scip); if( scipret != SCIP_OKAY ) { char buffer[256]; sprintf(buffer, "Error %d in call of SCIP function\n", scipret); gevLogStatPChar(gev, buffer); gmoSolveStatSet(gmo, gmoSolveStat_SystemErr); gmoModelStatSet(gmo, gmoModelStat_ErrorNoSolution); return 1; } SCIPinfoMessage(scip, NULL, "non-default parameter settings:\n"); SCIPwriteParams(scip, NULL, FALSE, TRUE); char* interactive = NULL; SCIP_CALL_ABORT( SCIPgetStringParam(scip, "gams/interactive", &interactive) ); assert(interactive != NULL); #ifdef GAMS_BUILD if( interactive[0] != '\0' && !palLicenseIsAcademic(pal) ) { gevLogStat(gev, "SCIP interactive shell not available in demo mode.\n"); interactive[0] = '\0'; } #endif SCIP_Bool printstat; SCIP_CALL_ABORT( SCIPgetBoolParam(scip, "display/statistics", &printstat) ); char* attrfile = NULL; #if 0 SCIP_CALL( SCIPgetStringParam(scip, "constraints/attrfile", &attrfile) ); #endif // setup commands to be executed by SCIP SCIP_CALL_ABORT( SCIPaddDialogInputLine(scip, "readgams") ); // setup model if( attrfile != NULL && *attrfile != '\0' ) { char buffer[SCIP_MAXSTRLEN + 10]; size_t len; len = strlen(attrfile); if( len >= 3 && strcmp(&attrfile[len-3], ".ca") == 0 ) (void) SCIPsnprintf(buffer, sizeof(buffer), "read %g", attrfile); else (void) SCIPsnprintf(buffer, sizeof(buffer), "read %g ca", attrfile); SCIP_CALL_ABORT( SCIPaddDialogInputLine(scip, buffer) ); // process constraints attribute file } if( interactive[0] == '\0' ) { SCIP_CALL_ABORT( SCIPaddDialogInputLine(scip, "optimize") ); // solve model if( printstat ) { SCIP_CALL_ABORT( SCIPaddDialogInputLine(scip, "disp statistics") ); // display solution statistics } SCIP_CALL_ABORT( SCIPaddDialogInputLine(scip, "write gamssol") ); // pass solution to GMO SCIP_CALL_ABORT( SCIPaddDialogInputLine(scip, "quit") ); // quit shell } else { // pass user commands to shell SCIP_CALL_ABORT( SCIPaddDialogInputLine(scip, interactive) ); } // run SCIP scipret = SCIPstartInteraction(scip); // evaluate SCIP return code switch( scipret ) { case SCIP_OKAY: break; case SCIP_READERROR: /* if it's readerror, then we guess that it comes from encountering an unsupported gams instruction in the gmo readers makeExprtree method * we still return with zero then */ gmoModelStatSet(gmo, gmoModelStat_NoSolutionReturned); gmoSolveStatSet(gmo, gmoSolveStat_Capability); break; case SCIP_LPERROR: case SCIP_MAXDEPTHLEVEL: /* if SCIP failed due to internal error (forced LP solve failed, max depth level reached), also return zero */ gmoModelStatSet(gmo, gmoModelStat_ErrorNoSolution); gmoSolveStatSet(gmo, gmoSolveStat_SolverErr); break; case SCIP_NOMEMORY: /* there is no extra solver status for running out of memory, but memory is a resource, so return this */ gmoModelStatSet(gmo, gmoModelStat_ErrorNoSolution); gmoSolveStatSet(gmo, gmoSolveStat_Resource); break; default: { char buffer[256]; sprintf(buffer, "Error %d in call of SCIP function\n", scipret); gevLogStatPChar(gev, buffer); gmoModelStatSet(gmo, gmoModelStat_ErrorNoSolution); gmoSolveStatSet(gmo, gmoSolveStat_SystemErr); return 1; } } return 0; }