From 40b0dd9b1616ce924a74f690798ad3d5ebe1bd53 Mon Sep 17 00:00:00 2001 From: RIIS Date: Wed, 14 Jun 2023 17:20:47 +0800 Subject: [PATCH] fix issues raised when adding COPT supports to YALMIP --- lib/copt_defaultparams.m | 6 + src/Makefile.osx | 6 +- src/Makefile.unix | 6 +- src/Makefile.win | 6 +- src/copt_computeiis.c | 186 +- src/copt_defaultparams.c | 46 + src/copt_feasrelax.c | 178 +- src/copt_read.c | 111 +- src/copt_solve.c | 222 +- src/copt_tune.c | 49 +- src/copt_write.c | 110 +- src/coptinit.c | 2731 +++++++++-------- src/coptmex.c | 6167 ++++++++++++++++++++++---------------- src/coptmex.h | 984 +++--- 14 files changed, 6071 insertions(+), 4737 deletions(-) create mode 100644 lib/copt_defaultparams.m create mode 100644 src/copt_defaultparams.c diff --git a/lib/copt_defaultparams.m b/lib/copt_defaultparams.m new file mode 100644 index 0000000..e36c059 --- /dev/null +++ b/lib/copt_defaultparams.m @@ -0,0 +1,6 @@ +% copt_defaultparams +% +% params = copt_defaultparams() +% +% This function generates default parameter settings of COPT as a MATLAB struct. +% \ No newline at end of file diff --git a/src/Makefile.osx b/src/Makefile.osx index edfecbb..4026f19 100755 --- a/src/Makefile.osx +++ b/src/Makefile.osx @@ -8,7 +8,7 @@ CFLAGS = -O2 -std=c99 -fPIC -Werror -DNDEBUG -DMATLAB_MEX_FILE C_INCS = -I. -I$(MATLAB_HOME)/extern/include -I$(COPT_HOME)/include C_LIBS = -L$(COPT_HOME)/lib -lcopt -L$(MATLAB_HOME)/bin/maci64 -lmx -lmex -lmat -C_MEXS = copt_read copt_solve copt_write copt_computeiis copt_feasrelax copt_tune +C_MEXS = copt_read copt_solve copt_write copt_computeiis copt_feasrelax copt_tune copt_defaultparams all: $(C_MEXS) @@ -36,5 +36,9 @@ copt_tune: copt_tune.c coptmex.c coptmex.h coptinit.c @$(CC) $(CFLAGS) $(C_INCS) -shared -install_name @rpath/copt_tune.mexmaci64 -o copt_tune.mexmaci64 copt_tune.c coptmex.c $(C_LIBS) @cp copt_tune.mexmaci64 ../lib +copt_defaultparams: copt_defaultparams.c coptmex.c coptmex.h coptinit.c + @$(CC) $(CFLAGS) $(C_INCS) -shared -install_name @rpath/copt_defaultparams.mexmaci64 -o copt_defaultparams.mexmaci64 copt_defaultparams.c coptmex.c $(C_LIBS) + @cp copt_defaultparams.mexmaci64 ../lib + clean: @rm -f *.mexmaci64 diff --git a/src/Makefile.unix b/src/Makefile.unix index f7327f5..5ca29dd 100755 --- a/src/Makefile.unix +++ b/src/Makefile.unix @@ -8,7 +8,7 @@ CFLAGS = -O2 -std=c99 -fPIC -Werror -DNDEBUG -DMATLAB_MEX_FILE -Wno-incompatible C_INCS = -I. -I$(MATLAB_HOME)/extern/include -I$(COPT_HOME)/include C_LIBS = -L$(COPT_HOME)/lib -lcopt -L$(MATLAB_HOME)/bin/glnxa64 -lmx -lmex -lmat -lm -ldl -C_MEXS = copt_read copt_solve copt_write copt_computeiis copt_feasrelax copt_tune +C_MEXS = copt_read copt_solve copt_write copt_computeiis copt_feasrelax copt_tune copt_defaultparams all: $(C_MEXS) @@ -36,5 +36,9 @@ copt_tune: copt_tune.c coptmex.c coptmex.h coptinit.c @$(CC) $(CFLAGS) $(C_INCS) -shared -o copt_tune.mexa64 copt_tune.c coptmex.c $(C_LIBS) @cp copt_tune.mexa64 ../lib +copt_defaultparams: copt_defaultparams.c coptmex.c coptmex.h coptinit.c + @$(CC) $(CFLAGS) $(C_INCS) -shared -o copt_defaultparams.mexa64 copt_defaultparams.c coptmex.c $(C_LIBS) + @cp copt_defaultparams.mexa64 ../lib + clean: @rm -f *.mexa64 diff --git a/src/Makefile.win b/src/Makefile.win index 70f859b..98c3993 100755 --- a/src/Makefile.win +++ b/src/Makefile.win @@ -8,7 +8,7 @@ CFLAGS = /nologo /O2 /MT /WX /DNDEBUG /DMATLAB_MEX_FILE C_INCS = -I. -I"$(MATLAB_HOME)\extern\include" -I"$(COPT_HOME)\include" C_LIBS = /LIBPATH:"$(COPT_HOME)\lib" copt.lib /LIBPATH:"$(MATLAB_HOME)\extern\lib\win64\microsoft" libmx.lib libmex.lib libmat.lib -C_MEXS = copt_read copt_solve copt_write copt_computeiis copt_feasrelax copt_tune +C_MEXS = copt_read copt_solve copt_write copt_computeiis copt_feasrelax copt_tune copt_defaultparams all: $(C_MEXS) @@ -36,5 +36,9 @@ copt_tune: copt_tune.c coptmex.c coptmex.h coptinit.c @$(CC) $(CFLAGS) $(C_INCS) copt_tune.c coptmex.c /link /dll /out:copt_tune.mexw64 $(C_LIBS) /export:mexFunction @copy /Y copt_tune.mexw64 ..\lib > nul +copt_defaultparams: copt_defaultparams.c coptmex.c coptmex.h coptinit.c + @$(CC) $(CFLAGS) $(C_INCS) copt_defaultparams.c coptmex.c /link /dll /out:copt_defaultparams.mexw64 $(C_LIBS) /export:mexFunction + @copy /Y copt_defaultparams.mexw64 ..\lib > nul + clean: @del /s /q *.mexw64 *.exp *.lib *.obj > nul diff --git a/src/copt_computeiis.c b/src/copt_computeiis.c index 90d77ef..5c86ceb 100755 --- a/src/copt_computeiis.c +++ b/src/copt_computeiis.c @@ -1,84 +1,102 @@ -#include "coptmex.h" - -void COPT_CALL COPTMEX_printLog(char *msg, void *userdata) { - if (msg != NULL) { - mexPrintf("%s\n", msg); - mexEvalString("drawnow;"); - } -} - -void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - int retcode = COPT_RETCODE_OK; - copt_env *env = NULL; - copt_prob *prob = NULL; - int retResult = 1; - - // Check if inputs/outputs are valid - if (nlhs != 0 && nlhs != 1) { - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, "outputs"); - goto exit_cleanup; - } - if (nlhs == 0) { - retResult = 0; - } - - if (nrhs == 1 || nrhs == 2) { - if (!mxIsChar(prhs[0]) && !mxIsStruct(prhs[0])) { - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, "problem/probfile"); - goto exit_cleanup; - } - if (nrhs == 2) { - if (!mxIsStruct(prhs[1])) { - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, "parameter"); - goto exit_cleanup; - } - } - } else { - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, "inputs"); - goto exit_cleanup; - } - - // Create COPT environment and problem - COPTMEX_CALL(COPT_CreateEnv(&env)); - COPTMEX_CALL(COPT_CreateProb(env, &prob)); - - // Set message callback - COPTMEX_CALL(COPT_SetLogCallback(prob, COPTMEX_printLog, NULL)); - - // Processing the second argument, if exists. - if (nrhs == 2) { - // Load and set parameters to problem - COPTMEX_CALL(COPTMEX_setParam(prob, prhs[1])); - } else { - COPTMEX_CALL(COPTMEX_dispBanner()); - } - - // Processing the first argument - // 1. 'string': a valid problem file; - // 2. 'struct': a struct that specify the problem data. - if (mxIsChar(prhs[0])) { - // Read the problem from file - COPTMEX_CALL(COPTMEX_readModel(prob, prhs[0])); - } else if (mxIsStruct(prhs[0])) { - // Extract and load data to problem - COPTMEX_CALL(COPTMEX_loadModel(prob, prhs[0])); - } - - // Compute IIS for infeasible problem and save result - COPTMEX_CALL(COPTMEX_computeIIS(prob, &plhs[0], retResult)); - -exit_cleanup: - if (retcode != COPT_RETCODE_OK) { - char errmsg[COPT_BUFFSIZE]; - char msgbuf[COPT_BUFFSIZE * 2]; - COPT_GetRetcodeMsg(retcode, errmsg, COPT_BUFFSIZE); - snprintf(msgbuf, COPT_BUFFSIZE * 2, "COPT Error %d: %s", retcode, errmsg); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_API, msgbuf); - } - - // Delete COPT problem and environment - COPT_DeleteProb(&prob); - COPT_DeleteEnv(&env); - - return; -} +#include "coptmex.h" + +void COPT_CALL COPTMEX_printLog(char* msg, void* userdata) +{ + if (msg != NULL) + { + mexPrintf("%s\n", msg); + mexEvalString("drawnow;"); + } +} + +void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) +{ + int retcode = COPT_RETCODE_OK; + copt_env* env = NULL; + copt_prob* prob = NULL; + int retResult = 1; + + // Check if inputs/outputs are valid + if (nlhs != 0 && nlhs != 1) + { + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, "outputs"); + goto exit_cleanup; + } + if (nlhs == 0) + { + retResult = 0; + } + + if (nrhs == 1 || nrhs == 2) + { + if (!mxIsChar(prhs[0]) && !mxIsStruct(prhs[0])) + { + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, "problem/probfile"); + goto exit_cleanup; + } + if (nrhs == 2) + { + if (!mxIsStruct(prhs[1])) + { + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, "parameter"); + goto exit_cleanup; + } + } + } + else + { + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, "inputs"); + goto exit_cleanup; + } + + // Create COPT environment and problem + COPTMEX_CALL(COPT_CreateEnv(&env)); + COPTMEX_CALL(COPT_CreateProb(env, &prob)); + + // Set message callback + COPTMEX_CALL(COPT_SetLogCallback(prob, COPTMEX_printLog, NULL)); + + // Processing the second argument, if exists. + if (nrhs == 2) + { + // Load and set parameters to problem + COPTMEX_CALL(COPTMEX_setParam(prob, prhs[1])); + } + else + { + COPTMEX_CALL(COPTMEX_dispBanner()); + } + + // Processing the first argument + // 1. 'string': a valid problem file; + // 2. 'struct': a struct that specify the problem data. + if (mxIsChar(prhs[0])) + { + // Read the problem from file + COPTMEX_CALL(COPTMEX_readModel(prob, prhs[0])); + } + else if (mxIsStruct(prhs[0])) + { + // Extract and load data to problem + COPTMEX_CALL(COPTMEX_loadModel(prob, prhs[0])); + } + + // Compute IIS for infeasible problem and save result + COPTMEX_CALL(COPTMEX_computeIIS(prob, &plhs[0], retResult)); + +exit_cleanup: + if (retcode != COPT_RETCODE_OK) + { + char errmsg[COPT_BUFFSIZE]; + char msgbuf[COPT_BUFFSIZE * 2]; + COPT_GetRetcodeMsg(retcode, errmsg, COPT_BUFFSIZE); + snprintf(msgbuf, COPT_BUFFSIZE * 2, "COPT Error %d: %s", retcode, errmsg); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_API, msgbuf); + } + + // Delete COPT problem and environment + COPT_DeleteProb(&prob); + COPT_DeleteEnv(&env); + + return; +} diff --git a/src/copt_defaultparams.c b/src/copt_defaultparams.c new file mode 100644 index 0000000..3b3bd7b --- /dev/null +++ b/src/copt_defaultparams.c @@ -0,0 +1,46 @@ +#include "coptmex.h" + +void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) +{ + int retcode = COPT_RETCODE_OK; + copt_env* env = NULL; + copt_prob* prob = NULL; + + // Check if arguments are valid + if (nlhs > 1) + { + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, "outputs"); + goto exit_cleanup; + } + if (nrhs > 0) + { + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, "inputs"); + goto exit_cleanup; + } + + // Create COPT environment and problem + COPTMEX_CALL(COPT_CreateEnv(&env)); + COPTMEX_CALL(COPT_CreateProb(env, &prob)); + + // Generate default parameters + if (nlhs == 1) + { + COPTMEX_CALL(COPTMEX_getDefaultParams(prob, &plhs[0])); + } + +exit_cleanup: + if (retcode != COPT_RETCODE_OK) + { + char errmsg[COPT_BUFFSIZE]; + char msgbuf[COPT_BUFFSIZE * 2]; + COPT_GetRetcodeMsg(retcode, errmsg, COPT_BUFFSIZE); + snprintf(msgbuf, COPT_BUFFSIZE * 2, "COPT Error %d: %s", retcode, errmsg); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_API, msgbuf); + } + + // Delete COPT problem and environment + COPT_DeleteProb(&prob); + COPT_DeleteEnv(&env); + + return; +} diff --git a/src/copt_feasrelax.c b/src/copt_feasrelax.c index 1f698bd..a61d978 100755 --- a/src/copt_feasrelax.c +++ b/src/copt_feasrelax.c @@ -1,82 +1,96 @@ -#include "coptmex.h" - -void COPT_CALL COPTMEX_printLog(char* msg, void* userdata) { - if (msg != NULL) { - mexPrintf("%s\n", msg); - mexEvalString("drawnow;"); - } -} - -void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) { - int retcode = COPT_RETCODE_OK; - copt_env* env = NULL; - copt_prob* prob = NULL; - int retResult = 1; - - // Check if inputs/outputs are valid - if (nlhs != 0 && nlhs != 1) { - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, "outputs"); - goto exit_cleanup; - } - if (nlhs == 0) { - retResult = 0; - } - - if (nrhs == 2 || nrhs == 3) { - if (!mxIsStruct(prhs[0])) { - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, "problem"); - goto exit_cleanup; - } - if (!mxIsStruct(prhs[1])) { - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, "penalties"); - goto exit_cleanup; - } - if (nrhs == 3) { - if (!mxIsStruct(prhs[2])) { - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, "parameter"); - goto exit_cleanup; - } - } - } - else { - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, "inputs"); - goto exit_cleanup; - } - - // Create COPT environment and problem - COPTMEX_CALL(COPT_CreateEnv(&env)); - COPTMEX_CALL(COPT_CreateProb(env, &prob)); - - // Set message callback - COPTMEX_CALL(COPT_SetLogCallback(prob, COPTMEX_printLog, NULL)); - - // Processing the third argument, if exists. - if (nrhs == 3) { - // Load and set parameters to problem - COPTMEX_CALL(COPTMEX_setParam(prob, prhs[2])); - } - else { - COPTMEX_CALL(COPTMEX_dispBanner()); - } - - // Extract and load data to problem - COPTMEX_CALL(COPTMEX_loadModel(prob, prhs[0])); - - // Compute feasibility relaxation and save result - COPTMEX_CALL(COPTMEX_feasRelax(prob, prhs[1], &plhs[0], retResult)); - -exit_cleanup: - if (retcode != COPT_RETCODE_OK) { - char errmsg[COPT_BUFFSIZE]; - char msgbuf[COPT_BUFFSIZE * 2]; - COPT_GetRetcodeMsg(retcode, errmsg, COPT_BUFFSIZE); - snprintf(msgbuf, COPT_BUFFSIZE * 2, "COPT Error %d: %s", retcode, errmsg); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_API, msgbuf); - } - - // Delete COPT problem and environment - COPT_DeleteProb(&prob); - COPT_DeleteEnv(&env); - - return; -} +#include "coptmex.h" + +void COPT_CALL COPTMEX_printLog(char* msg, void* userdata) +{ + if (msg != NULL) + { + mexPrintf("%s\n", msg); + mexEvalString("drawnow;"); + } +} + +void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) +{ + int retcode = COPT_RETCODE_OK; + copt_env* env = NULL; + copt_prob* prob = NULL; + int retResult = 1; + + // Check if inputs/outputs are valid + if (nlhs != 0 && nlhs != 1) + { + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, "outputs"); + goto exit_cleanup; + } + if (nlhs == 0) + { + retResult = 0; + } + + if (nrhs == 2 || nrhs == 3) + { + if (!mxIsStruct(prhs[0])) + { + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, "problem"); + goto exit_cleanup; + } + if (!mxIsStruct(prhs[1])) + { + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, "penalties"); + goto exit_cleanup; + } + if (nrhs == 3) + { + if (!mxIsStruct(prhs[2])) + { + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, "parameter"); + goto exit_cleanup; + } + } + } + else + { + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, "inputs"); + goto exit_cleanup; + } + + // Create COPT environment and problem + COPTMEX_CALL(COPT_CreateEnv(&env)); + COPTMEX_CALL(COPT_CreateProb(env, &prob)); + + // Set message callback + COPTMEX_CALL(COPT_SetLogCallback(prob, COPTMEX_printLog, NULL)); + + // Processing the third argument, if exists. + if (nrhs == 3) + { + // Load and set parameters to problem + COPTMEX_CALL(COPTMEX_setParam(prob, prhs[2])); + } + else + { + COPTMEX_CALL(COPTMEX_dispBanner()); + } + + // Extract and load data to problem + COPTMEX_CALL(COPTMEX_loadModel(prob, prhs[0])); + + // Compute feasibility relaxation and save result + COPTMEX_CALL(COPTMEX_feasRelax(prob, prhs[1], &plhs[0], retResult)); + +exit_cleanup: + if (retcode != COPT_RETCODE_OK) + { + char errmsg[COPT_BUFFSIZE]; + char msgbuf[COPT_BUFFSIZE * 2]; + COPT_GetRetcodeMsg(retcode, errmsg, COPT_BUFFSIZE); + snprintf(msgbuf, COPT_BUFFSIZE * 2, "COPT Error %d: %s", retcode, errmsg); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_API, msgbuf); + } + + // Delete COPT problem and environment + COPT_DeleteProb(&prob); + COPT_DeleteEnv(&env); + + return; +} diff --git a/src/copt_read.c b/src/copt_read.c index b1eb28c..e9911b1 100755 --- a/src/copt_read.c +++ b/src/copt_read.c @@ -1,51 +1,60 @@ -#include "coptmex.h" - -void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - int retcode = COPT_RETCODE_OK; - copt_env *env = NULL; - copt_prob *prob = NULL; - - // Check if inputs/outputs are valid - if (nlhs != 1) { - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, "outputs"); - goto exit_cleanup; - } - - if (nrhs == 1 || nrhs == 2) { - if (!mxIsChar(prhs[0])) { - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, "probfile"); - goto exit_cleanup; - } - if (nrhs == 2) { - if (!mxIsChar(prhs[1])) { - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, "infofile"); - goto exit_cleanup; - } - } - } else { - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, "inputs"); - goto exit_cleanup; - } - - // Create COPT environment and problem - COPTMEX_CALL(COPT_CreateEnv(&env)); - COPTMEX_CALL(COPT_CreateProb(env, &prob)); - - // Extract model data from file - COPTMEX_CALL(COPTMEX_getModel(prob, nrhs, prhs, &plhs[0])); - -exit_cleanup: - if (retcode != COPT_RETCODE_OK) { - char errmsg[COPT_BUFFSIZE]; - char msgbuf[COPT_BUFFSIZE * 2]; - COPT_GetRetcodeMsg(retcode, errmsg, COPT_BUFFSIZE); - snprintf(msgbuf, COPT_BUFFSIZE * 2, "COPT Error %d: %s", retcode, errmsg); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_API, msgbuf); - } - - // Delete COPT problem and environment - COPT_DeleteProb(&prob); - COPT_DeleteEnv(&env); - - return; -} +#include "coptmex.h" + +void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) +{ + int retcode = COPT_RETCODE_OK; + copt_env* env = NULL; + copt_prob* prob = NULL; + + // Check if inputs/outputs are valid + if (nlhs != 1) + { + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, "outputs"); + goto exit_cleanup; + } + + if (nrhs == 1 || nrhs == 2) + { + if (!mxIsChar(prhs[0])) + { + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, "probfile"); + goto exit_cleanup; + } + if (nrhs == 2) + { + if (!mxIsChar(prhs[1])) + { + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, "infofile"); + goto exit_cleanup; + } + } + } + else + { + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, "inputs"); + goto exit_cleanup; + } + + // Create COPT environment and problem + COPTMEX_CALL(COPT_CreateEnv(&env)); + COPTMEX_CALL(COPT_CreateProb(env, &prob)); + + // Extract model data from file + COPTMEX_CALL(COPTMEX_getModel(prob, nrhs, prhs, &plhs[0])); + +exit_cleanup: + if (retcode != COPT_RETCODE_OK) + { + char errmsg[COPT_BUFFSIZE]; + char msgbuf[COPT_BUFFSIZE * 2]; + COPT_GetRetcodeMsg(retcode, errmsg, COPT_BUFFSIZE); + snprintf(msgbuf, COPT_BUFFSIZE * 2, "COPT Error %d: %s", retcode, errmsg); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_API, msgbuf); + } + + // Delete COPT problem and environment + COPT_DeleteProb(&prob); + COPT_DeleteEnv(&env); + + return; +} diff --git a/src/copt_solve.c b/src/copt_solve.c index 1e196af..ba49621 100755 --- a/src/copt_solve.c +++ b/src/copt_solve.c @@ -1,99 +1,123 @@ -#include "coptmex.h" - -void COPT_CALL COPTMEX_printLog(char *msg, void *userdata) { - if (msg != NULL) { - mexPrintf("%s\n", msg); - mexEvalString("drawnow;"); - } -} - -void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - int retcode = COPT_RETCODE_OK; - copt_env *env = NULL; - copt_prob *prob = NULL; - int retResult = 1; - int ifConeData = 0; - - // Check if inputs/outputs are valid - if (nlhs != 1 && nlhs != 0) { - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, "outputs"); - goto exit_cleanup; - } - if (nlhs == 0) { - retResult = 0; - } - - if (nrhs == 0) { - COPTMEX_CALL(COPTMEX_getVersion(&plhs[0])); - return; - } else if (nrhs == 1 || nrhs == 2) { - if (!mxIsChar(prhs[0]) && !mxIsStruct(prhs[0])) { - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, "problem/probfile"); - goto exit_cleanup; - } - if (nrhs == 2) { - if (!mxIsStruct(prhs[1])) { - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, "parameter"); - goto exit_cleanup; - } - } - } else { - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, "inputs"); - goto exit_cleanup; - } - - // Create COPT environment and problem - COPTMEX_CALL(COPT_CreateEnv(&env)); - COPTMEX_CALL(COPT_CreateProb(env, &prob)); - - // Set message callback - COPTMEX_CALL(COPT_SetLogCallback(prob, COPTMEX_printLog, NULL)); - - // Processing the second argument, if exists. - if (nrhs == 2) { - // Load and set parameters to problem - COPTMEX_CALL(COPTMEX_setParam(prob, prhs[1])); - } else { - COPTMEX_CALL(COPTMEX_dispBanner()); - } - - // Processing the first argument - // 1. 'string': a valid problem file; - // 2. 'struct': a struct that specify the problem data. - if (mxIsChar(prhs[0])) { - // Read the problem from file - COPTMEX_CALL(COPTMEX_readModel(prob, prhs[0])); - } else if (mxIsStruct(prhs[0])) { - // Extract and load data to problem - ifConeData = COPTMEX_isConeModel(prhs[0]); - if (ifConeData) { - COPTMEX_CALL(COPTMEX_solveConeModel(prob, prhs[0], &plhs[0], retResult)); - goto exit_cleanup; - } else { - COPTMEX_CALL(COPTMEX_loadModel(prob, prhs[0])); - } - } - - // Solve the problem - COPTMEX_CALL(COPT_Solve(prob)); - - // Extract and save result - if (retResult == 1) { - COPTMEX_CALL(COPTMEX_getResult(prob, &plhs[0])); - } - -exit_cleanup: - if (retcode != COPT_RETCODE_OK) { - char errmsg[COPT_BUFFSIZE]; - char msgbuf[COPT_BUFFSIZE * 2]; - COPT_GetRetcodeMsg(retcode, errmsg, COPT_BUFFSIZE); - snprintf(msgbuf, COPT_BUFFSIZE * 2, "COPT Error %d: %s", retcode, errmsg); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_API, msgbuf); - } - - // Delete COPT problem and environment - COPT_DeleteProb(&prob); - COPT_DeleteEnv(&env); - - return; -} +#include "coptmex.h" + +void COPT_CALL COPTMEX_printLog(char* msg, void* userdata) +{ + if (msg != NULL) + { + mexPrintf("%s\n", msg); + mexEvalString("drawnow;"); + } +} + +void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) +{ + int retcode = COPT_RETCODE_OK; + copt_env* env = NULL; + copt_prob* prob = NULL; + int retResult = 1; + int ifConeData = 0; + + // Check if inputs/outputs are valid + if (nlhs != 1 && nlhs != 0) + { + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, "outputs"); + goto exit_cleanup; + } + if (nlhs == 0) + { + retResult = 0; + } + + if (nrhs == 0) + { + COPTMEX_CALL(COPTMEX_getVersion(&plhs[0])); + return; + } + else if (nrhs == 1 || nrhs == 2) + { + if (!mxIsChar(prhs[0]) && !mxIsStruct(prhs[0])) + { + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, "problem/probfile"); + goto exit_cleanup; + } + if (nrhs == 2) + { + if (!mxIsStruct(prhs[1])) + { + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, "parameter"); + goto exit_cleanup; + } + } + } + else + { + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, "inputs"); + goto exit_cleanup; + } + + // Create COPT environment and problem + COPTMEX_CALL(COPT_CreateEnv(&env)); + COPTMEX_CALL(COPT_CreateProb(env, &prob)); + + // Set message callback + COPTMEX_CALL(COPT_SetLogCallback(prob, COPTMEX_printLog, NULL)); + + // Processing the second argument, if exists. + if (nrhs == 2) + { + // Load and set parameters to problem + COPTMEX_CALL(COPTMEX_setParam(prob, prhs[1])); + } + else + { + COPTMEX_CALL(COPTMEX_dispBanner()); + } + + // Processing the first argument + // 1. 'string': a valid problem file; + // 2. 'struct': a struct that specify the problem data. + if (mxIsChar(prhs[0])) + { + // Read the problem from file + COPTMEX_CALL(COPTMEX_readModel(prob, prhs[0])); + } + else if (mxIsStruct(prhs[0])) + { + // Extract and load data to problem + ifConeData = COPTMEX_isConeModel(prhs[0]); + if (ifConeData) + { + COPTMEX_CALL(COPTMEX_solveConeModel(prob, prhs[0], &plhs[0], retResult)); + goto exit_cleanup; + } + else + { + COPTMEX_CALL(COPTMEX_loadModel(prob, prhs[0])); + } + } + + // Solve the problem + COPTMEX_CALL(COPT_Solve(prob)); + + // Extract and save result + if (retResult == 1) + { + COPTMEX_CALL(COPTMEX_getResult(prob, &plhs[0])); + } + +exit_cleanup: + if (retcode != COPT_RETCODE_OK) + { + char errmsg[COPT_BUFFSIZE]; + char msgbuf[COPT_BUFFSIZE * 2]; + COPT_GetRetcodeMsg(retcode, errmsg, COPT_BUFFSIZE); + snprintf(msgbuf, COPT_BUFFSIZE * 2, "COPT Error %d: %s", retcode, errmsg); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_API, msgbuf); + } + + // Delete COPT problem and environment + COPT_DeleteProb(&prob); + COPT_DeleteEnv(&env); + + return; +} diff --git a/src/copt_tune.c b/src/copt_tune.c index 352f707..94a2284 100644 --- a/src/copt_tune.c +++ b/src/copt_tune.c @@ -1,35 +1,45 @@ #include "coptmex.h" -void COPT_CALL COPTMEX_printLog(char *msg, void *userdata) { - if (msg != NULL) { +void COPT_CALL COPTMEX_printLog(char* msg, void* userdata) +{ + if (msg != NULL) + { mexPrintf("%s\n", msg); mexEvalString("drawnow;"); } } -void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { +void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) +{ int retcode = COPT_RETCODE_OK; - copt_env *env = NULL; - copt_prob *prob = NULL; + copt_env* env = NULL; + copt_prob* prob = NULL; // Check if inputs/outputs are valid - if (nlhs != 0) { + if (nlhs != 0) + { COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, "outputs"); goto exit_cleanup; } - if (nrhs == 1 || nrhs == 2) { - if (!mxIsChar(prhs[0]) && !mxIsStruct(prhs[0])) { + if (nrhs == 1 || nrhs == 2) + { + if (!mxIsChar(prhs[0]) && !mxIsStruct(prhs[0])) + { COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, "problem/probfile"); goto exit_cleanup; } - if (nrhs == 2) { - if (!mxIsStruct(prhs[1])) { + if (nrhs == 2) + { + if (!mxIsStruct(prhs[1])) + { COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, "parameter"); goto exit_cleanup; } } - } else { + } + else + { COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, "inputs"); goto exit_cleanup; } @@ -42,20 +52,26 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { COPTMEX_CALL(COPT_SetLogCallback(prob, COPTMEX_printLog, NULL)); // Processing the second argument, if exists. - if (nrhs == 2) { + if (nrhs == 2) + { // Load and set parameters to problem COPTMEX_CALL(COPTMEX_setParam(prob, prhs[1])); - } else { + } + else + { COPTMEX_CALL(COPTMEX_dispBanner()); } // Processing the first argument // 1. 'string': a valid problem file; // 2. 'struct': a struct that specify the problem data. - if (mxIsChar(prhs[0])) { + if (mxIsChar(prhs[0])) + { // Read the problem from file COPTMEX_CALL(COPTMEX_readModel(prob, prhs[0])); - } else if (mxIsStruct(prhs[0])) { + } + else if (mxIsStruct(prhs[0])) + { // Extract and load data to problem COPTMEX_CALL(COPTMEX_loadModel(prob, prhs[0])); } @@ -64,7 +80,8 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { COPTMEX_CALL(COPT_Tune(prob)); exit_cleanup: - if (retcode != COPT_RETCODE_OK) { + if (retcode != COPT_RETCODE_OK) + { char errmsg[COPT_BUFFSIZE]; char msgbuf[COPT_BUFFSIZE * 2]; COPT_GetRetcodeMsg(retcode, errmsg, COPT_BUFFSIZE); diff --git a/src/copt_write.c b/src/copt_write.c index 9175470..784d48f 100755 --- a/src/copt_write.c +++ b/src/copt_write.c @@ -1,51 +1,59 @@ -#include "coptmex.h" - -void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - int retcode = COPT_RETCODE_OK; - copt_env *env = NULL; - copt_prob *prob = NULL; - - // Check if arguments are valid - if (nlhs != 0) { - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, "outputs"); - goto exit_cleanup; - } - - if (nrhs == 2) { - if (!mxIsStruct(prhs[0])) { - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, "problem"); - goto exit_cleanup; - } - if (!mxIsChar(prhs[1])) { - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, "probfile"); - goto exit_cleanup; - } - } else { - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, "inputs"); - goto exit_cleanup; - } - - // Create COPT environment and problem - COPTMEX_CALL(COPT_CreateEnv(&env)); - COPTMEX_CALL(COPT_CreateProb(env, &prob)); - - // Extract and load problem data - COPTMEX_CALL(COPTMEX_loadModel(prob, prhs[0])); - // Write problem to file - COPTMEX_CALL(COPTMEX_writeModel(prob, prhs[1])); - -exit_cleanup: - if (retcode != COPT_RETCODE_OK) { - char errmsg[COPT_BUFFSIZE]; - char msgbuf[COPT_BUFFSIZE * 2]; - COPT_GetRetcodeMsg(retcode, errmsg, COPT_BUFFSIZE); - snprintf(msgbuf, COPT_BUFFSIZE * 2, "COPT Error %d: %s", retcode, errmsg); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_API, msgbuf); - } - - // Delete COPT problem and environment - COPT_DeleteProb(&prob); - COPT_DeleteEnv(&env); - - return; -} +#include "coptmex.h" + +void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) +{ + int retcode = COPT_RETCODE_OK; + copt_env* env = NULL; + copt_prob* prob = NULL; + + // Check if arguments are valid + if (nlhs != 0) + { + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, "outputs"); + goto exit_cleanup; + } + + if (nrhs == 2) + { + if (!mxIsStruct(prhs[0])) + { + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, "problem"); + goto exit_cleanup; + } + if (!mxIsChar(prhs[1])) + { + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, "probfile"); + goto exit_cleanup; + } + } + else + { + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, "inputs"); + goto exit_cleanup; + } + + // Create COPT environment and problem + COPTMEX_CALL(COPT_CreateEnv(&env)); + COPTMEX_CALL(COPT_CreateProb(env, &prob)); + + // Extract and load problem data + COPTMEX_CALL(COPTMEX_loadModel(prob, prhs[0])); + // Write problem to file + COPTMEX_CALL(COPTMEX_writeModel(prob, prhs[1])); + +exit_cleanup: + if (retcode != COPT_RETCODE_OK) + { + char errmsg[COPT_BUFFSIZE]; + char msgbuf[COPT_BUFFSIZE * 2]; + COPT_GetRetcodeMsg(retcode, errmsg, COPT_BUFFSIZE); + snprintf(msgbuf, COPT_BUFFSIZE * 2, "COPT Error %d: %s", retcode, errmsg); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_API, msgbuf); + } + + // Delete COPT problem and environment + COPT_DeleteProb(&prob); + COPT_DeleteEnv(&env); + + return; +} diff --git a/src/coptinit.c b/src/coptinit.c index ecaea22..3e107be 100755 --- a/src/coptinit.c +++ b/src/coptinit.c @@ -1,1277 +1,1454 @@ -#include "coptmex.h" -#include - -/* Initialize MEX-style version */ -static void COPTMEX_initVersion(coptmex_mversion *version) { - version->major = NULL; - version->minor = NULL; - version->technical = NULL; - return; -} - -/* Initialize C-style problem */ -static void COPTMEX_initCProb(coptmex_cprob *cprob) { - // The main part of problem - cprob->nRow = 0; - cprob->nCol = 0; - cprob->nElem = 0; - cprob->nObjSen = COPT_MINIMIZE; - cprob->dObjConst = 0.0; - - cprob->colMatBeg = NULL; - cprob->colMatIdx = NULL; - cprob->colMatElem = NULL; - - cprob->colCost = NULL; - cprob->colLower = NULL; - cprob->colUpper = NULL; - cprob->rowLower = NULL; - cprob->rowUpper = NULL; - - cprob->colType = NULL; - cprob->rowSense = NULL; - cprob->colNames = NULL; - cprob->rowNames = NULL; - - // The optional SOS part - cprob->nSos = 0; - cprob->nSosSize = 0; - cprob->sosType = NULL; - cprob->sosMatBeg = NULL; - cprob->sosMatCnt = NULL; - cprob->sosMatIdx = NULL; - cprob->sosMatWt = NULL; - - // The optional indicator part - cprob->nIndicator = 0; - - // The optional cone part - cprob->nCone = 0; - cprob->nConeSize = 0; - cprob->coneType = NULL; - cprob->coneBeg = NULL; - cprob->coneCnt = NULL; - cprob->coneIdx = NULL; - - // The optional Q objective part - cprob->nQElem = 0; - - // The optional quadratic constraint part - cprob->nQConstr = 0; - - // The optional advanced information - cprob->hasBasis = 0; - cprob->colBasis = NULL; - cprob->rowBasis = NULL; - return; -} - -/* Initialize MEX-style problem */ -static void COPTMEX_initMProb(coptmex_mprob *mprob) { - // The main part of problem - mprob->objsen = NULL; - mprob->objcon = NULL; - mprob->A = NULL; - mprob->obj = NULL; - mprob->lb = NULL; - mprob->ub = NULL; - mprob->vtype = NULL; - mprob->varnames = NULL; - mprob->sense = NULL; - mprob->lhs = NULL; - mprob->rhs = NULL; - mprob->constrnames = NULL; - - // The optional SOS part - mprob->sos = NULL; - - // The optional indicator part - mprob->indicator = NULL; - - // The optional cone part - mprob->cone = NULL; - - // The optional Q objective part - mprob->qobj = NULL; - - // The optional quadratic constraint part - mprob->quadcon = NULL; - - // The optional advanced information - mprob->varbasis = NULL; - mprob->constrbasis = NULL; - - mprob->value = NULL; - mprob->slack = NULL; - mprob->dual = NULL; - mprob->redcost = NULL; - - mprob->mipstart = NULL; - return; -} - -/* Initialize C-style cone problem */ -static void COPTMEX_initCConeProb(coptmex_cconeprob *cconeprob) { - cconeprob->nCol = 0; - cconeprob->nRow = 0; - - cconeprob->nObjSense = COPT_MINIMIZE; - cconeprob->dObjConst = 0.0; - - cconeprob->nFree = 0; - cconeprob->nPositive = 0; - cconeprob->nCone = 0; - cconeprob->nRotateCone = 0; - cconeprob->nPSD = 0; - - cconeprob->coneDim = NULL; - cconeprob->rotateConeDim = NULL; - cconeprob->psdDim = NULL; - - cconeprob->colObj = NULL; - - cconeprob->nQObjElem = 0; - cconeprob->qObjRow = NULL; - cconeprob->qObjCol = NULL; - cconeprob->qObjElem = NULL; - - cconeprob->colMatBeg = NULL; - cconeprob->colMatIdx = NULL; - cconeprob->colMatElem = NULL; - - cconeprob->rowRhs = NULL; -} - -/* Initialize MEX-style cone problem */ -static void COPTMEX_initMConeProb(coptmex_mconeprob *mconeprob) { - mconeprob->c = NULL; - mconeprob->A = NULL; - mconeprob->b = NULL; - - mconeprob->K = NULL; - mconeprob->f = NULL; - mconeprob->l = NULL; - mconeprob->q = NULL; - mconeprob->r = NULL; - mconeprob->s = NULL; - - mconeprob->objsen = NULL; - mconeprob->objcon = NULL; - mconeprob->Q = NULL; -} - -/* Initialize C-style LP solution */ -static void COPTMEX_initCLpSol(coptmex_clpsol *clpsol) { - clpsol->nRow = 0; - clpsol->nCol = 0; - clpsol->nPSD = 0; - clpsol->nPSDLen = 0; - clpsol->nPSDConstr = 0; - clpsol->nQConstr = 0; - clpsol->hasBasis = 0; - clpsol->hasLpSol = 0; - - clpsol->nStatus = COPT_LPSTATUS_UNSTARTED; - clpsol->nSimplexIter = 0; - clpsol->nBarrierIter = 0; - clpsol->dSolvingTime = 0.0; - clpsol->dObjVal = COPT_INFINITY; - - clpsol->colBasis = NULL; - clpsol->rowBasis = NULL; - clpsol->colValue = NULL; - clpsol->colDual = NULL; - clpsol->rowSlack = NULL; - clpsol->rowDual = NULL; - clpsol->primalRay = NULL; - clpsol->dualFarkas = NULL; - - clpsol->qRowSlack = NULL; - - clpsol->psdColValue = NULL; - clpsol->psdColDual = NULL; - clpsol->psdRowSlack = NULL; - clpsol->psdRowDual = NULL; - return; -} - -/* Initialize C-style MIP solution */ -static void COPTMEX_initCMipSol(coptmex_cmipsol *cmipsol) { - cmipsol->nRow = 0; - cmipsol->nCol = 0; - cmipsol->hasMipSol = 0; - - cmipsol->nStatus = COPT_MIPSTATUS_UNSTARTED; - cmipsol->nSimplexIter = 0; - cmipsol->nNodeCnt = 0; - cmipsol->dBestGap = COPT_INFINITY; - cmipsol->dSolvingTime = 0.0; - cmipsol->dObjVal = COPT_INFINITY; - cmipsol->dBestBnd = -COPT_INFINITY; - - cmipsol->colValue = NULL; - - cmipsol->nSolPool = 0; - return; -} - -/* Initialize C-style IIS information */ -static void COPTMEX_initCIISInfo(coptmex_ciisinfo *ciisinfo) { - ciisinfo->isMinIIS = 0; - ciisinfo->colLowerIIS = NULL; - ciisinfo->colUpperIIS = NULL; - ciisinfo->rowLowerIIS = NULL; - ciisinfo->rowUpperIIS = NULL; - ciisinfo->sosIIS = NULL; - ciisinfo->indicatorIIS = NULL; - return; -} - -/* Initialize C-style feasibility relaxation information */ -static void COPTMEX_initCRelaxInfo(coptmex_crelaxinfo *crelaxinfo) { - crelaxinfo->dObjVal = 0.0; - crelaxinfo->colValue = NULL; - crelaxinfo->colLowRlx = NULL; - crelaxinfo->colUppRlx = NULL; - crelaxinfo->rowLowRlx = NULL; - crelaxinfo->rowUppRlx = NULL; - return; -} - -/* Initialize MEX-style LP solution */ -static void COPTMEX_initMLpSol(coptmex_mlpsol *mlpsol) { - mlpsol->status = NULL; - mlpsol->simplexiter = NULL; - mlpsol->barrieriter = NULL; - mlpsol->solvingtime = NULL; - mlpsol->objval = NULL; - mlpsol->varbasis = NULL; - mlpsol->constrbasis = NULL; - mlpsol->value = NULL; - mlpsol->redcost = NULL; - mlpsol->slack = NULL; - mlpsol->dual = NULL; - mlpsol->ray = NULL; - mlpsol->farkas = NULL; - mlpsol->qcslack = NULL; - mlpsol->psdcolvalue = NULL; - mlpsol->psdcoldual = NULL; - mlpsol->psdrowslack = NULL; - mlpsol->psdrowdual = NULL; - return; -} - -/* Initialize MEX-style MIP solution */ -static void COPTMEX_initMMipSol(coptmex_mmipsol *mmipsol) { - mmipsol->status = NULL; - mmipsol->simplexiter = NULL; - mmipsol->nodecnt = NULL; - mmipsol->bestgap = NULL; - mmipsol->solvingtime = NULL; - mmipsol->objval = NULL; - mmipsol->bestbnd = NULL; - mmipsol->value = NULL; - - mmipsol->solpool = NULL; - return; -} - -/* Initialize MEX-style IIS information */ -static void COPTMEX_initMIISInfo(coptmex_miisinfo *miisinfo) { - miisinfo->isminiis = NULL; - miisinfo->varlb = NULL; - miisinfo->varub = NULL; - miisinfo->constrlb = NULL; - miisinfo->construb = NULL; - miisinfo->sos = NULL; - miisinfo->indicator = NULL; - return; -} - -/* Initialize MEX-style feasibility relaxation information */ -static void COPTMEX_initMRelaxInfo(coptmex_mrelaxinfo *mrelaxinfo) { - mrelaxinfo->relaxobj = NULL; - mrelaxinfo->relaxvalue = NULL; - mrelaxinfo->relaxlb = NULL; - mrelaxinfo->relaxub = NULL; - mrelaxinfo->relaxlhs = NULL; - mrelaxinfo->relaxrhs = NULL; - return; -} - -/* Check parts of penalty */ -static int COPTMEX_checkPenalty(copt_prob *prob, const mxArray *penalty) { - int isvalid = 1; - char msgbuf[COPT_BUFFSIZE]; - - mxArray *lbpen = NULL; - mxArray *ubpen = NULL; - mxArray *rhspen = NULL; - mxArray *upppen = NULL; - - int nCol = 0, nRow = 0; - - COPT_GetIntAttr(prob, COPT_INTATTR_COLS, &nCol); - COPT_GetIntAttr(prob, COPT_INTATTR_ROWS, &nRow); - - lbpen = mxGetField(penalty, 0, COPTMEX_PENALTY_LBPEN); - ubpen = mxGetField(penalty, 0, COPTMEX_PENALTY_UBPEN); - rhspen = mxGetField(penalty, 0, COPTMEX_PENALTY_RHSPEN); - upppen = mxGetField(penalty, 0, COPTMEX_PENALTY_UPPPEN); - - if (lbpen != NULL) { - if (!mxIsDouble(lbpen)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "penalty.%s", COPTMEX_PENALTY_LBPEN); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - if (mxGetNumberOfElements(lbpen) != nCol) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "penalty.%s", COPTMEX_PENALTY_LBPEN); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - } - - if (ubpen != NULL) { - if (!mxIsDouble(ubpen)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "penalty.%s", COPTMEX_PENALTY_UBPEN); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - if (mxGetNumberOfElements(ubpen) != nCol) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "penalty.%s", COPTMEX_PENALTY_UBPEN); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - } - - if (rhspen != NULL) { - if (!mxIsDouble(rhspen)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "penalty.%s", COPTMEX_PENALTY_RHSPEN); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - if (mxGetNumberOfElements(rhspen) != nRow) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "penalty.%s", COPTMEX_PENALTY_RHSPEN); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - } - - if (upppen != NULL) { - if (!mxIsDouble(upppen)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "penalty.%s", COPTMEX_PENALTY_UPPPEN); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - if (mxGetNumberOfElements(upppen) != nRow) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "penalty.%s", COPTMEX_PENALTY_UPPPEN); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - } - -exit_cleanup: - return isvalid; -} - -/* Check all parts of a cone problem */ -static int COPTMEX_checkConeModel(mxArray *conedata) { - int nrow = 0, ncol = 0; - int isvalid = 1; - char msgbuf[COPT_BUFFSIZE]; - - // 'conedata' - if (conedata != NULL) { - if (!mxIsStruct(conedata)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_CONEDATA); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - - // 'A' - mxArray *A = mxGetField(conedata, 0, COPTMEX_MODEL_CONE_A); - if (A == NULL) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.conedata.%s", COPTMEX_MODEL_CONE_A); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); - goto exit_cleanup; - } else { - if (!mxIsSparse(A)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.conedata.%s", COPTMEX_MODEL_CONE_A); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } else { - nrow = (int) mxGetM(A); - ncol = (int) mxGetN(A); - } - } - - // 'K' - mxArray *K = mxGetField(conedata, 0, COPTMEX_MODEL_CONE_K); - if (K == NULL) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.conedata.%s", COPTMEX_MODEL_CONE_K); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); - goto exit_cleanup; - } else { - if (!mxIsStruct(K)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.conedata.%s", COPTMEX_MODEL_CONE_K); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - } - - // 'f' - mxArray *f = mxGetField(conedata, 0, COPTMEX_MODEL_CONEK_F); - if (f != NULL) { - if (!mxIsScalar(f) || mxIsChar(f)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.conedata.%s", COPTMEX_MODEL_CONEK_F); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - } - - // 'l' - mxArray *l = mxGetField(conedata, 0, COPTMEX_MODEL_CONEK_L); - if (l != NULL) { - if (!mxIsScalar(l) || mxIsChar(l)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.conedata.%s", COPTMEX_MODEL_CONEK_L); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - } - - // 'q' - mxArray *q = mxGetField(conedata, 0, COPTMEX_MODEL_CONEK_Q); - if (q != NULL) { - if (!mxIsDouble(q)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.conedata.%s", COPTMEX_MODEL_CONEK_Q); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - } - - // 'r' - mxArray *r = mxGetField(conedata, 0, COPTMEX_MODEL_CONEK_R); - if (r != NULL) { - if (!mxIsDouble(r)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.conedata.%s", COPTMEX_MODEL_CONEK_R); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - } - - // 's' - mxArray *s = mxGetField(conedata, 0, COPTMEX_MODEL_CONEK_S); - if (s != NULL) { - if (!mxIsDouble(s)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.conedata.%s", COPTMEX_MODEL_CONEK_S); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - } - - // 'c' - mxArray *c = mxGetField(conedata, 0, COPTMEX_MODEL_CONE_C); - if (c != NULL) { - if (!mxIsDouble(c)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.conedata.%s", COPTMEX_MODEL_CONE_C); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } else { - if (mxGetNumberOfElements(c) != ncol) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.conedata.%s", COPTMEX_MODEL_CONE_C); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - } - } - - // 'b' - mxArray *b = mxGetField(conedata, 0, COPTMEX_MODEL_CONE_B); - if (b != NULL) { - if (!mxIsDouble(b)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.conedata.%s", COPTMEX_MODEL_CONE_B); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } else { - if (mxGetNumberOfElements(b) != nrow) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.conedata.%s", COPTMEX_MODEL_CONE_B); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - } - } - - // 'objsen' - mxArray *objsen = mxGetField(conedata, 0, COPTMEX_MODEL_CONE_OBJSEN); - if (objsen != NULL) { - if (!mxIsChar(objsen)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_CONE_OBJSEN); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - } - - // 'objcon' - mxArray *objcon = mxGetField(conedata, 0, COPTMEX_MODEL_CONE_OBJCON); - if (objcon != NULL) { - if (!mxIsScalar(objcon) || mxIsChar(objcon)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_CONE_OBJCON); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - } - } - -exit_cleanup: - return isvalid; -} - -/* Check all parts of a problem */ -static int COPTMEX_checkModel(coptmex_mprob *mprob) { - int nrow = 0, ncol = 0; - int isvalid = 1; - char msgbuf[COPT_BUFFSIZE]; - - // 'objsen' - if (mprob->objsen != NULL) { - if (!mxIsChar(mprob->objsen)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_OBJSEN); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - } - // 'objcon' - if (mprob->objcon != NULL) { - if (!mxIsScalar(mprob->objcon) || mxIsChar(mprob->objcon)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_OBJCON); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - } - // 'A' - if (mprob->A == NULL) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_A); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); - goto exit_cleanup; - } else { - if (!mxIsSparse(mprob->A)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_A); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } else { - nrow = (int) mxGetM(mprob->A); - ncol = (int) mxGetN(mprob->A); - } - } - // 'obj' - if (mprob->obj != NULL) { - if (!mxIsDouble(mprob->obj)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_OBJ); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - if (mxGetNumberOfElements(mprob->obj) != ncol) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_OBJ); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - } - // 'lb' - if (mprob->lb != NULL) { - if (!mxIsDouble(mprob->lb)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_LB); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - if (mxGetNumberOfElements(mprob->lb) != ncol) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_LB); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - } - // 'ub' - if (mprob->ub != NULL) { - if (!mxIsDouble(mprob->ub)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_UB); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - if (mxGetNumberOfElements(mprob->ub) != ncol) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_UB); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - } - // 'vtype' - if (mprob->vtype != NULL) { - if (!mxIsChar(mprob->vtype)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_VTYPE); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - if (mxGetNumberOfElements(mprob->vtype) != ncol && - mxGetNumberOfElements(mprob->vtype) != 1) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_VTYPE); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - } - // 'sense' - if (mprob->sense == NULL) { - // 'lhs' - if (!mxIsDouble(mprob->lhs)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_LHS); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - if (mxGetNumberOfElements(mprob->lhs) != nrow) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_LHS); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - - // 'rhs' - if (!mxIsDouble(mprob->rhs)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_RHS); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - if (mxGetNumberOfElements(mprob->rhs) != nrow) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_RHS); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - } else { - // 'sense' - if (!mxIsChar(mprob->sense)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_SENSE); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - if (mxGetNumberOfElements(mprob->sense) != nrow && - mxGetNumberOfElements(mprob->sense) != 1) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_SENSE); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - - // 'rhs' - if (!mxIsDouble(mprob->rhs)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_RHS); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - if (mxGetNumberOfElements(mprob->rhs) != nrow) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_RHS); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - } - // 'varnames' - if (mprob->varnames != NULL) { - if (!mxIsCell(mprob->varnames)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_VARNAME); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - if (mxGetNumberOfElements(mprob->varnames) != ncol) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_VARNAME); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - - for (int i = 0; i < mxGetNumberOfElements(mprob->varnames); ++i) { - if (!mxIsChar(mxGetCell(mprob->varnames, i))) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s{%d}", COPTMEX_MODEL_VARNAME, i); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); - goto exit_cleanup; - } - } - } - // 'constrnames' - if (mprob->constrnames != NULL) { - if (!mxIsCell(mprob->constrnames)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_CONNAME); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - if (mxGetNumberOfElements(mprob->constrnames) != nrow) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_CONNAME); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - - for (int i = 0; i < mxGetNumberOfElements(mprob->constrnames); ++i) { - if (!mxIsChar(mxGetCell(mprob->constrnames, i))) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s{%d}", COPTMEX_MODEL_CONNAME, i); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); - goto exit_cleanup; - } - } - } - - // 'sos' - if (mprob->sos != NULL) { - if (!mxIsStruct(mprob->sos)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_SOS); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - - for (int i = 0; i < mxGetNumberOfElements(mprob->sos); ++i) { - mxArray *sostype = mxGetField(mprob->sos, i, COPTMEX_MODEL_SOSTYPE); - mxArray *sosvars = mxGetField(mprob->sos, i, COPTMEX_MODEL_SOSVARS); - mxArray *soswght = mxGetField(mprob->sos, i, COPTMEX_MODEL_SOSWEIGHT); - - if (sostype == NULL) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_SOS, - i, COPTMEX_MODEL_SOSTYPE); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); - goto exit_cleanup; - } else { - if (!mxIsScalar(sostype) || mxIsChar(sostype)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_SOS, - i, COPTMEX_MODEL_SOSTYPE); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - } - - if (sosvars == NULL) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_SOS, - i, COPTMEX_MODEL_SOSVARS); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); - goto exit_cleanup; - } else { - if (!mxIsDouble(sosvars) || mxIsScalar(sosvars) || mxIsSparse(sosvars)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_SOS, - i, COPTMEX_MODEL_SOSVARS); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - } - - if (soswght != NULL) { - if (!mxIsDouble(soswght) || mxIsScalar(soswght) || mxIsSparse(soswght)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_SOS, - i, COPTMEX_MODEL_SOSWEIGHT); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - - if (mxGetNumberOfElements(sosvars) != mxGetNumberOfElements(soswght)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s and problem.%s(%d).%s", - COPTMEX_MODEL_SOS, i, COPTMEX_MODEL_SOSVARS, - COPTMEX_MODEL_SOS, i, COPTMEX_MODEL_SOSWEIGHT); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - } - } - } - - // 'indicator' - if (mprob->indicator != NULL) { - if (!mxIsStruct(mprob->indicator)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_INDICATOR); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - - for (int i = 0; i < mxGetNumberOfElements(mprob->indicator); ++i) { - mxArray *binvar = mxGetField(mprob->indicator, i, COPTMEX_MODEL_INDICBINVAR); - mxArray *binval = mxGetField(mprob->indicator, i, COPTMEX_MODEL_INDICBINVAL); - mxArray *indicA = mxGetField(mprob->indicator, i, COPTMEX_MODEL_INDICROW); - mxArray *rSense = mxGetField(mprob->indicator, i, COPTMEX_MODEL_INDICSENSE); - mxArray *rowBnd = mxGetField(mprob->indicator, i, COPTMEX_MODEL_INDICRHS); - - if (binvar == NULL) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_INDICATOR, - i, COPTMEX_MODEL_INDICBINVAR); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); - goto exit_cleanup; - } else { - if (!mxIsScalar(binvar) || mxIsChar(binvar)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_INDICATOR, - i, COPTMEX_MODEL_INDICBINVAR); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - } - - if (binval == NULL) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_INDICATOR, - i, COPTMEX_MODEL_INDICBINVAL); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); - goto exit_cleanup; - } else { - if (!mxIsScalar(binval) || mxIsChar(binval)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_INDICATOR, - i, COPTMEX_MODEL_INDICBINVAL); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - } - - if (indicA == NULL) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_INDICATOR, - i, COPTMEX_MODEL_INDICROW); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); - goto exit_cleanup; - } else { - if (!mxIsDouble(indicA)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_INDICATOR, - i, COPTMEX_MODEL_INDICROW); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - if (!mxIsSparse(indicA)) { - if (mxGetNumberOfElements(indicA) != ncol) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_INDICATOR, - i, COPTMEX_MODEL_INDICROW); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - } else { - if (mxGetN(indicA) != 1) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_INDICATOR, - i, COPTMEX_MODEL_INDICROW); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); - goto exit_cleanup; - } - } - } - - if (rSense == NULL) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_INDICATOR, - i, COPTMEX_MODEL_INDICSENSE); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); - goto exit_cleanup; - } else { - if (!mxIsChar(rSense) || !mxIsScalar(rSense)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_INDICATOR, - i, COPTMEX_MODEL_INDICSENSE); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - } - - if (rowBnd == NULL) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_INDICATOR, - i, COPTMEX_MODEL_INDICRHS); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); - goto exit_cleanup; - } else { - if (!mxIsScalar(rowBnd) || mxIsChar(rowBnd)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_INDICATOR, - i, COPTMEX_MODEL_INDICRHS); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - } - } - } - - // 'cone' - if (mprob->cone != NULL) { - if (!mxIsStruct(mprob->cone)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_CONE); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - - for (int i = 0; i < mxGetNumberOfElements(mprob->cone); ++i) { - mxArray *conetype = mxGetField(mprob->cone, i, COPTMEX_MODEL_CONETYPE); - mxArray *conevars = mxGetField(mprob->cone, i, COPTMEX_MODEL_CONEVARS); - - if (conetype == NULL) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_CONE, - i, COPTMEX_MODEL_CONETYPE); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); - goto exit_cleanup; - } else { - if (!mxIsScalar(conetype) || mxIsChar(conetype)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_CONE, - i, COPTMEX_MODEL_CONETYPE); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - } - - if (conevars == NULL) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_CONE, - i, COPTMEX_MODEL_CONEVARS); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); - goto exit_cleanup; - } else { - if (!mxIsDouble(conevars) || mxIsScalar(conevars) || mxIsSparse(conevars)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_CONE, - i, COPTMEX_MODEL_CONEVARS); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - } - } - } - - // 'Q' - if (mprob->qobj != NULL) { - if (!mxIsSparse(mprob->qobj)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_QUADOBJ); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); - goto exit_cleanup; - } - if (mxGetM(mprob->qobj) != ncol || mxGetN(mprob->qobj) != ncol) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_QUADOBJ); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - } - - // 'quadcon' - if (mprob->quadcon != NULL) { - if (!mxIsStruct(mprob->quadcon)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_QUADCON); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - - for (int i = 0; i < mxGetNumberOfElements(mprob->quadcon); ++i) { - mxArray *QcMat = mxGetField(mprob->quadcon, i, COPTMEX_MODEL_QCSPMAT); - mxArray *QcRow = mxGetField(mprob->quadcon, i, COPTMEX_MODEL_QCROW); - mxArray *QcCol = mxGetField(mprob->quadcon, i, COPTMEX_MODEL_QCCOL); - mxArray *QcVal = mxGetField(mprob->quadcon, i, COPTMEX_MODEL_QCVAL); - mxArray *QcLinear = mxGetField(mprob->quadcon, i, COPTMEX_MODEL_QCLINEAR); - mxArray *QcSense = mxGetField(mprob->quadcon, i, COPTMEX_MODEL_QCSENSE); - mxArray *QcRhs = mxGetField(mprob->quadcon, i, COPTMEX_MODEL_QCRHS); - mxArray *QcName = mxGetField(mprob->quadcon, i, COPTMEX_MODEL_QCNAME); - - if (QcMat != NULL) { - if (!mxIsSparse(QcMat)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, - i, COPTMEX_MODEL_QCSPMAT); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); - goto exit_cleanup; - } - if (mxGetM(QcMat) != mxGetN(QcMat)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, - i, COPTMEX_MODEL_QCSPMAT); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - } else { - if (QcRow != NULL && QcCol != NULL && QcVal != NULL) { - if (!mxIsDouble(QcRow)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, - i, COPTMEX_MODEL_QCROW); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - if (!mxIsDouble(QcCol)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, - i, COPTMEX_MODEL_QCCOL); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - if (!mxIsDouble(QcVal)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, - i, COPTMEX_MODEL_QCVAL); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - if (mxGetNumberOfElements(QcRow) != mxGetNumberOfElements(QcCol)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, - i, COPTMEX_MODEL_QCROW); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, - i, COPTMEX_MODEL_QCCOL); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - if (mxGetNumberOfElements(QcRow) != mxGetNumberOfElements(QcVal)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, - i, COPTMEX_MODEL_QCVAL); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - } - } - - if (QcLinear != NULL) { - if (!mxIsDouble(QcLinear)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, - i, COPTMEX_MODEL_QCLINEAR); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - if (!mxIsSparse(QcLinear)) { - if (mxGetNumberOfElements(QcLinear) != ncol) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, - i, COPTMEX_MODEL_QCLINEAR); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - } else { - if (mxGetN(QcLinear) != 1) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, - i, COPTMEX_MODEL_QCLINEAR); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - } - } - - if (QcMat == NULL && QcRow == NULL && QcCol == NULL && QcVal == NULL && QcLinear == NULL) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d)", COPTMEX_MODEL_QUADCON, i); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); - goto exit_cleanup; - } - - if (QcSense != NULL) { - if (!mxIsChar(QcSense) || !mxIsScalar(QcSense)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, - i, COPTMEX_MODEL_QCSENSE); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - } - - if (QcRhs == NULL) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, - i, COPTMEX_MODEL_QCRHS); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); - goto exit_cleanup; - } else { - if (mxIsChar(QcRhs) || !mxIsScalar(QcRhs)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, - i, COPTMEX_MODEL_QCRHS); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - } - - if (QcName != NULL) { - if (!mxIsChar(QcName)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, - i, COPTMEX_MODEL_QCNAME); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - } - } - } - - // 'varbasis' - if (mprob->varbasis != NULL) { - if (!mxIsDouble(mprob->varbasis) || mxIsScalar(mprob->varbasis) || - mxIsSparse(mprob->varbasis)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_RESULT_VARBASIS); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - if (mxGetNumberOfElements(mprob->varbasis) != ncol) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_RESULT_VARBASIS); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - } - // 'constrbasis' - if (mprob->constrbasis != NULL) { - if (!mxIsDouble(mprob->constrbasis) || mxIsScalar(mprob->constrbasis) || - mxIsSparse(mprob->constrbasis)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_RESULT_CONBASIS); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - if (mxGetNumberOfElements(mprob->constrbasis) != nrow) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_RESULT_CONBASIS); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - } - // 'x' - if (mprob->value != NULL) { - if (!mxIsDouble(mprob->value) || mxIsScalar(mprob->value) || mxIsSparse(mprob->value)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_RESULT_VALUE); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - if (mxGetNumberOfElements(mprob->value) != ncol) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_RESULT_VALUE); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - } - // 'rc' - if (mprob->redcost != NULL) { - if (!mxIsDouble(mprob->redcost) || mxIsScalar(mprob->redcost) || mxIsSparse(mprob->redcost)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_RESULT_REDCOST); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - if (mxGetNumberOfElements(mprob->redcost) != ncol) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_RESULT_REDCOST); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - } - // 'slack' - if (mprob->slack != NULL) { - if (!mxIsDouble(mprob->slack) || mxIsScalar(mprob->slack) || mxIsSparse(mprob->slack)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_RESULT_SLACK); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - if (mxGetNumberOfElements(mprob->slack) != nrow) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_RESULT_SLACK); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - } - // 'pi' - if (mprob->dual != NULL) { - if (!mxIsDouble(mprob->dual) || mxIsScalar(mprob->dual) || mxIsSparse(mprob->dual)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_RESULT_DUAL); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - if (mxGetNumberOfElements(mprob->dual) != nrow) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_RESULT_DUAL); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - } - // 'start' - if (mprob->mipstart != NULL) { - if (!mxIsDouble(mprob->mipstart)) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_ADVINFO_MIPSTART); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - if (!mxIsSparse(mprob->mipstart)) { - if (mxGetNumberOfElements(mprob->mipstart) != ncol) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_ADVINFO_MIPSTART); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); - goto exit_cleanup; - } - } else { - if (mxGetN(mprob->mipstart) != 1) { - isvalid = 0; - snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_ADVINFO_MIPSTART); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); - goto exit_cleanup; - } - } - } - -exit_cleanup: - return isvalid; -} +#include "coptmex.h" +#include + +/* Initialize MEX-style version */ +static void COPTMEX_initVersion(coptmex_mversion* version) +{ + version->major = NULL; + version->minor = NULL; + version->technical = NULL; + return; +} + +/* Initialize C-style problem */ +static void COPTMEX_initCProb(coptmex_cprob* cprob) +{ + // The main part of problem + cprob->nRow = 0; + cprob->nCol = 0; + cprob->nElem = 0; + cprob->nObjSen = COPT_MINIMIZE; + cprob->dObjConst = 0.0; + + cprob->colMatBeg = NULL; + cprob->colMatIdx = NULL; + cprob->colMatElem = NULL; + + cprob->colCost = NULL; + cprob->colLower = NULL; + cprob->colUpper = NULL; + cprob->rowLower = NULL; + cprob->rowUpper = NULL; + + cprob->colType = NULL; + cprob->rowSense = NULL; + cprob->colNames = NULL; + cprob->rowNames = NULL; + + // The optional SOS part + cprob->nSos = 0; + cprob->nSosSize = 0; + cprob->sosType = NULL; + cprob->sosMatBeg = NULL; + cprob->sosMatCnt = NULL; + cprob->sosMatIdx = NULL; + cprob->sosMatWt = NULL; + + // The optional indicator part + cprob->nIndicator = 0; + + // The optional cone part + cprob->nCone = 0; + cprob->nConeSize = 0; + cprob->coneType = NULL; + cprob->coneBeg = NULL; + cprob->coneCnt = NULL; + cprob->coneIdx = NULL; + + // The optional Q objective part + cprob->nQElem = 0; + + // The optional quadratic constraint part + cprob->nQConstr = 0; + + // The optional advanced information + cprob->hasBasis = 0; + cprob->colBasis = NULL; + cprob->rowBasis = NULL; + return; +} + +/* Initialize MEX-style problem */ +static void COPTMEX_initMProb(coptmex_mprob* mprob) +{ + // The main part of problem + mprob->objsen = NULL; + mprob->objcon = NULL; + mprob->A = NULL; + mprob->obj = NULL; + mprob->lb = NULL; + mprob->ub = NULL; + mprob->vtype = NULL; + mprob->varnames = NULL; + mprob->sense = NULL; + mprob->lhs = NULL; + mprob->rhs = NULL; + mprob->constrnames = NULL; + + // The optional SOS part + mprob->sos = NULL; + + // The optional indicator part + mprob->indicator = NULL; + + // The optional cone part + mprob->cone = NULL; + + // The optional Q objective part + mprob->qobj = NULL; + + // The optional quadratic constraint part + mprob->quadcon = NULL; + + // The optional advanced information + mprob->varbasis = NULL; + mprob->constrbasis = NULL; + + mprob->value = NULL; + mprob->slack = NULL; + mprob->dual = NULL; + mprob->redcost = NULL; + + mprob->mipstart = NULL; + return; +} + +/* Initialize C-style cone problem */ +static void COPTMEX_initCConeProb(coptmex_cconeprob* cconeprob) +{ + cconeprob->nCol = 0; + cconeprob->nRow = 0; + + cconeprob->nObjSense = COPT_MINIMIZE; + cconeprob->dObjConst = 0.0; + + cconeprob->nFree = 0; + cconeprob->nPositive = 0; + cconeprob->nCone = 0; + cconeprob->nRotateCone = 0; + cconeprob->nPSD = 0; + + cconeprob->coneDim = NULL; + cconeprob->rotateConeDim = NULL; + cconeprob->psdDim = NULL; + + cconeprob->colObj = NULL; + + cconeprob->nQObjElem = 0; + cconeprob->qObjRow = NULL; + cconeprob->qObjCol = NULL; + cconeprob->qObjElem = NULL; + + cconeprob->colMatBeg = NULL; + cconeprob->colMatIdx = NULL; + cconeprob->colMatElem = NULL; + + cconeprob->rowRhs = NULL; +} + +/* Initialize MEX-style cone problem */ +static void COPTMEX_initMConeProb(coptmex_mconeprob* mconeprob) +{ + mconeprob->c = NULL; + mconeprob->A = NULL; + mconeprob->b = NULL; + + mconeprob->K = NULL; + mconeprob->f = NULL; + mconeprob->l = NULL; + mconeprob->q = NULL; + mconeprob->r = NULL; + mconeprob->s = NULL; + + mconeprob->objsen = NULL; + mconeprob->objcon = NULL; + mconeprob->Q = NULL; +} + +/* Initialize C-style LP solution */ +static void COPTMEX_initCLpSol(coptmex_clpsol* clpsol) +{ + clpsol->nRow = 0; + clpsol->nCol = 0; + clpsol->nPSD = 0; + clpsol->nPSDLen = 0; + clpsol->nPSDConstr = 0; + clpsol->nQConstr = 0; + clpsol->hasBasis = 0; + clpsol->hasLpSol = 0; + + clpsol->nStatus = COPT_LPSTATUS_UNSTARTED; + clpsol->nSimplexIter = 0; + clpsol->nBarrierIter = 0; + clpsol->dSolvingTime = 0.0; + clpsol->dObjVal = COPT_INFINITY; + + clpsol->colBasis = NULL; + clpsol->rowBasis = NULL; + clpsol->colValue = NULL; + clpsol->colDual = NULL; + clpsol->rowSlack = NULL; + clpsol->rowDual = NULL; + clpsol->primalRay = NULL; + clpsol->dualFarkas = NULL; + + clpsol->qRowSlack = NULL; + + clpsol->psdColValue = NULL; + clpsol->psdColDual = NULL; + clpsol->psdRowSlack = NULL; + clpsol->psdRowDual = NULL; + return; +} + +/* Initialize C-style MIP solution */ +static void COPTMEX_initCMipSol(coptmex_cmipsol* cmipsol) +{ + cmipsol->nRow = 0; + cmipsol->nCol = 0; + cmipsol->hasMipSol = 0; + + cmipsol->nStatus = COPT_MIPSTATUS_UNSTARTED; + cmipsol->nSimplexIter = 0; + cmipsol->nNodeCnt = 0; + cmipsol->dBestGap = COPT_INFINITY; + cmipsol->dSolvingTime = 0.0; + cmipsol->dObjVal = COPT_INFINITY; + cmipsol->dBestBnd = -COPT_INFINITY; + + cmipsol->colValue = NULL; + + cmipsol->nSolPool = 0; + return; +} + +/* Initialize C-style IIS information */ +static void COPTMEX_initCIISInfo(coptmex_ciisinfo* ciisinfo) +{ + ciisinfo->isMinIIS = 0; + ciisinfo->colLowerIIS = NULL; + ciisinfo->colUpperIIS = NULL; + ciisinfo->rowLowerIIS = NULL; + ciisinfo->rowUpperIIS = NULL; + ciisinfo->sosIIS = NULL; + ciisinfo->indicatorIIS = NULL; + return; +} + +/* Initialize C-style feasibility relaxation information */ +static void COPTMEX_initCRelaxInfo(coptmex_crelaxinfo* crelaxinfo) +{ + crelaxinfo->dObjVal = 0.0; + crelaxinfo->colValue = NULL; + crelaxinfo->colLowRlx = NULL; + crelaxinfo->colUppRlx = NULL; + crelaxinfo->rowLowRlx = NULL; + crelaxinfo->rowUppRlx = NULL; + return; +} + +/* Initialize MEX-style LP solution */ +static void COPTMEX_initMLpSol(coptmex_mlpsol* mlpsol) +{ + mlpsol->status = NULL; + mlpsol->simplexiter = NULL; + mlpsol->barrieriter = NULL; + mlpsol->solvingtime = NULL; + mlpsol->objval = NULL; + mlpsol->varbasis = NULL; + mlpsol->constrbasis = NULL; + mlpsol->value = NULL; + mlpsol->redcost = NULL; + mlpsol->slack = NULL; + mlpsol->dual = NULL; + mlpsol->ray = NULL; + mlpsol->farkas = NULL; + mlpsol->qcslack = NULL; + mlpsol->psdcolvalue = NULL; + mlpsol->psdcoldual = NULL; + mlpsol->psdrowslack = NULL; + mlpsol->psdrowdual = NULL; + return; +} + +/* Initialize MEX-style MIP solution */ +static void COPTMEX_initMMipSol(coptmex_mmipsol* mmipsol) +{ + mmipsol->status = NULL; + mmipsol->simplexiter = NULL; + mmipsol->nodecnt = NULL; + mmipsol->bestgap = NULL; + mmipsol->solvingtime = NULL; + mmipsol->objval = NULL; + mmipsol->bestbnd = NULL; + mmipsol->value = NULL; + + mmipsol->solpool = NULL; + return; +} + +/* Initialize MEX-style IIS information */ +static void COPTMEX_initMIISInfo(coptmex_miisinfo* miisinfo) +{ + miisinfo->isminiis = NULL; + miisinfo->varlb = NULL; + miisinfo->varub = NULL; + miisinfo->constrlb = NULL; + miisinfo->construb = NULL; + miisinfo->sos = NULL; + miisinfo->indicator = NULL; + return; +} + +/* Initialize MEX-style feasibility relaxation information */ +static void COPTMEX_initMRelaxInfo(coptmex_mrelaxinfo* mrelaxinfo) +{ + mrelaxinfo->relaxobj = NULL; + mrelaxinfo->relaxvalue = NULL; + mrelaxinfo->relaxlb = NULL; + mrelaxinfo->relaxub = NULL; + mrelaxinfo->relaxlhs = NULL; + mrelaxinfo->relaxrhs = NULL; + return; +} + +/* Check parts of penalty */ +static int COPTMEX_checkPenalty(copt_prob* prob, const mxArray* penalty) +{ + int isvalid = 1; + char msgbuf[COPT_BUFFSIZE]; + + mxArray* lbpen = NULL; + mxArray* ubpen = NULL; + mxArray* rhspen = NULL; + mxArray* upppen = NULL; + + int nCol = 0, nRow = 0; + + COPT_GetIntAttr(prob, COPT_INTATTR_COLS, &nCol); + COPT_GetIntAttr(prob, COPT_INTATTR_ROWS, &nRow); + + lbpen = mxGetField(penalty, 0, COPTMEX_PENALTY_LBPEN); + ubpen = mxGetField(penalty, 0, COPTMEX_PENALTY_UBPEN); + rhspen = mxGetField(penalty, 0, COPTMEX_PENALTY_RHSPEN); + upppen = mxGetField(penalty, 0, COPTMEX_PENALTY_UPPPEN); + + if (lbpen != NULL) + { + if (!mxIsDouble(lbpen)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "penalty.%s", COPTMEX_PENALTY_LBPEN); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + if (mxGetNumberOfElements(lbpen) != nCol) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "penalty.%s", COPTMEX_PENALTY_LBPEN); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + } + + if (ubpen != NULL) + { + if (!mxIsDouble(ubpen)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "penalty.%s", COPTMEX_PENALTY_UBPEN); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + if (mxGetNumberOfElements(ubpen) != nCol) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "penalty.%s", COPTMEX_PENALTY_UBPEN); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + } + + if (rhspen != NULL) + { + if (!mxIsDouble(rhspen)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "penalty.%s", COPTMEX_PENALTY_RHSPEN); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + if (mxGetNumberOfElements(rhspen) != nRow) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "penalty.%s", COPTMEX_PENALTY_RHSPEN); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + } + + if (upppen != NULL) + { + if (!mxIsDouble(upppen)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "penalty.%s", COPTMEX_PENALTY_UPPPEN); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + if (mxGetNumberOfElements(upppen) != nRow) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "penalty.%s", COPTMEX_PENALTY_UPPPEN); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + } + +exit_cleanup: + return isvalid; +} + +/* Check all parts of a cone problem */ +static int COPTMEX_checkConeModel(mxArray* conedata) +{ + int nrow = 0, ncol = 0; + int isvalid = 1; + char msgbuf[COPT_BUFFSIZE]; + + // 'conedata' + if (conedata != NULL) + { + if (!mxIsStruct(conedata)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_CONEDATA); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + + // 'A' + mxArray* A = mxGetField(conedata, 0, COPTMEX_MODEL_CONE_A); + if (A == NULL) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.conedata.%s", COPTMEX_MODEL_CONE_A); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); + goto exit_cleanup; + } + else + { + if (!mxIsSparse(A)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.conedata.%s", COPTMEX_MODEL_CONE_A); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + else + { + nrow = (int)mxGetM(A); + ncol = (int)mxGetN(A); + } + } + + // 'K' + mxArray* K = mxGetField(conedata, 0, COPTMEX_MODEL_CONE_K); + if (K == NULL) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.conedata.%s", COPTMEX_MODEL_CONE_K); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); + goto exit_cleanup; + } + else + { + if (!mxIsStruct(K)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.conedata.%s", COPTMEX_MODEL_CONE_K); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + } + + // 'f' + mxArray* f = mxGetField(conedata, 0, COPTMEX_MODEL_CONEK_F); + if (f != NULL) + { + if (!mxIsScalar(f) || mxIsChar(f)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.conedata.%s", COPTMEX_MODEL_CONEK_F); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + } + + // 'l' + mxArray* l = mxGetField(conedata, 0, COPTMEX_MODEL_CONEK_L); + if (l != NULL) + { + if (!mxIsScalar(l) || mxIsChar(l)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.conedata.%s", COPTMEX_MODEL_CONEK_L); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + } + + // 'q' + mxArray* q = mxGetField(conedata, 0, COPTMEX_MODEL_CONEK_Q); + if (q != NULL) + { + if (!mxIsDouble(q)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.conedata.%s", COPTMEX_MODEL_CONEK_Q); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + } + + // 'r' + mxArray* r = mxGetField(conedata, 0, COPTMEX_MODEL_CONEK_R); + if (r != NULL) + { + if (!mxIsDouble(r)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.conedata.%s", COPTMEX_MODEL_CONEK_R); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + } + + // 's' + mxArray* s = mxGetField(conedata, 0, COPTMEX_MODEL_CONEK_S); + if (s != NULL) + { + if (!mxIsDouble(s)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.conedata.%s", COPTMEX_MODEL_CONEK_S); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + } + + // 'c' + mxArray* c = mxGetField(conedata, 0, COPTMEX_MODEL_CONE_C); + if (c != NULL) + { + if (!mxIsDouble(c)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.conedata.%s", COPTMEX_MODEL_CONE_C); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + else + { + if (mxGetNumberOfElements(c) != ncol) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.conedata.%s", COPTMEX_MODEL_CONE_C); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + } + } + + // 'b' + mxArray* b = mxGetField(conedata, 0, COPTMEX_MODEL_CONE_B); + if (b != NULL) + { + if (!mxIsDouble(b)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.conedata.%s", COPTMEX_MODEL_CONE_B); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + else + { + if (mxGetNumberOfElements(b) != nrow) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.conedata.%s", COPTMEX_MODEL_CONE_B); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + } + } + + // 'objsen' + mxArray* objsen = mxGetField(conedata, 0, COPTMEX_MODEL_CONE_OBJSEN); + if (objsen != NULL) + { + if (!mxIsChar(objsen)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_CONE_OBJSEN); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + } + + // 'objcon' + mxArray* objcon = mxGetField(conedata, 0, COPTMEX_MODEL_CONE_OBJCON); + if (objcon != NULL) + { + if (!mxIsScalar(objcon) || mxIsChar(objcon)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_CONE_OBJCON); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + } + } + +exit_cleanup: + return isvalid; +} + +/* Check all parts of a problem */ +static int COPTMEX_checkModel(coptmex_mprob* mprob) +{ + int nrow = 0, ncol = 0; + int isvalid = 1; + char msgbuf[COPT_BUFFSIZE]; + + // 'objsen' + if (mprob->objsen != NULL) + { + if (!mxIsChar(mprob->objsen)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_OBJSEN); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + } + // 'objcon' + if (mprob->objcon != NULL) + { + if (!mxIsScalar(mprob->objcon) || mxIsChar(mprob->objcon)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_OBJCON); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + } + // 'A' + if (mprob->A == NULL) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_A); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); + goto exit_cleanup; + } + else + { + if (!mxIsSparse(mprob->A)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_A); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + else + { + nrow = (int)mxGetM(mprob->A); + ncol = (int)mxGetN(mprob->A); + } + } + // 'obj' + if (mprob->obj != NULL) + { + if (!mxIsDouble(mprob->obj)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_OBJ); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + if (mxGetNumberOfElements(mprob->obj) != ncol) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_OBJ); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + } + // 'lb' + if (mprob->lb != NULL) + { + if (!mxIsDouble(mprob->lb)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_LB); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + if (mxGetNumberOfElements(mprob->lb) != ncol) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_LB); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + } + // 'ub' + if (mprob->ub != NULL) + { + if (!mxIsDouble(mprob->ub)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_UB); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + if (mxGetNumberOfElements(mprob->ub) != ncol) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_UB); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + } + // 'vtype' + if (mprob->vtype != NULL) + { + if (!mxIsChar(mprob->vtype)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_VTYPE); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + if (mxGetNumberOfElements(mprob->vtype) != ncol && mxGetNumberOfElements(mprob->vtype) != 1) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_VTYPE); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + } + // 'sense' + if (mprob->sense == NULL) + { + // 'lhs' + if (!mxIsDouble(mprob->lhs)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_LHS); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + if (mxGetNumberOfElements(mprob->lhs) != nrow) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_LHS); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + + // 'rhs' + if (!mxIsDouble(mprob->rhs)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_RHS); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + if (mxGetNumberOfElements(mprob->rhs) != nrow) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_RHS); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + } + else + { + // 'sense' + if (!mxIsChar(mprob->sense)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_SENSE); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + if (mxGetNumberOfElements(mprob->sense) != nrow && mxGetNumberOfElements(mprob->sense) != 1) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_SENSE); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + + // 'rhs' + if (!mxIsDouble(mprob->rhs)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_RHS); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + if (mxGetNumberOfElements(mprob->rhs) != nrow) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_RHS); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + } + // 'varnames' + if (mprob->varnames != NULL) + { + if (!mxIsCell(mprob->varnames)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_VARNAME); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + if (mxGetNumberOfElements(mprob->varnames) != ncol) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_VARNAME); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + + for (int i = 0; i < mxGetNumberOfElements(mprob->varnames); ++i) + { + if (!mxIsChar(mxGetCell(mprob->varnames, i))) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s{%d}", COPTMEX_MODEL_VARNAME, i); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); + goto exit_cleanup; + } + } + } + // 'constrnames' + if (mprob->constrnames != NULL) + { + if (!mxIsCell(mprob->constrnames)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_CONNAME); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + if (mxGetNumberOfElements(mprob->constrnames) != nrow) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_CONNAME); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + + for (int i = 0; i < mxGetNumberOfElements(mprob->constrnames); ++i) + { + if (!mxIsChar(mxGetCell(mprob->constrnames, i))) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s{%d}", COPTMEX_MODEL_CONNAME, i); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); + goto exit_cleanup; + } + } + } + + // 'sos' + if (mprob->sos != NULL) + { + if (!mxIsStruct(mprob->sos)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_SOS); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + + for (int i = 0; i < mxGetNumberOfElements(mprob->sos); ++i) + { + mxArray* sostype = mxGetField(mprob->sos, i, COPTMEX_MODEL_SOSTYPE); + mxArray* sosvars = mxGetField(mprob->sos, i, COPTMEX_MODEL_SOSVARS); + mxArray* soswght = mxGetField(mprob->sos, i, COPTMEX_MODEL_SOSWEIGHT); + + if (sostype == NULL) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_SOS, i, COPTMEX_MODEL_SOSTYPE); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); + goto exit_cleanup; + } + else + { + if (!mxIsScalar(sostype) || mxIsChar(sostype)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_SOS, i, COPTMEX_MODEL_SOSTYPE); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + } + + if (sosvars == NULL) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_SOS, i, COPTMEX_MODEL_SOSVARS); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); + goto exit_cleanup; + } + else + { + if (!mxIsDouble(sosvars) || mxIsScalar(sosvars) || mxIsSparse(sosvars)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_SOS, i, COPTMEX_MODEL_SOSVARS); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + } + + if (soswght != NULL) + { + if (!mxIsDouble(soswght) || mxIsScalar(soswght) || mxIsSparse(soswght)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_SOS, i, COPTMEX_MODEL_SOSWEIGHT); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + + if (mxGetNumberOfElements(sosvars) != mxGetNumberOfElements(soswght)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s and problem.%s(%d).%s", COPTMEX_MODEL_SOS, i, + COPTMEX_MODEL_SOSVARS, COPTMEX_MODEL_SOS, i, COPTMEX_MODEL_SOSWEIGHT); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + } + } + } + + // 'indicator' + if (mprob->indicator != NULL) + { + if (!mxIsStruct(mprob->indicator)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_INDICATOR); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + + for (int i = 0; i < mxGetNumberOfElements(mprob->indicator); ++i) + { + mxArray* binvar = mxGetField(mprob->indicator, i, COPTMEX_MODEL_INDICBINVAR); + mxArray* binval = mxGetField(mprob->indicator, i, COPTMEX_MODEL_INDICBINVAL); + mxArray* indicA = mxGetField(mprob->indicator, i, COPTMEX_MODEL_INDICROW); + mxArray* rSense = mxGetField(mprob->indicator, i, COPTMEX_MODEL_INDICSENSE); + mxArray* rowBnd = mxGetField(mprob->indicator, i, COPTMEX_MODEL_INDICRHS); + + if (binvar == NULL) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_INDICATOR, i, COPTMEX_MODEL_INDICBINVAR); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); + goto exit_cleanup; + } + else + { + if (!mxIsScalar(binvar) || mxIsChar(binvar)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_INDICATOR, i, COPTMEX_MODEL_INDICBINVAR); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + } + + if (binval == NULL) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_INDICATOR, i, COPTMEX_MODEL_INDICBINVAL); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); + goto exit_cleanup; + } + else + { + if (!mxIsScalar(binval) || mxIsChar(binval)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_INDICATOR, i, COPTMEX_MODEL_INDICBINVAL); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + } + + if (indicA == NULL) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_INDICATOR, i, COPTMEX_MODEL_INDICROW); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); + goto exit_cleanup; + } + else + { + if (!mxIsDouble(indicA)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_INDICATOR, i, COPTMEX_MODEL_INDICROW); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + if (!mxIsSparse(indicA)) + { + if (mxGetNumberOfElements(indicA) != ncol) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_INDICATOR, i, COPTMEX_MODEL_INDICROW); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + } + else + { + if (mxGetN(indicA) != 1) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_INDICATOR, i, COPTMEX_MODEL_INDICROW); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); + goto exit_cleanup; + } + } + } + + if (rSense == NULL) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_INDICATOR, i, COPTMEX_MODEL_INDICSENSE); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); + goto exit_cleanup; + } + else + { + if (!mxIsChar(rSense) || !mxIsScalar(rSense)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_INDICATOR, i, COPTMEX_MODEL_INDICSENSE); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + } + + if (rowBnd == NULL) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_INDICATOR, i, COPTMEX_MODEL_INDICRHS); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); + goto exit_cleanup; + } + else + { + if (!mxIsScalar(rowBnd) || mxIsChar(rowBnd)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_INDICATOR, i, COPTMEX_MODEL_INDICRHS); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + } + } + } + + // 'cone' + if (mprob->cone != NULL) + { + if (!mxIsStruct(mprob->cone)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_CONE); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + + for (int i = 0; i < mxGetNumberOfElements(mprob->cone); ++i) + { + mxArray* conetype = mxGetField(mprob->cone, i, COPTMEX_MODEL_CONETYPE); + mxArray* conevars = mxGetField(mprob->cone, i, COPTMEX_MODEL_CONEVARS); + + if (conetype == NULL) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_CONE, i, COPTMEX_MODEL_CONETYPE); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); + goto exit_cleanup; + } + else + { + if (!mxIsScalar(conetype) || mxIsChar(conetype)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_CONE, i, COPTMEX_MODEL_CONETYPE); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + } + + if (conevars == NULL) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_CONE, i, COPTMEX_MODEL_CONEVARS); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); + goto exit_cleanup; + } + else + { + if (!mxIsDouble(conevars) || mxIsScalar(conevars) || mxIsSparse(conevars)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_CONE, i, COPTMEX_MODEL_CONEVARS); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + } + } + } + + // 'Q' + if (mprob->qobj != NULL) + { + if (!mxIsSparse(mprob->qobj)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_QUADOBJ); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); + goto exit_cleanup; + } + if (mxGetM(mprob->qobj) != ncol || mxGetN(mprob->qobj) != ncol) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_QUADOBJ); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + } + + // 'quadcon' + if (mprob->quadcon != NULL) + { + if (!mxIsStruct(mprob->quadcon)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_MODEL_QUADCON); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + + for (int i = 0; i < mxGetNumberOfElements(mprob->quadcon); ++i) + { + mxArray* QcMat = mxGetField(mprob->quadcon, i, COPTMEX_MODEL_QCSPMAT); + mxArray* QcRow = mxGetField(mprob->quadcon, i, COPTMEX_MODEL_QCROW); + mxArray* QcCol = mxGetField(mprob->quadcon, i, COPTMEX_MODEL_QCCOL); + mxArray* QcVal = mxGetField(mprob->quadcon, i, COPTMEX_MODEL_QCVAL); + mxArray* QcLinear = mxGetField(mprob->quadcon, i, COPTMEX_MODEL_QCLINEAR); + mxArray* QcSense = mxGetField(mprob->quadcon, i, COPTMEX_MODEL_QCSENSE); + mxArray* QcRhs = mxGetField(mprob->quadcon, i, COPTMEX_MODEL_QCRHS); + mxArray* QcName = mxGetField(mprob->quadcon, i, COPTMEX_MODEL_QCNAME); + + if (QcMat != NULL) + { + if (!mxIsSparse(QcMat)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, i, COPTMEX_MODEL_QCSPMAT); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); + goto exit_cleanup; + } + if (mxGetM(QcMat) != mxGetN(QcMat)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, i, COPTMEX_MODEL_QCSPMAT); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + } + else + { + if (QcRow != NULL && QcCol != NULL && QcVal != NULL) + { + if (!mxIsDouble(QcRow)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, i, COPTMEX_MODEL_QCROW); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + if (!mxIsDouble(QcCol)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, i, COPTMEX_MODEL_QCCOL); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + if (!mxIsDouble(QcVal)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, i, COPTMEX_MODEL_QCVAL); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + if (mxGetNumberOfElements(QcRow) != mxGetNumberOfElements(QcCol)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, i, COPTMEX_MODEL_QCROW); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, i, COPTMEX_MODEL_QCCOL); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + if (mxGetNumberOfElements(QcRow) != mxGetNumberOfElements(QcVal)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, i, COPTMEX_MODEL_QCVAL); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + } + } + + if (QcLinear != NULL) + { + if (!mxIsDouble(QcLinear)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, i, COPTMEX_MODEL_QCLINEAR); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + if (!mxIsSparse(QcLinear)) + { + if (mxGetNumberOfElements(QcLinear) != ncol) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, i, COPTMEX_MODEL_QCLINEAR); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + } + else + { + if (mxGetN(QcLinear) != 1) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, i, COPTMEX_MODEL_QCLINEAR); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + } + } + + if (QcMat == NULL && QcRow == NULL && QcCol == NULL && QcVal == NULL && QcLinear == NULL) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d)", COPTMEX_MODEL_QUADCON, i); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); + goto exit_cleanup; + } + + if (QcSense != NULL) + { + if (!mxIsChar(QcSense) || !mxIsScalar(QcSense)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, i, COPTMEX_MODEL_QCSENSE); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + } + + if (QcRhs == NULL) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, i, COPTMEX_MODEL_QCRHS); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); + goto exit_cleanup; + } + else + { + if (mxIsChar(QcRhs) || !mxIsScalar(QcRhs)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, i, COPTMEX_MODEL_QCRHS); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + } + + if (QcName != NULL) + { + if (!mxIsChar(QcName)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s(%d).%s", COPTMEX_MODEL_QUADCON, i, COPTMEX_MODEL_QCNAME); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + } + } + } + + // 'varbasis' + if (mprob->varbasis != NULL) + { + if (!mxIsDouble(mprob->varbasis) || mxIsScalar(mprob->varbasis) || mxIsSparse(mprob->varbasis)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_RESULT_VARBASIS); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + if (mxGetNumberOfElements(mprob->varbasis) != ncol) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_RESULT_VARBASIS); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + } + // 'constrbasis' + if (mprob->constrbasis != NULL) + { + if (!mxIsDouble(mprob->constrbasis) || mxIsScalar(mprob->constrbasis) || mxIsSparse(mprob->constrbasis)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_RESULT_CONBASIS); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + if (mxGetNumberOfElements(mprob->constrbasis) != nrow) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_RESULT_CONBASIS); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + } + // 'x' + if (mprob->value != NULL) + { + if (!mxIsDouble(mprob->value) || mxIsScalar(mprob->value) || mxIsSparse(mprob->value)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_RESULT_VALUE); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + if (mxGetNumberOfElements(mprob->value) != ncol) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_RESULT_VALUE); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + } + // 'rc' + if (mprob->redcost != NULL) + { + if (!mxIsDouble(mprob->redcost) || mxIsScalar(mprob->redcost) || mxIsSparse(mprob->redcost)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_RESULT_REDCOST); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + if (mxGetNumberOfElements(mprob->redcost) != ncol) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_RESULT_REDCOST); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + } + // 'slack' + if (mprob->slack != NULL) + { + if (!mxIsDouble(mprob->slack) || mxIsScalar(mprob->slack) || mxIsSparse(mprob->slack)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_RESULT_SLACK); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + if (mxGetNumberOfElements(mprob->slack) != nrow) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_RESULT_SLACK); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + } + // 'pi' + if (mprob->dual != NULL) + { + if (!mxIsDouble(mprob->dual) || mxIsScalar(mprob->dual) || mxIsSparse(mprob->dual)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_RESULT_DUAL); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + if (mxGetNumberOfElements(mprob->dual) != nrow) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_RESULT_DUAL); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + } + // 'start' + if (mprob->mipstart != NULL) + { + if (!mxIsDouble(mprob->mipstart)) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_ADVINFO_MIPSTART); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + if (!mxIsSparse(mprob->mipstart)) + { + if (mxGetNumberOfElements(mprob->mipstart) != ncol) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_ADVINFO_MIPSTART); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NUM, msgbuf); + goto exit_cleanup; + } + } + else + { + if (mxGetN(mprob->mipstart) != 1) + { + isvalid = 0; + snprintf(msgbuf, COPT_BUFFSIZE, "problem.%s", COPTMEX_ADVINFO_MIPSTART); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_DATA, msgbuf); + goto exit_cleanup; + } + } + } + +exit_cleanup: + return isvalid; +} diff --git a/src/coptmex.c b/src/coptmex.c index 93df49c..869f291 100755 --- a/src/coptmex.c +++ b/src/coptmex.c @@ -1,2593 +1,3574 @@ -#include "coptmex.h" - -/* Uncomment the following line for use with legacy MEX APIs */ -// #define COPTMEX_USE_LEGACYMEX -#ifdef COPTMEX_USE_LEGACYMEX -#define mxGetDoubles mxGetPr -#endif - -extern int COPT_SearchParamAttr(copt_prob *prob, const char *name, int *p_type); - -extern int COPT_GetPSDSolution(copt_prob* prob, - double* psdColValue, - double* psdRowSlack, - double* psdRowDual, - double* psdColDual); - -extern int COPT_LoadConeProb(copt_prob* prob, - int nCol, - int nRow, - int nFree, - int nPositive, - int nBox, - int nCone, - int nRotateCone, - int nPrimalExp, - int nDualExp, - int nPrimalPow, - int nDualPow, - int nPSD, - int nQObjElem, - int iObjSense, - double dObjConst, - const double* colObj, - const int* qObjRow, - const int* qObjCol, - const double* qObjElem, - const int* colMatBeg, - const int* colMatCnt, - const int* colMatIdx, - const double* colMatElem, - const double* rowRhs, - const double* boxLower, - const double* boxUpper, - const int* coneDim, - const int* rotateConeDim, - const int* primalPowDim, - const int* dualPowDim, - const double* primalPowAlpha, - const double* dualPowAlpha, - const int* psdDim, - const char* colType, - char const* const* colNames, - char const* const* rowNames, - char const* const* psdColNames, - int* outRowMap); - -/* Convert status code from integer to string */ -static const char *COPTMEX_statusInt2Str(int status) { - switch (status) { - case 0: // unstarted - return COPTMEX_STATUS_UNSTARTED; - case 1: // optimal - return COPTMEX_STATUS_OPTIMAL; - case 2: // infeasible - return COPTMEX_STATUS_INFEASIBLE; - case 3: // unbounded - return COPTMEX_STATUS_UNBOUNDED; - case 4: // inf_or_unb - return COPTMEX_STATUS_INF_OF_UNB; - case 5: // numerical - return COPTMEX_STATUS_NUMERICAL; - case 6: // nodelimit - return COPTMEX_STATUS_NODELIMIT; - case 8: // timeout - return COPTMEX_STATUS_TIMEOUT; - case 9: // unfinished - return COPTMEX_STATUS_UNFINISHED; - case 10: // interrupted - return COPTMEX_STATUS_INTERRUPTED; - default: // unknown - return "unknown"; - } -} - -/* Convert objective sense from string to integer */ -static int COPTMEX_objsenStr2Int(char *objsen) { - if (mystrcmp(objsen, "max") == 0 || mystrcmp(objsen, "maximize") == 0) { - return COPT_MAXIMIZE; - } - return COPT_MINIMIZE; -} - -/* Convert objective sense from integer to string */ -static const char *COPTMEX_objsenInt2Str(int objsen) { - if (objsen == COPT_MAXIMIZE) { - return "max"; - } - return "min"; -} - -/* Extract string from MEX */ -static int COPTMEX_getString(const mxArray *in_array, char **out_str) { - int retcode = 0; - - int bufflen = mxGetNumberOfElements(in_array) + 1; - char *buffer = (char *) mxCalloc(bufflen, sizeof(char)); - if (!buffer) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - mxGetString(in_array, buffer, bufflen); - *out_str = buffer; - -exit_cleanup: - return retcode; -} - -/* Free string allocated by MEX */ -static void COPTMEX_freeString(char **in_str) { - if (in_str != NULL && *in_str != NULL) { - mxFree(*in_str); - } - return; -} - -/* Display error message */ -void COPTMEX_errorMsg(int errcode, const char *errinfo) { - char *errid = NULL; - char *errtxt = NULL; - - switch (errcode) { - case COPTMEX_ERROR_BAD_TYPE: - errid = "coptmex:BadType"; - errtxt = "Invalid type of '%s'."; - break; - case COPTMEX_ERROR_BAD_NAME: - errid = "coptmex:BadName"; - errtxt = "Invalid name of '%s'."; - break; - case COPTMEX_ERROR_BAD_DATA: - errid = "coptmex:BadData"; - errtxt = "Invalid data of '%s'."; - break; - case COPTMEX_ERROR_BAD_NUM: - errid = "coptmex:BadNum"; - errtxt = "Invalid number of elemtents in '%s'."; - break; - case COPTMEX_ERROR_BAD_API: - errid = "coptmex:BadAPI"; - errtxt = "%s."; - break; - default: - return; - } - - mexErrMsgIdAndTxt(errid, errtxt, errinfo); -} - -/* Convert CSC matrix to COO matrix */ -void COPTMEX_csc2coo(mxArray *q, int *qMatRow, int *qMatCol, double *qMatElem) { - int ncol = mxGetN(q); - mwIndex *jc = mxGetJc(q); - mwIndex *ir = mxGetIr(q); - double *val = mxGetDoubles(q); - - for (int i = 0; i < ncol; ++i) { - int nColElem = (int) jc[i]; - int nColLast = (int) jc[i + 1]; - for (; nColElem < nColLast; ++nColElem) { - qMatRow[nColElem] = (int) ir[nColElem]; - qMatCol[nColElem] = i; - qMatElem[nColElem] = val[nColElem]; - } - } - - return; -} - -/* Convert COO matrix to CSC matrix */ -int COPTMEX_coo2csc(int nQElem, int *qMatRow, int *qMatCol, double *qMatElem, mxArray *q) { - int ncol = mxGetN(q); - mwIndex *jc = mxGetJc(q); - mwIndex *ir = mxGetIr(q); - double *val = mxGetDoubles(q); - - int *colMatCnt = (int *) mxCalloc(ncol, sizeof(int)); - if (!colMatCnt) { - return COPT_RETCODE_MEMORY; - } - - for (int i = 0; i < nQElem; ++i) { - colMatCnt[qMatCol[i]]++; - } - - jc[0] = 0; - for (int i = 1; i <= ncol; ++i) { - jc[i] = jc[i - 1] + colMatCnt[i - 1]; - } - - for (int i = 0; i < nQElem; ++i) { - int iCol = qMatCol[i]; - int iElem = (int) jc[iCol]; - - ir[iElem] = qMatRow[i]; - val[iElem] = qMatElem[i]; - - jc[iCol]++; - } - - for (int i = 0, last = 0; i <= ncol; ++i) { - int tmp = jc[i]; - jc[i] = last; - last = tmp; - } - - mxFree(colMatCnt); - return COPT_RETCODE_OK; -} - -#include "coptinit.c" - -/* Display banner */ -int COPTMEX_dispBanner(void) { - int retcode = 0; - char msgbuf[COPT_BUFFSIZE]; - - COPTMEX_CALL(COPT_GetBanner(msgbuf, COPT_BUFFSIZE)); - mexPrintf("%s", msgbuf); - -exit_cleanup: - return retcode; -} - -/* Extract version of COPT */ -int COPTMEX_getVersion(mxArray **out_version) { - int retcode = COPT_RETCODE_OK; - mxArray *retver = NULL; - coptmex_mversion coptver; - - COPTMEX_initVersion(&coptver); - - coptver.major = mxCreateDoubleMatrix(1, 1, mxREAL); - coptver.minor = mxCreateDoubleMatrix(1, 1, mxREAL); - coptver.technical = mxCreateDoubleMatrix(1, 1, mxREAL); - if (!coptver.major || !coptver.minor || !coptver.technical) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - *mxGetDoubles(coptver.major) = COPT_VERSION_MAJOR; - *mxGetDoubles(coptver.minor) = COPT_VERSION_MINOR; - *mxGetDoubles(coptver.technical) = COPT_VERSION_TECHNICAL; - - retver = mxCreateStructMatrix(1, 1, 0, NULL); - if (!retver) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - // 'major' - mxAddField(retver, COPTMEX_VERSION_MAJOR); - mxSetField(retver, 0, COPTMEX_VERSION_MAJOR, coptver.major); - // 'minor' - mxAddField(retver, COPTMEX_VERSION_MINOR); - mxSetField(retver, 0, COPTMEX_VERSION_MINOR, coptver.minor); - // 'technical' - mxAddField(retver, COPTMEX_VERSION_TECHNICAL); - mxSetField(retver, 0, COPTMEX_VERSION_TECHNICAL, coptver.technical); - - *out_version = retver; - -exit_cleanup: - if (retcode != COPT_RETCODE_OK) { - *out_version = NULL; - } - - return retcode; -} - -/* Extract objective sense */ -int COPTMEX_getObjsen(const mxArray *in_objsen, int *out_objsen) { - int retcode = COPT_RETCODE_OK; - char *objsen = NULL; - - COPTMEX_CALL(COPTMEX_getString(in_objsen, &objsen)); - *out_objsen = COPTMEX_objsenStr2Int(objsen); - -exit_cleanup: - COPTMEX_freeString(&objsen); - return retcode; -} - -/* Extract LP solution */ -static int COPTMEX_getLpResult(copt_prob *prob, mxArray **out_lpresult) { - int retcode = COPT_RETCODE_OK; - mxArray *lpResult = NULL; - coptmex_clpsol csol; - coptmex_mlpsol msol; - - COPTMEX_initCLpSol(&csol); - COPTMEX_initMLpSol(&msol); - - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_ROWS, &csol.nRow)); - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_COLS, &csol.nCol)); - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_PSDCOLS, &csol.nPSD)); - COPTMEX_CALL(COPT_GetIntAttr(prob, "PSDLens", &csol.nPSDLen)); - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_PSDCONSTRS, &csol.nPSDConstr)); - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_QCONSTRS, &csol.nQConstr)); - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_LPSTATUS, &csol.nStatus)); - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_HASBASIS, &csol.hasBasis)); - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_HASLPSOL, &csol.hasLpSol)); - - msol.status = mxCreateString(COPTMEX_statusInt2Str(csol.nStatus)); - msol.simplexiter = mxCreateDoubleMatrix(1, 1, mxREAL); - msol.barrieriter = mxCreateDoubleMatrix(1, 1, mxREAL); - msol.solvingtime = mxCreateDoubleMatrix(1, 1, mxREAL); - if (!msol.status || !msol.simplexiter || !msol.barrieriter || !msol.solvingtime) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - if (csol.hasLpSol) { - msol.objval = mxCreateDoubleMatrix(1, 1, mxREAL); - msol.value = mxCreateDoubleMatrix(csol.nCol, 1, mxREAL); - msol.redcost = mxCreateDoubleMatrix(csol.nCol, 1, mxREAL); - msol.slack = mxCreateDoubleMatrix(csol.nRow, 1, mxREAL); - msol.dual = mxCreateDoubleMatrix(csol.nRow, 1, mxREAL); - if (!msol.objval || !msol.value || !msol.redcost || !msol.slack || !msol.dual) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - csol.colValue = mxGetDoubles(msol.value); - csol.colDual = mxGetDoubles(msol.redcost); - csol.rowSlack = mxGetDoubles(msol.slack); - csol.rowDual = mxGetDoubles(msol.dual); - - if (csol.nQConstr > 0) { - msol.qcslack = mxCreateDoubleMatrix(csol.nQConstr, 1, mxREAL); - if (!msol.qcslack) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - csol.qRowSlack = mxGetDoubles(msol.qcslack); - } - - if (csol.nPSD > 0) { - msol.psdcolvalue = mxCreateDoubleMatrix(csol.nPSDLen, 1, mxREAL); - msol.psdcoldual = mxCreateDoubleMatrix(csol.nPSDLen, 1, mxREAL); - if (!msol.psdcolvalue || !msol.psdcoldual) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - csol.psdColValue = mxGetDoubles(msol.psdcolvalue); - csol.psdColDual = mxGetDoubles(msol.psdcoldual); - } - - if (csol.nPSDConstr > 0) { - msol.psdrowslack = mxCreateDoubleMatrix(csol.nPSDConstr, 1, mxREAL); - msol.psdrowdual = mxCreateDoubleMatrix(csol.nPSDConstr, 1, mxREAL); - if (!msol.psdrowslack || !msol.psdrowdual) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - csol.psdRowSlack = mxGetDoubles(msol.psdrowslack); - csol.psdRowDual = mxGetDoubles(msol.psdrowdual); - } - } - - if (csol.nStatus == COPT_LPSTATUS_INFEASIBLE || - csol.nStatus == COPT_LPSTATUS_UNBOUNDED) { - int iReqFarkasRay = 0; - COPTMEX_CALL(COPT_GetIntParam(prob, COPT_INTPARAM_REQFARKASRAY, &iReqFarkasRay)); - - if (iReqFarkasRay) { - if (csol.nStatus == COPT_LPSTATUS_INFEASIBLE) { - msol.farkas = mxCreateDoubleMatrix(csol.nRow, 1, mxREAL); - if (!msol.farkas) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - csol.dualFarkas = mxGetDoubles(msol.farkas); - } - - if (csol.nStatus == COPT_LPSTATUS_UNBOUNDED) { - msol.ray = mxCreateDoubleMatrix(csol.nCol, 1, mxREAL); - if (!msol.ray) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - csol.primalRay = mxGetDoubles(msol.ray); - } - } - } - - if (csol.hasBasis) { - msol.varbasis = mxCreateDoubleMatrix(csol.nCol, 1, mxREAL); - msol.constrbasis = mxCreateDoubleMatrix(csol.nRow, 1, mxREAL); - if (!msol.varbasis || !msol.constrbasis) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - csol.colBasis = (int *) mxCalloc(csol.nCol, sizeof(int)); - csol.rowBasis = (int *) mxCalloc(csol.nRow, sizeof(int)); - if (!csol.colBasis || !csol.rowBasis) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - } - - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_SIMPLEXITER, &csol.nSimplexIter)); - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_BARRIERITER, &csol.nBarrierIter)); - COPTMEX_CALL(COPT_GetDblAttr(prob, COPT_DBLATTR_SOLVINGTIME, &csol.dSolvingTime)); - - if (csol.hasLpSol) { - COPTMEX_CALL(COPT_GetDblAttr(prob, COPT_DBLATTR_LPOBJVAL, &csol.dObjVal)); - COPTMEX_CALL(COPT_GetLpSolution(prob, csol.colValue, csol.rowSlack, - csol.rowDual, csol.colDual)); - - if (csol.nQConstr > 0) { - COPTMEX_CALL(COPT_GetQConstrInfo(prob, COPT_DBLINFO_SLACK, csol.nQConstr, NULL, csol.qRowSlack)); - } - - if (csol.nPSD > 0) { - COPTMEX_CALL(COPT_GetPSDSolution(prob, csol.psdColValue, NULL, NULL, csol.psdColDual)); - } - - if (csol.nPSDConstr > 0) { - COPTMEX_CALL(COPT_GetPSDSolution(prob, NULL, csol.psdRowSlack, csol.psdRowDual, NULL)); - } - } - - if (csol.dualFarkas != NULL) { - COPTMEX_CALL(COPT_GetRowInfo(prob, COPT_DBLINFO_DUALFARKAS, csol.nRow, NULL, csol.dualFarkas)); - } - - if (csol.primalRay != NULL) { - COPTMEX_CALL(COPT_GetColInfo(prob, COPT_DBLINFO_PRIMALRAY, csol.nCol, NULL, csol.primalRay)); - } - - if (csol.hasBasis) { - COPTMEX_CALL(COPT_GetBasis(prob, csol.colBasis, csol.rowBasis)); - } - - *mxGetDoubles(msol.simplexiter) = csol.nSimplexIter; - *mxGetDoubles(msol.barrieriter) = csol.nBarrierIter; - *mxGetDoubles(msol.solvingtime) = csol.dSolvingTime; - - if (csol.hasLpSol) { - *mxGetDoubles(msol.objval) = csol.dObjVal; - } - - if (csol.hasBasis) { - double *colBasis_data = mxGetDoubles(msol.varbasis); - double *rowBasis_data = mxGetDoubles(msol.constrbasis); - for (int i = 0; i < csol.nCol; ++i) { - colBasis_data[i] = csol.colBasis[i]; - } - for (int i = 0; i < csol.nRow; ++i) { - rowBasis_data[i] = csol.rowBasis[i]; - } - - mxFree(csol.colBasis); - mxFree(csol.rowBasis); - } - - lpResult = mxCreateStructMatrix(1, 1, 0, NULL); - if (!lpResult) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - // 'status' - mxAddField(lpResult, COPTMEX_RESULT_STATUS); - mxSetField(lpResult, 0, COPTMEX_RESULT_STATUS, msol.status); - // 'simplexiter' - mxAddField(lpResult, COPTMEX_RESULT_SIMITER); - mxSetField(lpResult, 0, COPTMEX_RESULT_SIMITER, msol.simplexiter); - // 'barrieriter' - mxAddField(lpResult, COPTMEX_RESULT_BARITER); - mxSetField(lpResult, 0, COPTMEX_RESULT_BARITER, msol.barrieriter); - // 'solvingtime' - mxAddField(lpResult, COPTMEX_RESULT_SOLVETIME); - mxSetField(lpResult, 0, COPTMEX_RESULT_SOLVETIME, msol.solvingtime); - - if (csol.hasLpSol) { - // 'objval' - mxAddField(lpResult, COPTMEX_RESULT_OBJVAL); - mxSetField(lpResult, 0, COPTMEX_RESULT_OBJVAL, msol.objval); - // 'x' - mxAddField(lpResult, COPTMEX_RESULT_VALUE); - mxSetField(lpResult, 0, COPTMEX_RESULT_VALUE, msol.value); - // 'rc' - mxAddField(lpResult, COPTMEX_RESULT_REDCOST); - mxSetField(lpResult, 0, COPTMEX_RESULT_REDCOST, msol.redcost); - // 'slack; - mxAddField(lpResult, COPTMEX_RESULT_SLACK); - mxSetField(lpResult, 0, COPTMEX_RESULT_SLACK, msol.slack); - // 'pi' - mxAddField(lpResult, COPTMEX_RESULT_DUAL); - mxSetField(lpResult, 0, COPTMEX_RESULT_DUAL, msol.dual); - - // 'qcslack' - if (csol.nQConstr > 0) { - mxAddField(lpResult, COPTMEX_RESULT_QCSLACK); - mxSetField(lpResult, 0, COPTMEX_RESULT_QCSLACK, msol.qcslack); - } - - if (csol.nPSD > 0) { - // 'psdx' - mxAddField(lpResult, COPTMEX_RESULT_PSDX); - mxSetField(lpResult, 0, COPTMEX_RESULT_PSDX, msol.psdcolvalue); - - // 'psdrc' - mxAddField(lpResult, COPTMEX_RESULT_PSDRC); - mxSetField(lpResult, 0, COPTMEX_RESULT_PSDRC, msol.psdcoldual); - } - - if (csol.nPSDConstr > 0) { - // 'psdslack' - mxAddField(lpResult, COPTMEX_RESULT_PSDSLACK); - mxSetField(lpResult, 0, COPTMEX_RESULT_PSDSLACK, msol.psdrowslack); - - // 'psdpi' - mxAddField(lpResult, COPTMEX_RESULT_PSDPI); - mxSetField(lpResult, 0, COPTMEX_RESULT_PSDPI, msol.psdrowdual); - } - } - - if (msol.farkas != NULL) { - // 'dualfarkas' - mxAddField(lpResult, COPTMEX_RESULT_DUALFARKAS); - mxSetField(lpResult, 0, COPTMEX_RESULT_DUALFARKAS, msol.farkas); - } - - if (msol.ray != NULL) { - // 'primalray' - mxAddField(lpResult, COPTMEX_RESULT_PRIMALRAY); - mxSetField(lpResult, 0, COPTMEX_RESULT_PRIMALRAY, msol.ray); - } - - if (csol.hasBasis) { - // 'varbasis' - mxAddField(lpResult, COPTMEX_RESULT_VARBASIS); - mxSetField(lpResult, 0, COPTMEX_RESULT_VARBASIS, msol.varbasis); - // 'constrbasis' - mxAddField(lpResult, COPTMEX_RESULT_CONBASIS); - mxSetField(lpResult, 0, COPTMEX_RESULT_CONBASIS, msol.constrbasis); - } - - *out_lpresult = lpResult; - -exit_cleanup: - if (retcode != COPT_RETCODE_OK) { - *out_lpresult = NULL; - } - - return retcode; -} - -/* Extract MIP solution */ -static int COPTMEX_getMipResult(copt_prob *prob, mxArray **out_mipresult) { - int retcode = COPT_RETCODE_OK; - mxArray *mipResult = NULL; - coptmex_cmipsol csol; - coptmex_mmipsol msol; - - COPTMEX_initCMipSol(&csol); - COPTMEX_initMMipSol(&msol); - - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_ROWS, &csol.nRow)); - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_COLS, &csol.nCol)); - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_HASMIPSOL, &csol.hasMipSol)); - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_POOLSOLS, &csol.nSolPool)); - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_MIPSTATUS, &csol.nStatus)); - - msol.status = mxCreateString(COPTMEX_statusInt2Str(csol.nStatus)); - msol.simplexiter = mxCreateDoubleMatrix(1, 1, mxREAL); - msol.nodecnt = mxCreateDoubleMatrix(1, 1, mxREAL); - msol.solvingtime = mxCreateDoubleMatrix(1, 1, mxREAL); - if (!msol.status || !msol.simplexiter || !msol.nodecnt || !msol.solvingtime) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - if (csol.hasMipSol) { - msol.bestgap = mxCreateDoubleMatrix(1, 1, mxREAL); - msol.objval = mxCreateDoubleMatrix(1, 1, mxREAL); - msol.bestbnd = mxCreateDoubleMatrix(1, 1, mxREAL); - msol.value = mxCreateDoubleMatrix(csol.nCol, 1, mxREAL); - if (!msol.bestgap || !msol.objval || !msol.bestbnd || !msol.value) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - csol.colValue = mxGetDoubles(msol.value); - } - - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_SIMPLEXITER, &csol.nSimplexIter)); - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_NODECNT, &csol.nNodeCnt)); - COPTMEX_CALL(COPT_GetDblAttr(prob, COPT_DBLATTR_SOLVINGTIME, &csol.dSolvingTime)); - - if (csol.hasMipSol) { - COPTMEX_CALL(COPT_GetDblAttr(prob, COPT_DBLATTR_BESTGAP, &csol.dBestGap)); - COPTMEX_CALL(COPT_GetDblAttr(prob, COPT_DBLATTR_BESTOBJ, &csol.dObjVal)); - COPTMEX_CALL(COPT_GetDblAttr(prob, COPT_DBLATTR_BESTBND, &csol.dBestBnd)); - COPTMEX_CALL(COPT_GetSolution(prob, csol.colValue)); - } - - if (csol.nSolPool > 0) { - const char *solpoolfields[] = {COPTMEX_RESULT_POOLOBJ, - COPTMEX_RESULT_POOLXN}; - msol.solpool = mxCreateStructMatrix(csol.nSolPool, 1, 2, solpoolfields); - if (!msol.solpool) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - for (int i = 0; i < csol.nSolPool; ++i) { - mxArray *poolobjval = mxCreateDoubleMatrix(1, 1, mxREAL); - mxArray *poolxn = mxCreateDoubleMatrix(csol.nCol, 1, mxREAL); - if (!poolobjval || !poolxn) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - double dPoolObjVal = +COPT_INFINITY; - double *dPoolColValue = mxGetDoubles(poolxn); - - COPTMEX_CALL(COPT_GetPoolObjVal(prob, i, &dPoolObjVal)); - COPTMEX_CALL(COPT_GetPoolSolution(prob, i, csol.nCol, NULL, dPoolColValue)); - - *mxGetDoubles(poolobjval) = dPoolObjVal; - - mxSetField(msol.solpool, i, COPTMEX_RESULT_POOLOBJ, poolobjval); - mxSetField(msol.solpool, i, COPTMEX_RESULT_POOLXN, poolxn); - } - } - - *mxGetDoubles(msol.simplexiter) = csol.nSimplexIter; - *mxGetDoubles(msol.nodecnt) = csol.nNodeCnt; - *mxGetDoubles(msol.solvingtime) = csol.dSolvingTime; - - if (csol.hasMipSol) { - *mxGetDoubles(msol.bestgap) = csol.dBestGap; - *mxGetDoubles(msol.objval) = csol.dObjVal; - *mxGetDoubles(msol.bestbnd) = csol.dBestBnd; - } - - mipResult = mxCreateStructMatrix(1, 1, 0, NULL); - if (!mipResult) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - // 'status' - mxAddField(mipResult, COPTMEX_RESULT_STATUS); - mxSetField(mipResult, 0, COPTMEX_RESULT_STATUS, msol.status); - // 'simplexiter' - mxAddField(mipResult, COPTMEX_RESULT_SIMITER); - mxSetField(mipResult, 0, COPTMEX_RESULT_SIMITER, msol.simplexiter); - // 'nodecnt' - mxAddField(mipResult, COPTMEX_RESULT_NODECNT); - mxSetField(mipResult, 0, COPTMEX_RESULT_NODECNT, msol.nodecnt); - // 'solvingtime' - mxAddField(mipResult, COPTMEX_RESULT_SOLVETIME); - mxSetField(mipResult, 0, COPTMEX_RESULT_SOLVETIME, msol.solvingtime); - - if (csol.hasMipSol) { - // 'bestgap' - mxAddField(mipResult, COPTMEX_RESULT_BESTGAP); - mxSetField(mipResult, 0, COPTMEX_RESULT_BESTGAP, msol.bestgap); - // 'objval' - mxAddField(mipResult, COPTMEX_RESULT_OBJVAL); - mxSetField(mipResult, 0, COPTMEX_RESULT_OBJVAL, msol.objval); - // 'bestbnd' - mxAddField(mipResult, COPTMEX_RESULT_BESTBND); - mxSetField(mipResult, 0, COPTMEX_RESULT_BESTBND, msol.bestbnd); - // 'x' - mxAddField(mipResult, COPTMEX_RESULT_VALUE); - mxSetField(mipResult, 0, COPTMEX_RESULT_VALUE, msol.value); - } - - if (csol.nSolPool > 0) { - // 'pool' - mxAddField(mipResult, COPTMEX_RESULT_POOL); - mxSetField(mipResult, 0, COPTMEX_RESULT_POOL, msol.solpool); - } - - *out_mipresult = mipResult; - -exit_cleanup: - if (retcode != COPT_RETCODE_OK) { - *out_mipresult = NULL; - } - - return retcode; -} - -/* Extract and save result */ -int COPTMEX_getResult(copt_prob *prob, mxArray **out_result) { - int retcode = 0; - int isMip = 0; - - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_ISMIP, &isMip)); - if (isMip) { - COPTMEX_CALL(COPTMEX_getMipResult(prob, out_result)); - } else { - COPTMEX_CALL(COPTMEX_getLpResult(prob, out_result)); - } - -exit_cleanup: - return retcode; -} - -/* Extract model data */ -int COPTMEX_getModel(copt_prob *prob, int nfiles, const mxArray **in_files, - mxArray **out_model) { - int retcode = COPT_RETCODE_OK; - int hasInfoFile = 0; - mxArray *retmodel = NULL; - coptmex_cprob cprob; - coptmex_mprob mprob; - - // Read model from file - if (nfiles == 1 || nfiles == 2) { - COPTMEX_CALL(COPTMEX_readModel(prob, in_files[0])); - if (nfiles == 2) { - COPTMEX_CALL(COPTMEX_readInfo(prob, in_files[1])); - hasInfoFile = 1; - } - } - - COPTMEX_initCProb(&cprob); - COPTMEX_initMProb(&mprob); - - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_ROWS, &cprob.nRow)); - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_COLS, &cprob.nCol)); - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_ELEMS, &cprob.nElem)); - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_QELEMS, &cprob.nQElem)); - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_SOSS, &cprob.nSos)); - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_INDICATORS, &cprob.nIndicator)); - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_CONES, &cprob.nCone)); - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_QCONSTRS, &cprob.nQConstr)); - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_OBJSENSE, &cprob.nObjSen)); - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_HASBASIS, &cprob.hasBasis)); - - mprob.objsen = mxCreateString(COPTMEX_objsenInt2Str(cprob.nObjSen)); - mprob.objcon = mxCreateDoubleMatrix(1, 1, mxREAL); - if (!mprob.objsen || !mprob.objcon) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - COPTMEX_CALL(COPT_GetDblAttr(prob, COPT_DBLATTR_OBJCONST, &cprob.dObjConst)); - *mxGetDoubles(mprob.objcon) = cprob.dObjConst; - - if (cprob.nRow > 0 && cprob.nCol > 0) { - int nRealElem = 0; - if (cprob.nElem == 0) { - nRealElem = 1; - } else { - nRealElem = cprob.nElem; - } - - mprob.A = mxCreateSparse(cprob.nRow, cprob.nCol, nRealElem, mxREAL); - if (!mprob.A) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - cprob.colMatBeg = (int *) mxCalloc(cprob.nCol + 1, sizeof(int)); - cprob.colMatIdx = (int *) mxCalloc(nRealElem, sizeof(int)); - if (!cprob.colMatBeg || !cprob.colMatIdx) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - cprob.colMatElem = mxGetDoubles(mprob.A); - - if (cprob.nElem > 0) { - COPTMEX_CALL(COPT_GetCols(prob, cprob.nCol, NULL, cprob.colMatBeg, NULL, - cprob.colMatIdx, cprob.colMatElem, cprob.nElem, NULL)); - } - - mwIndex *colMatBeg_data = mxGetJc(mprob.A); - mwIndex *colMatIdx_data = mxGetIr(mprob.A); - - for (int i = 0; i < cprob.nCol + 1; ++i) { - colMatBeg_data[i] = cprob.colMatBeg[i]; - } - for (int i = 0; i < nRealElem; ++i) { - colMatIdx_data[i] = cprob.colMatIdx[i]; - } - - mxFree(cprob.colMatBeg); - mxFree(cprob.colMatIdx); - } - - if (cprob.nCol > 0) { - mprob.obj = mxCreateDoubleMatrix(cprob.nCol, 1, mxREAL); - mprob.lb = mxCreateDoubleMatrix(cprob.nCol, 1, mxREAL); - mprob.ub = mxCreateDoubleMatrix(cprob.nCol, 1, mxREAL); - mprob.varnames = mxCreateCellMatrix(cprob.nCol, 1); - if (!mprob.obj || !mprob.lb || !mprob.ub || !mprob.varnames) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - cprob.colCost = mxGetDoubles(mprob.obj); - cprob.colLower = mxGetDoubles(mprob.lb); - cprob.colUpper = mxGetDoubles(mprob.ub); - - COPTMEX_CALL(COPT_GetColInfo(prob, COPT_DBLINFO_OBJ, cprob.nCol, NULL, cprob.colCost)); - COPTMEX_CALL(COPT_GetColInfo(prob, COPT_DBLINFO_LB, cprob.nCol, NULL, cprob.colLower)); - COPTMEX_CALL(COPT_GetColInfo(prob, COPT_DBLINFO_UB, cprob.nCol, NULL, cprob.colUpper)); - - char *colType_c = (char *) mxCalloc(2 * cprob.nCol, sizeof(char)); - char **colType_s = (char **) mxCalloc(cprob.nCol, sizeof(char *)); - if (!colType_c || !colType_s) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - COPTMEX_CALL(COPT_GetColType(prob, cprob.nCol, NULL, colType_c)); - - for (int i = cprob.nCol - 1; i >= 0; --i) { - colType_c[2 * i] = colType_c[i]; - colType_c[2 * i + 1] = 0; - } - - for (int i = 0; i < cprob.nCol; ++i) { - colType_s[i] = colType_c + 2 * i; - } - - mprob.vtype = mxCreateCharMatrixFromStrings(cprob.nCol, (const char **) colType_s); - - int colNameLen = 0; - char **colNames = (char **) mxCalloc(cprob.nCol, sizeof(char *)); - if (!colNames) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - for (int i = 0; i < cprob.nCol; ++i) { - COPTMEX_CALL(COPT_GetColName(prob, i, NULL, 0, &colNameLen)); - colNames[i] = (char *) mxCalloc(colNameLen, sizeof(char)); - if (!colNames[i]) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - COPTMEX_CALL(COPT_GetColName(prob, i, colNames[i], colNameLen, NULL)); - - mxSetCell(mprob.varnames, i, mxCreateString(colNames[i])); - } - } - - if (cprob.nRow > 0) { - mprob.lhs = mxCreateDoubleMatrix(cprob.nRow, 1, mxREAL); - mprob.rhs = mxCreateDoubleMatrix(cprob.nRow, 1, mxREAL); - mprob.constrnames = mxCreateCellMatrix(cprob.nRow, 1); - if (!mprob.lhs || !mprob.rhs || !mprob.constrnames) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - cprob.rowLower = mxGetDoubles(mprob.lhs); - cprob.rowUpper = mxGetDoubles(mprob.rhs); - - COPTMEX_CALL(COPT_GetRowInfo(prob, COPT_DBLINFO_LB, cprob.nRow, NULL, cprob.rowLower)); - COPTMEX_CALL(COPT_GetRowInfo(prob, COPT_DBLINFO_UB, cprob.nRow, NULL, cprob.rowUpper)); - - int rowNameLen = 0; - //TODO: rowSense - char **rowNames = (char **) mxCalloc(cprob.nRow, sizeof(char *)); - if (!rowNames) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - for (int i = 0; i < cprob.nRow; ++i) { - COPTMEX_CALL(COPT_GetRowName(prob, i, NULL, 0, &rowNameLen)); - rowNames[i] = (char *) mxCalloc(rowNameLen, sizeof(char)); - if (!rowNames[i]) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - COPTMEX_CALL(COPT_GetRowName(prob, i, rowNames[i], rowNameLen, NULL)); - - mxSetCell(mprob.constrnames, i, mxCreateString(rowNames[i])); - } - } - - if (cprob.nSos > 0) { - const char *sosfields[] = {COPTMEX_MODEL_SOSTYPE, - COPTMEX_MODEL_SOSVARS, - COPTMEX_MODEL_SOSWEIGHT}; - mprob.sos = mxCreateStructMatrix(cprob.nSos, 1, 3, sosfields); - if (!mprob.sos) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - COPTMEX_CALL(COPT_GetSOSs(prob, cprob.nSos, NULL, NULL, NULL, NULL, NULL, - NULL, 0, &cprob.nSosSize)); - - cprob.sosType = (int *) mxCalloc(cprob.nSos, sizeof(int)); - cprob.sosMatBeg = (int *) mxCalloc(cprob.nSos, sizeof(int)); - cprob.sosMatCnt = (int *) mxCalloc(cprob.nSos, sizeof(int)); - cprob.sosMatIdx = (int *) mxCalloc(cprob.nSosSize, sizeof(int)); - cprob.sosMatWt = (double *) mxCalloc(cprob.nSosSize, sizeof(double)); - if (!cprob.sosType || !cprob.sosMatBeg || !cprob.sosMatCnt || - !cprob.sosMatIdx || !cprob.sosMatWt) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - COPTMEX_CALL(COPT_GetSOSs(prob, cprob.nSos, NULL, cprob.sosType, - cprob.sosMatBeg, cprob.sosMatCnt, cprob.sosMatIdx, - cprob.sosMatWt, cprob.nSosSize, NULL)); - - for (int i = 0; i < cprob.nSos; ++i) { - mxArray *sosType = mxCreateDoubleMatrix(1, 1, mxREAL); - mxArray *sosIdx = mxCreateDoubleMatrix(cprob.sosMatCnt[i], 1, mxREAL); - mxArray *sosWts = mxCreateDoubleMatrix(cprob.sosMatCnt[i], 1, mxREAL); - if (!sosType || !sosIdx || !sosWts) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - *mxGetDoubles(sosType) = cprob.sosType[i]; - - int iSosElem = cprob.sosMatBeg[i]; - int iSosLast = cprob.sosMatCnt[i] + iSosElem; - double *sosIdx_data = mxGetDoubles(sosIdx); - double *sosWts_data = mxGetDoubles(sosWts); - for (int iElem = 0; iElem < cprob.sosMatCnt[i]; ++iElem) { - sosIdx_data[iElem] = cprob.sosMatIdx[iSosElem] + 1; - sosWts_data[iElem] = cprob.sosMatWt[iSosElem]; - iSosElem++; - } - - mxSetField(mprob.sos, i, COPTMEX_MODEL_SOSTYPE, sosType); - mxSetField(mprob.sos, i, COPTMEX_MODEL_SOSVARS, sosIdx); - mxSetField(mprob.sos, i, COPTMEX_MODEL_SOSWEIGHT, sosWts); - } - } - - if (cprob.nIndicator > 0) { - const char *indicfields[] = {COPTMEX_MODEL_INDICBINVAR, - COPTMEX_MODEL_INDICBINVAL, - COPTMEX_MODEL_INDICROW, - COPTMEX_MODEL_INDICSENSE, - COPTMEX_MODEL_INDICRHS}; - mprob.indicator = mxCreateStructMatrix(cprob.nIndicator, 1, 5, indicfields); - if (!mprob.indicator) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - for (int i = 0; i < cprob.nIndicator; ++i) { - int rowElemCnt = 0; - COPTMEX_CALL(COPT_GetIndicator(prob, i, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, 0, &rowElemCnt)); - - mxArray *binVar = mxCreateDoubleMatrix(1, 1, mxREAL); - mxArray *binVal = mxCreateDoubleMatrix(1, 1, mxREAL); - mxArray *indicA = mxCreateSparse(cprob.nCol, 1, rowElemCnt, mxREAL); - mxArray *indicSense = NULL; - mxArray *indicRhs = mxCreateDoubleMatrix(1, 1, mxREAL); - - int binColIdx = 0; - int binColVal = 0; - int nRowMatCnt = 0; - int *rowMatIdx = (int *) mxCalloc(rowElemCnt, sizeof(int)); - double *rowMatElem = (double *) mxCalloc(rowElemCnt, sizeof(double)); - char cRowSense[2] = {0}; - double dRowBound = 0; - - COPTMEX_CALL(COPT_GetIndicator(prob, i, &binColIdx, &binColVal, - &nRowMatCnt, rowMatIdx, rowMatElem, &cRowSense[0], - &dRowBound, rowElemCnt, NULL)); - - *mxGetDoubles(binVar) = binColIdx + 1; - *mxGetDoubles(binVal) = binColVal; - - mwIndex *jc_data = mxGetJc(indicA); - mwIndex *ir_data = mxGetIr(indicA); - double *val_data = mxGetDoubles(indicA); - - jc_data[0] = 0; - jc_data[1] = rowElemCnt; - for (int i = 0; i < rowElemCnt; ++i) { - ir_data[i] = rowMatIdx[i]; - val_data[i] = rowMatElem[i]; - } - - indicSense = mxCreateString(cRowSense); - *mxGetDoubles(indicRhs) = dRowBound; - - mxFree(rowMatIdx); - mxFree(rowMatElem); - - mxSetField(mprob.indicator, i, COPTMEX_MODEL_INDICBINVAR, binVar); - mxSetField(mprob.indicator, i, COPTMEX_MODEL_INDICBINVAL, binVal); - mxSetField(mprob.indicator, i, COPTMEX_MODEL_INDICROW, indicA); - mxSetField(mprob.indicator, i, COPTMEX_MODEL_INDICSENSE, indicSense); - mxSetField(mprob.indicator, i, COPTMEX_MODEL_INDICRHS, indicRhs); - } - } - - if (cprob.nCone > 0) { - const char *conefields[] = {COPTMEX_MODEL_CONETYPE, - COPTMEX_MODEL_CONEVARS}; - mprob.cone = mxCreateStructMatrix(cprob.nCone, 1, 2, conefields); - if (!mprob.cone) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - COPTMEX_CALL(COPT_GetCones(prob, cprob.nCone, NULL, NULL, NULL, NULL, NULL, - 0, &cprob.nConeSize)); - - cprob.coneType = (int *) mxCalloc(cprob.nCone, sizeof(int)); - cprob.coneBeg = (int *) mxCalloc(cprob.nCone, sizeof(int)); - cprob.coneCnt = (int *) mxCalloc(cprob.nCone, sizeof(int)); - cprob.coneIdx = (int *) mxCalloc(cprob.nConeSize, sizeof(int)); - if (!cprob.coneType || !cprob.coneBeg || !cprob.coneCnt || !cprob.coneIdx) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - COPTMEX_CALL(COPT_GetCones(prob, cprob.nCone, NULL, cprob.coneType, - cprob.coneBeg, cprob.coneCnt, cprob.coneIdx, cprob.nConeSize, - NULL)); - - for (int i = 0; i < cprob.nCone; ++i) { - mxArray *coneType = mxCreateDoubleMatrix(1, 1, mxREAL); - mxArray *coneIdx = mxCreateDoubleMatrix(cprob.coneCnt[i], 1, mxREAL); - if (!coneType || !coneIdx) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - *mxGetDoubles(coneType) = cprob.coneType[i]; - - int iConeElem = cprob.coneBeg[i]; - int iConeLast = cprob.coneCnt[i] + iConeElem; - double *coneIdx_data = mxGetDoubles(coneIdx); - for (int iElem = 0; iElem < cprob.coneCnt[i]; ++iElem) { - coneIdx_data[iElem] = cprob.coneIdx[iConeElem] + 1; - iConeElem++; - } - - mxSetField(mprob.cone, i, COPTMEX_MODEL_CONETYPE, coneType); - mxSetField(mprob.cone, i, COPTMEX_MODEL_CONEVARS, coneIdx); - } - } - - if (cprob.nQElem > 0) { - mprob.qobj = mxCreateSparse(cprob.nCol, cprob.nCol, cprob.nQElem, mxREAL); - if (!mprob.qobj) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - int *qObjRow = (int *) mxCalloc(cprob.nQElem, sizeof(int)); - int *qObjCol = (int *) mxCalloc(cprob.nQElem, sizeof(int)); - double *qObjElem = (double *) mxCalloc(cprob.nQElem, sizeof(double)); - if (!qObjRow || !qObjCol || !qObjElem) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - COPTMEX_CALL(COPT_GetQuadObj(prob, NULL, qObjRow, qObjCol, qObjElem)); - COPTMEX_CALL(COPTMEX_coo2csc(cprob.nQElem, qObjRow, qObjCol, qObjElem, mprob.qobj)); - - mxFree(qObjRow); - mxFree(qObjCol); - mxFree(qObjElem); - } - - if (cprob.nQConstr > 0) { - const char *qconstrfields[] = {COPTMEX_MODEL_QCROW, - COPTMEX_MODEL_QCCOL, - COPTMEX_MODEL_QCVAL, - COPTMEX_MODEL_QCLINEAR, - COPTMEX_MODEL_QCSENSE, - COPTMEX_MODEL_QCRHS, - COPTMEX_MODEL_QCNAME}; - mprob.quadcon = mxCreateStructMatrix(cprob.nQConstr, 1, 7, qconstrfields); - if (!mprob.quadcon) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - for (int i = 0; i < cprob.nQConstr; ++i) { - int nQMatElem = 0; - int nQRowElem = 0; - COPTMEX_CALL(COPT_GetQConstr(prob, i, NULL, NULL, NULL, 0, &nQMatElem, NULL, - NULL, NULL, NULL, 0, &nQRowElem)); - - mxArray *QcRow = mxCreateDoubleMatrix(nQMatElem, 1, mxREAL); - mxArray *QcCol = mxCreateDoubleMatrix(nQMatElem, 1, mxREAL); - mxArray *QcVal = mxCreateDoubleMatrix(nQMatElem, 1, mxREAL); - mxArray *QcLinear = mxCreateSparse(cprob.nCol, 1, nQRowElem, mxREAL); - mxArray *QcSense = NULL; - mxArray *QcRhs = mxCreateDoubleMatrix(1, 1, mxREAL); - mxArray *QcName = NULL; - - int *qMatRow = (int *) mxCalloc(nQMatElem, sizeof(int)); - int *qMatCol = (int *) mxCalloc(nQMatElem, sizeof(int)); - double *qMatElem = mxGetDoubles(QcVal); - int *qRowMatIdx = (int *) mxCalloc(nQRowElem, sizeof(int)); - double *qRowMatElem = mxGetDoubles(QcLinear); - char qRowSense[2]; - double qRowBound = 0.0; - char *qRowName = NULL; - - COPTMEX_CALL(COPT_GetQConstr(prob, i, qMatRow, qMatCol, qMatElem, nQMatElem, NULL, - qRowMatIdx, qRowMatElem, qRowSense, &qRowBound, nQRowElem, NULL)); - - double *qMatRow_data = mxGetDoubles(QcRow); - double *qMatCol_data = mxGetDoubles(QcCol); - for (int i = 0; i < nQMatElem; ++i) { - qMatRow_data[i] = qMatRow[i]; - qMatCol_data[i] = qMatCol[i]; - } - - mwIndex *jc_data = mxGetJc(QcLinear); - mwIndex *ir_data = mxGetIr(QcLinear); - - jc_data[0] = 0; - jc_data[1] = nQRowElem; - for (int i = 0; i < nQRowElem; ++i) { - ir_data[i] = qRowMatIdx[i]; - } - - QcSense = mxCreateString(qRowSense); - *mxGetDoubles(QcRhs) = qRowBound; - - int nQcNameSize = 0; - COPTMEX_CALL(COPT_GetQConstrName(prob, i, NULL, 0, &nQcNameSize)); - - qRowName = (char *) mxCalloc(nQcNameSize + 1, sizeof(char)); - if (!qRowName) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - COPTMEX_CALL(COPT_GetQConstrName(prob, i, qRowName, nQcNameSize, NULL)); - QcName = mxCreateString(qRowName); - - mxSetField(mprob.quadcon, i, COPTMEX_MODEL_QCROW, QcRow); - mxSetField(mprob.quadcon, i, COPTMEX_MODEL_QCCOL, QcCol); - mxSetField(mprob.quadcon, i, COPTMEX_MODEL_QCVAL, QcVal); - mxSetField(mprob.quadcon, i, COPTMEX_MODEL_QCLINEAR, QcLinear); - mxSetField(mprob.quadcon, i, COPTMEX_MODEL_QCSENSE, QcSense); - mxSetField(mprob.quadcon, i, COPTMEX_MODEL_QCRHS, QcRhs); - mxSetField(mprob.quadcon, i, COPTMEX_MODEL_QCNAME, QcName); - - mxFree(qMatRow); - mxFree(qMatCol); - mxFree(qRowMatIdx); - mxFree(qRowName); - } - } - - if (hasInfoFile && cprob.hasBasis) { - mprob.varbasis = mxCreateDoubleMatrix(cprob.nCol, 1, mxREAL); - mprob.constrbasis = mxCreateDoubleMatrix(cprob.nRow, 1, mxREAL); - if (!mprob.varbasis || !mprob.constrbasis) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - cprob.colBasis = (int *) mxCalloc(cprob.nCol, sizeof(int)); - cprob.rowBasis = (int *) mxCalloc(cprob.nRow, sizeof(int)); - if (!cprob.colBasis || !cprob.rowBasis) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - COPTMEX_CALL(COPT_GetColBasis(prob, cprob.nCol, NULL, cprob.colBasis)); - COPTMEX_CALL(COPT_GetRowBasis(prob, cprob.nRow, NULL, cprob.rowBasis)); - - double *colBasis_data = mxGetDoubles(mprob.varbasis); - double *rowBasis_data = mxGetDoubles(mprob.constrbasis); - for (int i = 0; i < cprob.nCol; ++i) { - colBasis_data[i] = cprob.colBasis[i]; - } - for (int i = 0; i < cprob.nRow; ++i) { - rowBasis_data[i] = cprob.rowBasis[i]; - } - - mxFree(cprob.colBasis); - mxFree(cprob.rowBasis); - } - - retmodel = mxCreateStructMatrix(1, 1, 0, NULL); - if (!retmodel) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - // 'objsen' - mxAddField(retmodel, COPTMEX_MODEL_OBJSEN); - mxSetField(retmodel, 0, COPTMEX_MODEL_OBJSEN, mprob.objsen); - // 'objcon' - mxAddField(retmodel, COPTMEX_MODEL_OBJCON); - mxSetField(retmodel, 0, COPTMEX_MODEL_OBJCON, mprob.objcon); - - if (mprob.A != NULL) { - // 'A' - mxAddField(retmodel, COPTMEX_MODEL_A); - mxSetField(retmodel, 0, COPTMEX_MODEL_A, mprob.A); - } - - if (cprob.nCol > 0) { - // 'obj' - mxAddField(retmodel, COPTMEX_MODEL_OBJ); - mxSetField(retmodel, 0, COPTMEX_MODEL_OBJ, mprob.obj); - // 'lb' - mxAddField(retmodel, COPTMEX_MODEL_LB); - mxSetField(retmodel, 0, COPTMEX_MODEL_LB, mprob.lb); - // 'ub' - mxAddField(retmodel, COPTMEX_MODEL_UB); - mxSetField(retmodel, 0, COPTMEX_MODEL_UB, mprob.ub); - // 'vtype' - mxAddField(retmodel, COPTMEX_MODEL_VTYPE); - mxSetField(retmodel, 0, COPTMEX_MODEL_VTYPE, mprob.vtype); - // 'varnames' - mxAddField(retmodel, COPTMEX_MODEL_VARNAME); - mxSetField(retmodel, 0, COPTMEX_MODEL_VARNAME, mprob.varnames); - } - - if (cprob.nRow > 0) { - //TODO: 'sense' - // 'lhs' - mxAddField(retmodel, COPTMEX_MODEL_LHS); - mxSetField(retmodel, 0, COPTMEX_MODEL_LHS, mprob.lhs); - // 'rhs' - mxAddField(retmodel, COPTMEX_MODEL_RHS); - mxSetField(retmodel, 0, COPTMEX_MODEL_RHS, mprob.rhs); - // 'constrnames' - mxAddField(retmodel, COPTMEX_MODEL_CONNAME); - mxSetField(retmodel, 0, COPTMEX_MODEL_CONNAME, mprob.constrnames); - } - - // 'sos' - if (cprob.nSos > 0) { - mxAddField(retmodel, COPTMEX_MODEL_SOS); - mxSetField(retmodel, 0, COPTMEX_MODEL_SOS, mprob.sos); - } - - // 'indicator' - if (cprob.nIndicator > 0) { - mxAddField(retmodel, COPTMEX_MODEL_INDICATOR); - mxSetField(retmodel, 0, COPTMEX_MODEL_INDICATOR, mprob.indicator); - } - - // 'cone' - if (cprob.nCone > 0) { - mxAddField(retmodel, COPTMEX_MODEL_CONE); - mxSetField(retmodel, 0, COPTMEX_MODEL_CONE, mprob.cone); - } - - // 'Q' - if (cprob.nQElem > 0) { - mxAddField(retmodel, COPTMEX_MODEL_QUADOBJ); - mxSetField(retmodel, 0, COPTMEX_MODEL_QUADOBJ, mprob.qobj); - } - - // 'quadcon' - if (cprob.nQConstr > 0) { - mxAddField(retmodel, COPTMEX_MODEL_QUADCON); - mxSetField(retmodel, 0, COPTMEX_MODEL_QUADCON, mprob.quadcon); - } - - if (hasInfoFile && cprob.hasBasis) { - // 'varbasis' - mxAddField(retmodel, COPTMEX_RESULT_VARBASIS); - mxSetField(retmodel, 0, COPTMEX_RESULT_VARBASIS, mprob.varbasis); - // 'constrbasis' - mxAddField(retmodel, COPTMEX_RESULT_CONBASIS); - mxSetField(retmodel, 0, COPTMEX_RESULT_CONBASIS, mprob.constrbasis); - } - - *out_model = retmodel; - -exit_cleanup: - if (retcode != COPT_RETCODE_OK) { - *out_model = NULL; - } - - return retcode; -} - -/* Load parameters to problem */ -int COPTMEX_setParam(copt_prob *prob, const mxArray *in_param) { - int retcode = 0; - char msgbuf[COPT_BUFFSIZE]; - - int islogging = 1; - mxArray *logging = NULL; - for (int i = mxGetNumberOfFields(in_param) - 1; i >= 0; --i) { - const char *loggingname = mxGetFieldNameByNumber(in_param, i); - if (mystrcmp(loggingname, COPT_INTPARAM_LOGGING) == 0) { - logging = mxGetField(in_param, 0, loggingname); - if (!mxIsScalar(logging) || mxIsChar(logging)) { - snprintf(msgbuf, COPT_BUFFSIZE, "parameter.%s", COPT_INTPARAM_LOGGING); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - - islogging = (int) mxGetScalar(logging); - break; - } - } - - if (islogging == 1) { - COPTMEX_CALL(COPTMEX_dispBanner()); - } - - if (logging != NULL) { - COPTMEX_CALL(COPT_SetIntParam(prob, COPT_INTPARAM_LOGGING, islogging)); - } - - for (int i = 0; i < mxGetNumberOfFields(in_param); ++i) { - int partype = -1; - const char *parname = mxGetFieldNameByNumber(in_param, i); - mxArray *pararray = mxGetField(in_param, 0, parname); - - if (mystrcmp(parname, COPT_INTPARAM_LOGGING) == 0) { - continue; - } - - COPTMEX_CALL(COPT_SearchParamAttr(prob, parname, &partype)); - if (partype != 0 && partype != 1) { - snprintf(msgbuf, COPT_BUFFSIZE, "parameter.%s", parname); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NAME, msgbuf); - goto exit_cleanup; - } - - if (!mxIsScalar(pararray) || mxIsChar(pararray)) { - snprintf(msgbuf, COPT_BUFFSIZE, "parameter.%s", parname); - COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); - goto exit_cleanup; - } - - if (partype == 0) { - COPTMEX_CALL(COPT_SetDblParam(prob, parname, mxGetScalar(pararray))); - } else if (partype == 1) { - COPTMEX_CALL(COPT_SetIntParam(prob, parname, (int) mxGetScalar(pararray))); - } - } - -exit_cleanup: - return retcode; -} - -static char *COPTMEX_getFileExt(const char *filename) { - char *tmpfilename = NULL; - char *lastdot = NULL; - int lenfile = strlen(filename); - - tmpfilename = (char *) mxCalloc(lenfile + 1, sizeof(char)); - memcpy(tmpfilename, filename, lenfile + 1); - - lastdot = strrchr(tmpfilename, '.'); - if (!lastdot || lastdot == tmpfilename) { - return ""; - } - - if (lastdot != NULL) { - if (strcmp(lastdot, ".gz") == 0) { - *lastdot = '\0'; - - lastdot = strrchr(tmpfilename, '.'); - if (!lastdot || lastdot == tmpfilename) { - return ""; - } - } - } - - return lastdot + 1; -} - -/* Read optional information from file */ -int COPTMEX_readInfo(copt_prob *prob, const mxArray *in_info) { - int retcode = 0; - char *filename = NULL; - char *fileext = NULL; - - COPTMEX_CALL(COPTMEX_getString(in_info, &filename)); - - fileext = COPTMEX_getFileExt(filename); - if (strcmp(fileext, "bas") == 0) { - COPTMEX_CALL(COPT_ReadBasis(prob, filename)); - } else { - retcode = COPT_RETCODE_INVALID; - } - -exit_cleanup: - COPTMEX_freeString(&filename); - return retcode; -} - -/* Read model from file */ -int COPTMEX_readModel(copt_prob *prob, const mxArray *in_model) { - int retcode = 0; - char *filename = NULL; - char *fileext = NULL; - - COPTMEX_CALL(COPTMEX_getString(in_model, &filename)); - - fileext = COPTMEX_getFileExt(filename); - if (strcmp(fileext, "mps") == 0) { - COPTMEX_CALL(COPT_ReadMps(prob, filename)); - } else if (strcmp(fileext, "lp") == 0) { - COPTMEX_CALL(COPT_ReadLp(prob, filename)); - } else if (strcmp(fileext, "bin") == 0) { - COPTMEX_CALL(COPT_ReadBin(prob, filename)); - } else if (strcmp(fileext, "dat-s") == 0) { - COPTMEX_CALL(COPT_ReadSDPA(prob, filename)); - } else if (strcmp(fileext, "cbf") == 0) { - COPTMEX_CALL(COPT_ReadCbf(prob, filename)); - } else { - retcode = COPT_RETCODE_INVALID; - } - -exit_cleanup: - COPTMEX_freeString(&filename); - return retcode; -} - -/* Write model to file */ -int COPTMEX_writeModel(copt_prob *prob, const mxArray *out_file) { - int retcode = 0; - char *filename = NULL; - char *fileext = NULL; - - COPTMEX_CALL(COPTMEX_getString(out_file, &filename)); - - fileext = COPTMEX_getFileExt(filename); - if (strcmp(fileext, "mps") == 0) { - COPTMEX_CALL(COPT_WriteMps(prob, filename)); - } else if (strcmp(fileext, "lp") == 0) { - COPTMEX_CALL(COPT_WriteLp(prob, filename)); - } else if (strcmp(fileext, "bin") == 0) { - COPTMEX_CALL(COPT_WriteBin(prob, filename)); - } else if (strcmp(fileext, "cbf") == 0) { - COPTMEX_CALL(COPT_WriteCbf(prob, filename)); - } else { - retcode = COPT_RETCODE_INVALID; - } - -exit_cleanup: - COPTMEX_freeString(&filename); - return retcode; -} - -/* Check if solve problem via cone data */ -int COPTMEX_isConeModel(const mxArray *in_model) { - int ifConeData = 0; - mxArray *conedata = NULL; - - conedata = mxGetField(in_model, 0, COPTMEX_MODEL_CONEDATA); - if (conedata != NULL) { - if (COPTMEX_checkConeModel(conedata)) { - ifConeData = 1; - } - } - - return ifConeData; -} - -/* Solve cone problem with cone data */ -int COPTMEX_solveConeModel(copt_prob *prob, const mxArray *in_model, mxArray **out_result, int ifRetResult) { - int retcode = 0; - coptmex_cconeprob cconeprob; - coptmex_mconeprob mconeprob; - mxArray *conedata = NULL; - int *outRowMap = NULL; - - COPTMEX_initCConeProb(&cconeprob); - COPTMEX_initMConeProb(&mconeprob); - - conedata = mxGetField(in_model, 0, COPTMEX_MODEL_CONEDATA); - - mconeprob.c = mxGetField(conedata, 0, COPTMEX_MODEL_CONE_C); - mconeprob.A = mxGetField(conedata, 0, COPTMEX_MODEL_CONE_A); - mconeprob.b = mxGetField(conedata, 0, COPTMEX_MODEL_CONE_B); - - mconeprob.K = mxGetField(conedata, 0, COPTMEX_MODEL_CONE_K); - mconeprob.f = mxGetField(mconeprob.K, 0, COPTMEX_MODEL_CONEK_F); - mconeprob.l = mxGetField(mconeprob.K, 0, COPTMEX_MODEL_CONEK_L); - mconeprob.q = mxGetField(mconeprob.K, 0, COPTMEX_MODEL_CONEK_Q); - mconeprob.r = mxGetField(mconeprob.K, 0, COPTMEX_MODEL_CONEK_R); - mconeprob.s = mxGetField(mconeprob.K, 0, COPTMEX_MODEL_CONEK_S); - - mconeprob.objsen = mxGetField(conedata, 0, COPTMEX_MODEL_CONE_OBJSEN); - mconeprob.objcon = mxGetField(conedata, 0, COPTMEX_MODEL_CONE_OBJCON); - mconeprob.Q = mxGetField(conedata, 0, COPTMEX_MODEL_CONE_Q); - - // 'objsen' - if (mconeprob.objsen != NULL) { - COPTMEX_CALL(COPTMEX_getObjsen(mconeprob.objsen, &cconeprob.nObjSense)); - } - // 'objcon' - if (mconeprob.objcon != NULL) { - cconeprob.dObjConst = mxGetScalar(mconeprob.objcon); - } - // 'Q' - if (mconeprob.Q != NULL) { - cconeprob.nQObjElem = mxGetNzmax(mconeprob.Q); - - cconeprob.qObjRow = (int *) mxCalloc(cconeprob.nQObjElem, sizeof(int)); - cconeprob.qObjCol = (int *) mxCalloc(cconeprob.nQObjElem, sizeof(int)); - cconeprob.qObjElem = (double *) mxCalloc(cconeprob.nQObjElem, sizeof(double)); - if (!cconeprob.qObjRow || !cconeprob.qObjCol || !cconeprob.qObjElem) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - COPTMEX_csc2coo(mconeprob.Q, cconeprob.qObjRow, cconeprob.qObjCol, cconeprob.qObjElem); - } - - // 'c' - if (mconeprob.c != NULL) { - cconeprob.colObj = mxGetDoubles(mconeprob.c); - } - // 'A' - if (mconeprob.A != NULL) { - cconeprob.nRow = mxGetM(mconeprob.A); - cconeprob.nCol = mxGetN(mconeprob.A); - cconeprob.nElem = mxGetNzmax(mconeprob.A); - cconeprob.colMatBeg = (int *) mxCalloc(cconeprob.nCol + 1, sizeof(int)); - cconeprob.colMatIdx = (int *) mxCalloc(cconeprob.nElem, sizeof(int)); - if (!cconeprob.colMatBeg || !cconeprob.colMatIdx) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - mwIndex *colMatBeg_data = mxGetJc(mconeprob.A); - mwIndex *colMatIdx_data = mxGetIr(mconeprob.A); - for (int i = 0; i < cconeprob.nCol + 1; ++i) { - cconeprob.colMatBeg[i] = (int) colMatBeg_data[i]; - } - for (int i = 0; i < cconeprob.nElem; ++i) { - cconeprob.colMatIdx[i] = (int) colMatIdx_data[i]; - } - - cconeprob.colMatElem = mxGetDoubles(mconeprob.A); - } - // 'b' - if (mconeprob.b != NULL) { - cconeprob.rowRhs = mxGetDoubles(mconeprob.b); - } - - // 'K' - if (mconeprob.K != NULL) { - // 'f' - if (mconeprob.f != NULL) { - cconeprob.nFree = (int) mxGetScalar(mconeprob.f); - } - // 'l' - if (mconeprob.l != NULL) { - cconeprob.nPositive = (int) mxGetScalar(mconeprob.l); - } - // 'q' - if (mconeprob.q != NULL) { - int nCone = mxGetNumberOfElements(mconeprob.q); - double *coneDim_data = mxGetDoubles(mconeprob.q); - - if (nCone > 1 || (nCone == 1 && coneDim_data[0] > 0)) { - cconeprob.nCone = nCone; - cconeprob.coneDim = (int *) mxCalloc(cconeprob.nCone, sizeof(int)); - - for (int i = 0; i < cconeprob.nCone; ++i) { - cconeprob.coneDim[i] = (int) coneDim_data[i]; - } - } - } - // 'r' - if (mconeprob.r != NULL) { - int nRotateCone = mxGetNumberOfElements(mconeprob.r); - double *rotateConeDim_data = mxGetDoubles(mconeprob.r); - - if (nRotateCone > 1 || (nRotateCone == 1 && rotateConeDim_data[0] > 0)) { - cconeprob.nRotateCone = nRotateCone; - cconeprob.rotateConeDim = (int *) mxCalloc(cconeprob.nRotateCone, sizeof(int)); - - for (int i = 0; i < cconeprob.nRotateCone; ++i) { - cconeprob.rotateConeDim[i] = (int) rotateConeDim_data[i]; - } - } - } - // 's' - if (mconeprob.s != NULL) { - int nPSD = mxGetNumberOfElements(mconeprob.s); - double *psdDim_data = mxGetDoubles(mconeprob.s); - - if (nPSD > 1 || (nPSD == 1 && psdDim_data[0] > 0)) { - cconeprob.nPSD = nPSD; - cconeprob.psdDim = (int *) mxCalloc(cconeprob.nPSD, sizeof(int)); - - for (int i = 0; i < cconeprob.nPSD; ++i) { - cconeprob.psdDim[i] = (int) psdDim_data[i]; - } - } - } - } - - outRowMap = (int *) mxCalloc(cconeprob.nRow, sizeof(int)); - if (!outRowMap) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - // Load cone problem data - COPTMEX_CALL(COPT_LoadConeProb(prob, cconeprob.nCol, cconeprob.nRow, - cconeprob.nFree, cconeprob.nPositive, 0, cconeprob.nCone, cconeprob.nRotateCone, - 0, 0, 0, 0, cconeprob.nPSD, cconeprob.nQObjElem, cconeprob.nObjSense, cconeprob.dObjConst, - cconeprob.colObj, cconeprob.qObjRow, cconeprob.qObjCol, cconeprob.qObjElem, - cconeprob.colMatBeg, NULL, cconeprob.colMatIdx, cconeprob.colMatElem, cconeprob.rowRhs, - NULL, NULL, cconeprob.coneDim, cconeprob.rotateConeDim, NULL, NULL, NULL, NULL, - cconeprob.psdDim, NULL, NULL, NULL, NULL, outRowMap)); - - COPTMEX_CALL(COPT_Solve(prob)); - - if (ifRetResult == 1) { - COPTMEX_CALL(COPTMEX_getResult(prob, out_result)); - - if (*out_result != NULL) { - mxArray *rowMap = mxCreateDoubleMatrix(cconeprob.nRow, 1, mxREAL); - if (rowMap == NULL) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - double *rowMap_data = mxGetDoubles(rowMap); - for (int i = 0; i < cconeprob.nRow; ++i) { - rowMap_data[i] = outRowMap[i]; - } - - mxAddField(*out_result, "rowmap"); - mxSetField(*out_result, 0, "rowmap", rowMap); - } - } - -exit_cleanup: - if (outRowMap != NULL) { - mxFree(outRowMap); - } - - if (cconeprob.qObjRow != NULL) { - mxFree(cconeprob.qObjRow); - } - if (cconeprob.qObjCol != NULL) { - mxFree(cconeprob.qObjCol); - } - if (cconeprob.qObjElem != NULL) { - mxFree(cconeprob.qObjElem); - } - - if (cconeprob.coneDim != NULL) { - mxFree(cconeprob.coneDim); - } - if (cconeprob.rotateConeDim != NULL) { - mxFree(cconeprob.rotateConeDim); - } - if (cconeprob.psdDim != NULL) { - mxFree(cconeprob.psdDim); - } - - if (cconeprob.colMatBeg != NULL) { - mxFree(cconeprob.colMatBeg); - } - if (cconeprob.colMatIdx != NULL) { - mxFree(cconeprob.colMatIdx); - } - return retcode; -} - -/* Extract and load data to problem */ -int COPTMEX_loadModel(copt_prob *prob, const mxArray *in_model) { - int retcode = 0; - coptmex_cprob cprob; - coptmex_mprob mprob; - - COPTMEX_initCProb(&cprob); - COPTMEX_initMProb(&mprob); - - mprob.objsen = mxGetField(in_model, 0, COPTMEX_MODEL_OBJSEN); - mprob.objcon = mxGetField(in_model, 0, COPTMEX_MODEL_OBJCON); - mprob.A = mxGetField(in_model, 0, COPTMEX_MODEL_A); - mprob.obj = mxGetField(in_model, 0, COPTMEX_MODEL_OBJ); - mprob.lb = mxGetField(in_model, 0, COPTMEX_MODEL_LB); - mprob.ub = mxGetField(in_model, 0, COPTMEX_MODEL_UB); - mprob.vtype = mxGetField(in_model, 0, COPTMEX_MODEL_VTYPE); - mprob.varnames = mxGetField(in_model, 0, COPTMEX_MODEL_VARNAME); - mprob.sense = mxGetField(in_model, 0, COPTMEX_MODEL_SENSE); - mprob.lhs = mxGetField(in_model, 0, COPTMEX_MODEL_LHS); - mprob.rhs = mxGetField(in_model, 0, COPTMEX_MODEL_RHS); - mprob.constrnames = mxGetField(in_model, 0, COPTMEX_MODEL_CONNAME); - - mprob.sos = mxGetField(in_model, 0, COPTMEX_MODEL_SOS); - mprob.indicator = mxGetField(in_model, 0, COPTMEX_MODEL_INDICATOR); - mprob.cone = mxGetField(in_model, 0, COPTMEX_MODEL_CONE); - - mprob.qobj = mxGetField(in_model, 0, COPTMEX_MODEL_QUADOBJ); - mprob.quadcon = mxGetField(in_model, 0, COPTMEX_MODEL_QUADCON); - - mprob.varbasis = mxGetField(in_model, 0, COPTMEX_RESULT_VARBASIS); - mprob.constrbasis = mxGetField(in_model, 0, COPTMEX_RESULT_CONBASIS); - - mprob.value = mxGetField(in_model, 0, COPTMEX_RESULT_VALUE); - mprob.slack = mxGetField(in_model, 0, COPTMEX_RESULT_SLACK); - mprob.dual = mxGetField(in_model, 0, COPTMEX_RESULT_DUAL); - mprob.redcost = mxGetField(in_model, 0, COPTMEX_RESULT_REDCOST); - - mprob.mipstart = mxGetField(in_model, 0, COPTMEX_ADVINFO_MIPSTART); - - if (COPTMEX_checkModel(&mprob) == 0) { - goto exit_cleanup; - } - - // 'objsen' - if (mprob.objsen != NULL) { - COPTMEX_CALL(COPTMEX_getObjsen(mprob.objsen, &cprob.nObjSen)); - } - // 'objcon' - if (mprob.objcon != NULL) { - cprob.dObjConst = mxGetScalar(mprob.objcon); - } - // 'A' - if (mprob.A != NULL) { - cprob.nRow = mxGetM(mprob.A); - cprob.nCol = mxGetN(mprob.A); - cprob.nElem = mxGetNzmax(mprob.A); - cprob.colMatBeg = (int *) mxCalloc(cprob.nCol + 1, sizeof(int)); - cprob.colMatIdx = (int *) mxCalloc(cprob.nElem, sizeof(int)); - if (!cprob.colMatBeg || !cprob.colMatIdx) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - mwIndex *colMatBeg_data = mxGetJc(mprob.A); - mwIndex *colMatIdx_data = mxGetIr(mprob.A); - for (int i = 0; i < cprob.nCol + 1; ++i) { - cprob.colMatBeg[i] = (int) colMatBeg_data[i]; - } - for (int i = 0; i < cprob.nElem; ++i) { - cprob.colMatIdx[i] = (int) colMatIdx_data[i]; - } - - cprob.colMatElem = mxGetDoubles(mprob.A); - } - // 'obj' - if (mprob.obj != NULL) { - cprob.colCost = mxGetDoubles(mprob.obj); - } - // 'lb' - if (mprob.lb != NULL) { - cprob.colLower = mxGetDoubles(mprob.lb); - } - // 'ub' - if (mprob.ub != NULL) { - cprob.colUpper = mxGetDoubles(mprob.ub); - } - // 'vtype' - if (mprob.vtype != NULL) { - if (mxGetNumberOfElements(mprob.vtype) == cprob.nCol) { - COPTMEX_CALL(COPTMEX_getString(mprob.vtype, &cprob.colType)); - } else { - char *vtype = NULL; - COPTMEX_CALL(COPTMEX_getString(mprob.vtype, &vtype)); - - cprob.colType = (char *) mxCalloc(cprob.nCol + 1, sizeof(char)); - if (!cprob.colType) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - for (int i = 0; i < cprob.nCol; ++i) { - cprob.colType[i] = vtype[0]; - } - } - } - // 'varnames' - if (mprob.varnames != NULL) { - cprob.colNames = (char **) mxCalloc(cprob.nCol, sizeof(char *)); - for (int i = 0; i < cprob.nCol; ++i) { - mxArray *nameCell = mxGetCell(mprob.varnames, i); - COPTMEX_CALL(COPTMEX_getString(nameCell, &cprob.colNames[i])); - } - } - // 'sense', 'lhs' and 'rhs' - if (mprob.sense == NULL) { - cprob.rowLower = mxGetDoubles(mprob.lhs); - cprob.rowUpper = mxGetDoubles(mprob.rhs); - } else { - if (mxGetNumberOfElements(mprob.sense) == cprob.nRow) { - COPTMEX_CALL(COPTMEX_getString(mprob.sense, &cprob.rowSense)); - } else { - char *rsense = NULL; - COPTMEX_CALL(COPTMEX_getString(mprob.sense, &rsense)); - - cprob.rowSense = (char *) mxCalloc(cprob.nRow + 1, sizeof(char)); - if (!cprob.rowSense) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - for (int i = 0; i < cprob.nRow; ++i) { - cprob.rowSense[i] = rsense[0]; - } - } - - cprob.rowUpper = mxGetDoubles(mprob.rhs); - } - // 'constrnames' - if (mprob.constrnames != NULL) { - cprob.rowNames = (char **) mxCalloc(cprob.nRow, sizeof(char *)); - for (int i = 0; i < cprob.nRow; ++i) { - mxArray *namecell = mxGetCell(mprob.constrnames, i); - COPTMEX_CALL(COPTMEX_getString(namecell, &cprob.rowNames[i])); - } - } - - // Load problem data to COPT problem - if (cprob.rowSense == NULL) { - COPTMEX_CALL(COPT_LoadProb(prob, cprob.nCol, cprob.nRow, - cprob.nObjSen, cprob.dObjConst, cprob.colCost, - cprob.colMatBeg, NULL, cprob.colMatIdx, cprob.colMatElem, - cprob.colType, cprob.colLower, cprob.colUpper, - NULL, cprob.rowLower, cprob.rowUpper, - cprob.colNames, cprob.rowNames)); - } else { - COPTMEX_CALL(COPT_LoadProb(prob, cprob.nCol, cprob.nRow, - cprob.nObjSen, cprob.dObjConst, cprob.colCost, - cprob.colMatBeg, NULL, cprob.colMatIdx, cprob.colMatElem, - cprob.colType, cprob.colLower, cprob.colUpper, - cprob.rowSense, cprob.rowUpper, NULL, - cprob.colNames, cprob.rowNames)); - } - - // Extract and load the optional SOS part - if (mprob.sos != NULL) { - for (int i = 0; i < mxGetNumberOfElements(mprob.sos); ++i) { - mxArray *sostype_m = mxGetField(mprob.sos, i, COPTMEX_MODEL_SOSTYPE); - mxArray *sosvars_m = mxGetField(mprob.sos, i, COPTMEX_MODEL_SOSVARS); - mxArray *soswgts_m = mxGetField(mprob.sos, i, COPTMEX_MODEL_SOSWEIGHT); - - int sosType = (int) mxGetScalar(sostype_m); - int sosMatBeg = 0; - int sosMatCnt = (int) mxGetNumberOfElements(sosvars_m); - int *sosMatIdx = (int *) mxCalloc(sosMatCnt, sizeof(int)); - if (!sosMatIdx) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - double *sosvars_data = mxGetDoubles(sosvars_m); - for (int i = 0; i < sosMatCnt; ++i) { - sosMatIdx[i] = (int) sosvars_data[i] - 1; - } - - double *sosMatWt = NULL; - if (soswgts_m != NULL) { - sosMatWt = mxGetDoubles(soswgts_m); - } - - COPTMEX_CALL(COPT_AddSOSs(prob, 1, &sosType, &sosMatBeg, &sosMatCnt, - sosMatIdx, sosMatWt)); - - mxFree(sosMatIdx); - } - } - - // Extract and load the optional indicator part - if (mprob.indicator != NULL) { - for (int i = 0; i < mxGetNumberOfElements(mprob.indicator); ++i) { - mxArray *binVar = mxGetField(mprob.indicator, i, COPTMEX_MODEL_INDICBINVAR); - mxArray *binVal = mxGetField(mprob.indicator, i, COPTMEX_MODEL_INDICBINVAL); - mxArray *indicA = mxGetField(mprob.indicator, i, COPTMEX_MODEL_INDICROW); - mxArray *rSense = mxGetField(mprob.indicator, i, COPTMEX_MODEL_INDICSENSE); - mxArray *rowBnd = mxGetField(mprob.indicator, i, COPTMEX_MODEL_INDICRHS); - - int binColIdx = (int) mxGetScalar(binVar) - 1; - int binColVal = (int) mxGetScalar(binVal); - int nRowMatCnt = 0; - int *rowMatIdx = NULL; - double *rowMatElem = NULL; - - if (mxIsSparse(indicA)) { - nRowMatCnt = mxGetNzmax(indicA); - rowMatIdx = (int *) mxCalloc(nRowMatCnt, sizeof(int)); - if (!rowMatIdx) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - mwIndex *rowMatIdx_data = mxGetIr(indicA); - for (int i = 0; i < nRowMatCnt; ++i) { - rowMatIdx[i] = rowMatIdx_data[i]; - } - rowMatElem = mxGetDoubles(indicA); - } else { - double *rowMatElem_data = mxGetDoubles(indicA); - for (int i = 0; i < mxGetNumberOfElements(indicA); ++i) { - if (rowMatElem_data[i] != 0) { - ++nRowMatCnt; - } - } - rowMatIdx = (int *) mxCalloc(nRowMatCnt, sizeof(int)); - rowMatElem = (double *) mxCalloc(nRowMatCnt, sizeof(double)); - if (!rowMatIdx || !rowMatElem) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - for (int i = 0, iElem = 0; i < mxGetNumberOfElements(indicA); ++i) { - if (rowMatElem_data[i] != 0) { - rowMatIdx[iElem] = i; - rowMatElem[iElem] = rowMatElem_data[i]; - iElem++; - } - } - } - - char cRowSense[2]; - mxGetString(rSense, cRowSense, 2); - double dRowBound = mxGetScalar(rowBnd); - - COPTMEX_CALL(COPT_AddIndicator(prob, binColIdx, binColVal, nRowMatCnt, - rowMatIdx, rowMatElem, cRowSense[0], dRowBound)); - - mxFree(rowMatIdx); - if (!mxIsSparse(indicA)) { - mxFree(rowMatElem); - } - } - } - - // Extract and load the optional cone part - if (mprob.cone != NULL) { - for (int i = 0; i < mxGetNumberOfElements(mprob.cone); ++i) { - mxArray *conetype_m = mxGetField(mprob.cone, i, COPTMEX_MODEL_CONETYPE); - mxArray *conevars_m = mxGetField(mprob.cone, i, COPTMEX_MODEL_CONEVARS); - - int coneType = (int) mxGetScalar(conetype_m); - int coneBeg = 0; - int coneCnt = (int) mxGetNumberOfElements(conevars_m); - int *coneIdx = (int *) mxCalloc(coneCnt, sizeof(int)); - if (!coneIdx) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - double *conevars_data = mxGetDoubles(conevars_m); - for (int i = 0; i < coneCnt; ++i) { - coneIdx[i] = (int) conevars_data[i] - 1; - } - - COPTMEX_CALL(COPT_AddCones(prob, 1, &coneType, &coneBeg, &coneCnt, coneIdx)); - - mxFree(coneIdx); - } - } - - // Extract and load optional Q objective part - if (mprob.qobj != NULL) { - cprob.nQElem = mxGetNzmax(mprob.qobj); - int *qObjRow = (int *) mxCalloc(cprob.nQElem, sizeof(int)); - int *qObjCol = (int *) mxCalloc(cprob.nQElem, sizeof(int)); - double *qObjElem = (double *) mxCalloc(cprob.nQElem, sizeof(double)); - if (!qObjRow || !qObjCol || !qObjElem) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - COPTMEX_csc2coo(mprob.qobj, qObjRow, qObjCol, qObjElem); - COPTMEX_CALL(COPT_SetQuadObj(prob, cprob.nQElem, qObjRow, qObjCol, qObjElem)); - - mxFree(qObjRow); - mxFree(qObjCol); - mxFree(qObjElem); - } - - // Extract and load optional quadratic constraint part - if (mprob.quadcon != NULL) { - for (int i = 0; i < mxGetNumberOfElements(mprob.quadcon); ++i) { - mxArray *QcMat = mxGetField(mprob.quadcon, i, COPTMEX_MODEL_QCSPMAT); - mxArray *QcRow = mxGetField(mprob.quadcon, i, COPTMEX_MODEL_QCROW); - mxArray *QcCol = mxGetField(mprob.quadcon, i, COPTMEX_MODEL_QCCOL); - mxArray *QcVal = mxGetField(mprob.quadcon, i, COPTMEX_MODEL_QCVAL); - mxArray *QcLinear = mxGetField(mprob.quadcon, i, COPTMEX_MODEL_QCLINEAR); - mxArray *QcSense = mxGetField(mprob.quadcon, i, COPTMEX_MODEL_QCSENSE); - mxArray *QcRhs = mxGetField(mprob.quadcon, i, COPTMEX_MODEL_QCRHS); - mxArray *QcName = mxGetField(mprob.quadcon, i, COPTMEX_MODEL_QCNAME); - - int nQMatElem = 0; - int *qMatRow = NULL; - int *qMatCol = NULL; - double *qMatElem = NULL; - int nQRowElem = 0; - int *qRowMatIdx = NULL; - double *qRowMatElem = NULL; - char qRowSense[2]; - double qRowBound = 0.0; - char qRowName[COPT_BUFFSIZE] = {0}; - - if (QcMat != NULL) { - nQMatElem = mxGetNzmax(QcMat); - qMatRow = (int *) mxCalloc(nQMatElem, sizeof(int)); - qMatCol = (int *) mxCalloc(nQMatElem, sizeof(int)); - qMatElem = (double *) mxCalloc(nQMatElem, sizeof(double)); - if (!qMatRow || !qMatCol || !qMatElem) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - COPTMEX_csc2coo(QcMat, qMatRow, qMatCol, qMatElem); - } else { - if (QcRow != NULL && QcCol != NULL && QcVal != NULL) { - nQMatElem = mxGetNumberOfElements(QcRow); - qMatRow = (int *) mxCalloc(nQMatElem, sizeof(int)); - qMatCol = (int *) mxCalloc(nQMatElem, sizeof(int)); - if (!qMatRow || !qMatCol) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - double *qMatRow_data = mxGetDoubles(QcRow); - double *qMatCol_data = mxGetDoubles(QcCol); - qMatElem = mxGetDoubles(QcVal); - for (int i = 0; i < nQMatElem; ++i) { - qMatRow[i] = (int) qMatRow_data[i] - 1; - qMatCol[i] = (int) qMatCol_data[i] - 1; - } - } - } - - if (QcLinear != NULL) { - if (mxIsSparse(QcLinear)) { - double *qRowMatElem_data = mxGetDoubles(QcLinear); - for (int i = 0; i < mxGetNzmax(QcLinear); ++i) { - if (qRowMatElem_data[i] != 0.0) { - ++nQRowElem; - } - } - if (nQRowElem > 0) { - qRowMatIdx = (int *) mxCalloc(nQRowElem, sizeof(int)); - qRowMatElem = (double *) mxCalloc(nQRowElem, sizeof(double)); - if (!qRowMatIdx || !qRowMatElem) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - mwIndex *qRowMatIdx_data = mxGetIr(QcLinear); - for (int i = 0, iElem = 0; i < mxGetNzmax(QcLinear); ++i) { - if (qRowMatElem_data[i] != 0.0) { - qRowMatIdx[iElem] = (int) qRowMatIdx_data[i]; - qRowMatElem[iElem] = qRowMatElem_data[i]; - iElem++; - } - } - } - } else { - double *qRowMatElem_data = mxGetDoubles(QcLinear); - for (int i = 0; i < mxGetNumberOfElements(QcLinear); ++i) { - if (qRowMatElem_data[i] != 0.0) { - ++nQRowElem; - } - } - if (nQRowElem > 0) { - qRowMatIdx = (int *) mxCalloc(nQRowElem, sizeof(int)); - qRowMatElem = (double *) mxCalloc(nQRowElem, sizeof(double)); - if (!qRowMatIdx || !qRowMatElem) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - for (int i = 0, iElem = 0; i < mxGetNumberOfElements(QcLinear); ++i) { - if (qRowMatElem_data[i] != 0.0) { - qRowMatIdx[iElem] = i; - qRowMatElem[iElem] = qRowMatElem_data[i]; - iElem++; - } - } - } - } - } - - if (QcSense != NULL) { - mxGetString(QcSense, qRowSense, 2); - } else { - qRowSense[0] = COPT_LESS_EQUAL; - } - qRowBound = mxGetScalar(QcRhs); - if (QcName != NULL) { - mxGetString(QcName, qRowName, COPT_BUFFSIZE); - } - - COPTMEX_CALL(COPT_AddQConstr(prob, nQRowElem, qRowMatIdx, qRowMatElem, - nQMatElem, qMatRow, qMatCol, qMatElem, qRowSense[0], qRowBound, - qRowName)); - - mxFree(qMatRow); - mxFree(qMatCol); - if (QcMat != NULL) { - mxFree(qMatElem); - } - - if (nQRowElem > 0) { - mxFree(qRowMatIdx); - mxFree(qRowMatElem); - } - } - } - - // Extract and load the optional advanced information - if (mprob.varbasis != NULL && mprob.constrbasis != NULL) { - cprob.colBasis = (int *) mxCalloc(cprob.nCol, sizeof(int)); - cprob.rowBasis = (int *) mxCalloc(cprob.nRow, sizeof(int)); - if (!cprob.colBasis || !cprob.rowBasis) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - double *colBasis_data = mxGetDoubles(mprob.varbasis); - double *rowBasis_data = mxGetDoubles(mprob.constrbasis); - for (int i = 0; i < cprob.nCol; ++i) { - cprob.colBasis[i] = (int) colBasis_data[i]; - } - for (int i = 0; i < cprob.nRow; ++i) { - cprob.rowBasis[i] = (int) rowBasis_data[i]; - } - - COPTMEX_CALL(COPT_SetBasis(prob, cprob.colBasis, cprob.rowBasis)); - - mxFree(cprob.colBasis); - mxFree(cprob.rowBasis); - } - - if (mprob.value != NULL && mprob.slack != NULL && mprob.dual != NULL && mprob.redcost != NULL) { - double *colValue = mxGetDoubles(mprob.value); - double *colDual = mxGetDoubles(mprob.redcost); - double *rowSlack = mxGetDoubles(mprob.slack); - double *rowDual = mxGetDoubles(mprob.dual); - - COPTMEX_CALL(COPT_SetLpSolution(prob, colValue, rowSlack, rowDual, colDual)); - } - - if (mprob.mipstart != NULL) { - int nRowCnt = 0; - int *rowIdx = NULL; - double *rowElem = NULL; - - if (mxIsSparse(mprob.mipstart)) { - nRowCnt = mxGetNzmax(mprob.mipstart); - rowIdx = (int *) mxCalloc(nRowCnt, sizeof(int)); - if (!rowIdx) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - mwIndex *rowIdx_data = mxGetIr(mprob.mipstart); - for (int i = 0; i < nRowCnt; ++i) { - rowIdx[i] = rowIdx_data[i]; - } - rowElem = mxGetDoubles(mprob.mipstart); - - COPTMEX_CALL(COPT_AddMipStart(prob, nRowCnt, rowIdx, rowElem)); - - mxFree(rowIdx); - } else { - double *rowElem_data = mxGetDoubles(mprob.mipstart); - - nRowCnt = mxGetNumberOfElements(mprob.mipstart); - rowElem = (double *) mxCalloc(nRowCnt, sizeof(double)); - if (!rowElem) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - for (int i = 0; i < nRowCnt; ++i) { - if (mxIsNaN(rowElem_data[i])) { - rowElem[i] = COPT_UNDEFINED; - } else { - rowElem[i] = rowElem_data[i]; - } - } - - COPTMEX_CALL(COPT_AddMipStart(prob, nRowCnt, NULL, rowElem)); - - mxFree(rowElem); - } - } - -exit_cleanup: - return retcode; -} - -/* Extract IIS information */ -static int COPTMEX_getIIS(copt_prob *prob, mxArray **out_iis) { - int retcode = COPT_RETCODE_OK; - int nRow = 0, nCol = 0, nSos = 0, nIndicator = 0; - int hasIIS = 0; - int isMinIIS = 0; - mxArray *iisInfo = NULL; - coptmex_ciisinfo ciisinfo; - coptmex_miisinfo miisinfo; - - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_HASIIS, &hasIIS)); - if (hasIIS == 0) { - *out_iis = NULL; - goto exit_cleanup; - } - - COPTMEX_initCIISInfo(&ciisinfo); - COPTMEX_initMIISInfo(&miisinfo); - - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_ROWS, &nRow)); - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_COLS, &nCol)); - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_SOSS, &nSos)); - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_INDICATORS, &nIndicator)); - - miisinfo.isminiis = mxCreateDoubleMatrix(1, 1, mxREAL); - if (!miisinfo.isminiis) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - if (nCol > 0) { - miisinfo.varlb = mxCreateLogicalMatrix(nCol, 1); - miisinfo.varub = mxCreateLogicalMatrix(nCol, 1); - if (!miisinfo.varlb || !miisinfo.varub) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - } - - if (nRow > 0) { - miisinfo.constrlb = mxCreateLogicalMatrix(nRow, 1); - miisinfo.construb = mxCreateLogicalMatrix(nRow, 1); - if (!miisinfo.constrlb || !miisinfo.construb) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - } - - if (nSos > 0) { - miisinfo.sos = mxCreateLogicalMatrix(nSos, 1); - if (!miisinfo.sos) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - } - - if (nIndicator > 0) { - miisinfo.indicator = mxCreateLogicalMatrix(nIndicator, 1); - if (!miisinfo.indicator) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - } - - if (nCol > 0) { - ciisinfo.colLowerIIS = (int *) mxCalloc(nCol, sizeof(int)); - ciisinfo.colUpperIIS = (int *) mxCalloc(nCol, sizeof(int)); - if (!ciisinfo.colLowerIIS || !ciisinfo.colUpperIIS) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - } - - if (nRow > 0) { - ciisinfo.rowLowerIIS = (int *) mxCalloc(nRow, sizeof(int)); - ciisinfo.rowUpperIIS = (int *) mxCalloc(nRow, sizeof(int)); - if (!ciisinfo.rowLowerIIS || !ciisinfo.rowUpperIIS) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - } - - if (nSos > 0) { - ciisinfo.sosIIS = (int *) mxCalloc(nSos, sizeof(int)); - if (!ciisinfo.sosIIS) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - } - - if (nIndicator > 0) { - ciisinfo.indicatorIIS = (int *) mxCalloc(nIndicator, sizeof(int)); - if (!ciisinfo.indicatorIIS) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - } - - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_ISMINIIS, &isMinIIS)); - - if (nCol > 0) { - COPTMEX_CALL(COPT_GetColLowerIIS(prob, nCol, NULL, ciisinfo.colLowerIIS)); - COPTMEX_CALL(COPT_GetColUpperIIS(prob, nCol, NULL, ciisinfo.colUpperIIS)); - } - - if (nRow > 0) { - COPTMEX_CALL(COPT_GetRowLowerIIS(prob, nRow, NULL, ciisinfo.rowLowerIIS)); - COPTMEX_CALL(COPT_GetRowUpperIIS(prob, nRow, NULL, ciisinfo.rowUpperIIS)); - } - - if (nSos > 0) { - COPTMEX_CALL(COPT_GetSOSIIS(prob, nSos, NULL, ciisinfo.sosIIS)); - } - - if (nIndicator > 0) { - COPTMEX_CALL(COPT_GetIndicatorIIS(prob, nIndicator, NULL, ciisinfo.indicatorIIS)); - } - - *mxGetDoubles(miisinfo.isminiis) = isMinIIS; - - if (nCol > 0) { - mxLogical *colLowerIIS_data = mxGetLogicals(miisinfo.varlb); - mxLogical *colUpperIIS_data = mxGetLogicals(miisinfo.varub); - for (int i = 0; i < nCol; ++i) { - colLowerIIS_data[i] = ciisinfo.colLowerIIS[i]; - colUpperIIS_data[i] = ciisinfo.colUpperIIS[i]; - } - mxFree(ciisinfo.colLowerIIS); - mxFree(ciisinfo.colUpperIIS); - } - - if (nRow > 0) { - mxLogical *rowLowerIIS_data = mxGetLogicals(miisinfo.constrlb); - mxLogical *rowUpperIIS_data = mxGetLogicals(miisinfo.construb); - for (int i = 0; i < nRow; ++i) { - rowLowerIIS_data[i] = ciisinfo.rowLowerIIS[i]; - rowUpperIIS_data[i] = ciisinfo.rowUpperIIS[i]; - } - mxFree(ciisinfo.rowLowerIIS); - mxFree(ciisinfo.rowUpperIIS); - } - - if (nSos > 0) { - mxLogical *sosIIS_data = mxGetLogicals(miisinfo.sos); - for (int i = 0; i < nSos; ++i) { - sosIIS_data[i] = ciisinfo.sosIIS[i]; - } - mxFree(ciisinfo.sosIIS); - } - - if (nIndicator > 0) { - mxLogical *indicatorIIS_data = mxGetLogicals(miisinfo.indicator); - for (int i = 0; i < nIndicator; ++i) { - indicatorIIS_data[i] = ciisinfo.indicatorIIS[i]; - } - mxFree(ciisinfo.indicatorIIS); - } - - iisInfo = mxCreateStructMatrix(1, 1, 0, NULL); - if (!iisInfo) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - // 'isminiis' - mxAddField(iisInfo, COPTMEX_IIS_ISMINIIS); - mxSetField(iisInfo, 0, COPTMEX_IIS_ISMINIIS, miisinfo.isminiis); - - if (nCol > 0) { - // 'varlb' - mxAddField(iisInfo, COPTMEX_IIS_VARLB); - mxSetField(iisInfo, 0, COPTMEX_IIS_VARLB, miisinfo.varlb); - // 'varub' - mxAddField(iisInfo, COPTMEX_IIS_VARUB); - mxSetField(iisInfo, 0, COPTMEX_IIS_VARUB, miisinfo.varub); - } - - if (nRow > 0) { - // 'constrlb' - mxAddField(iisInfo, COPTMEX_IIS_CONSTRLB); - mxSetField(iisInfo, 0, COPTMEX_IIS_CONSTRLB, miisinfo.constrlb); - // 'construb' - mxAddField(iisInfo, COPTMEX_IIS_CONSTRUB); - mxSetField(iisInfo, 0, COPTMEX_IIS_CONSTRUB, miisinfo.construb); - } - - if (nSos > 0) { - // 'sos' - mxAddField(iisInfo, COPTMEX_IIS_SOS); - mxSetField(iisInfo, 0, COPTMEX_IIS_SOS, miisinfo.sos); - } - - if (nIndicator > 0) { - // 'indicator' - mxAddField(iisInfo, COPTMEX_IIS_INDICATOR); - mxSetField(iisInfo, 0, COPTMEX_IIS_INDICATOR, miisinfo.indicator); - } - - // Write out IIS problem - COPTMEX_CALL(COPT_WriteIIS(prob, "result.iis")); - - *out_iis = iisInfo; - -exit_cleanup: - if (retcode != COPT_RETCODE_OK) { - *out_iis = NULL; - } - - return retcode; -} - -/* Compute IIS for infeasible problem */ -int COPTMEX_computeIIS(copt_prob *prob, mxArray **out_iis, int ifRetResult) { - int retcode = COPT_RETCODE_OK; - int modelStatus = 0; - int isMIP = 0; - - // Try to find IIS for the given problem - COPTMEX_CALL(COPT_ComputeIIS(prob)); - - // Extract IIS information - if (ifRetResult == 1) { - COPTMEX_CALL(COPTMEX_getIIS(prob, out_iis)); - } - -exit_cleanup: - return retcode; -} - -/* Extract feasibility relaxation information */ -static int COPTMEX_getFeasRelax(copt_prob *prob, mxArray **out_relax) { - int retcode = COPT_RETCODE_OK; - int nRow = 0, nCol = 0; - int hasFeasRelax = 0; - mxArray *relaxInfo = NULL; - coptmex_crelaxinfo crelaxinfo; - coptmex_mrelaxinfo mrelaxinfo; - - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_HASFEASRELAXSOL, &hasFeasRelax)); - if (hasFeasRelax == 0) { - *out_relax = NULL; - goto exit_cleanup; - } - - COPTMEX_initCRelaxInfo(&crelaxinfo); - COPTMEX_initMRelaxInfo(&mrelaxinfo); - - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_ROWS, &nRow)); - COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_COLS, &nCol)); - - mrelaxinfo.relaxobj = mxCreateDoubleMatrix(1, 1, mxREAL); - if (!mrelaxinfo.relaxobj) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - if (nCol > 0) { - mrelaxinfo.relaxvalue = mxCreateDoubleMatrix(nCol, 1, mxREAL); - mrelaxinfo.relaxlb = mxCreateDoubleMatrix(nCol, 1, mxREAL); - mrelaxinfo.relaxub = mxCreateDoubleMatrix(nCol, 1, mxREAL); - if (!mrelaxinfo.relaxvalue || !mrelaxinfo.relaxlb || !mrelaxinfo.relaxub) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - } - - if (nRow > 0) { - mrelaxinfo.relaxlhs = mxCreateDoubleMatrix(nRow, 1, mxREAL); - mrelaxinfo.relaxrhs = mxCreateDoubleMatrix(nRow, 1, mxREAL); - if (!mrelaxinfo.relaxlhs || !mrelaxinfo.relaxrhs) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - } - - if (nCol > 0) { - crelaxinfo.colValue = mxGetDoubles(mrelaxinfo.relaxvalue); - crelaxinfo.colLowRlx = mxGetDoubles(mrelaxinfo.relaxlb); - crelaxinfo.colUppRlx = mxGetDoubles(mrelaxinfo.relaxub); - } - - if (nRow > 0) { - crelaxinfo.rowLowRlx = mxGetDoubles(mrelaxinfo.relaxlhs); - crelaxinfo.rowUppRlx = mxGetDoubles(mrelaxinfo.relaxrhs); - } - - COPTMEX_CALL(COPT_GetDblAttr(prob, COPT_DBLATTR_FEASRELAXOBJ, &crelaxinfo.dObjVal)); - *mxGetDoubles(mrelaxinfo.relaxobj) = crelaxinfo.dObjVal; - - if (nCol > 0) { - COPTMEX_CALL(COPT_GetColInfo(prob, COPT_DBLINFO_RELAXVALUE, nCol, NULL, crelaxinfo.colValue)); - COPTMEX_CALL(COPT_GetColInfo(prob, COPT_DBLINFO_RELAXLB, nCol, NULL, crelaxinfo.colLowRlx)); - COPTMEX_CALL(COPT_GetColInfo(prob, COPT_DBLINFO_RELAXUB, nCol, NULL, crelaxinfo.colUppRlx)); - } - - if (nRow > 0) { - COPTMEX_CALL(COPT_GetRowInfo(prob, COPT_DBLINFO_RELAXLB, nRow, NULL, crelaxinfo.rowLowRlx)); - COPTMEX_CALL(COPT_GetRowInfo(prob, COPT_DBLINFO_RELAXUB, nRow, NULL, crelaxinfo.rowUppRlx)); - } - - relaxInfo = mxCreateStructMatrix(1, 1, 0, NULL); - if (!relaxInfo) { - retcode = COPT_RETCODE_MEMORY; - goto exit_cleanup; - } - - // 'relaxobj' - mxAddField(relaxInfo, COPTMEX_FEASRELAX_OBJ); - mxSetField(relaxInfo, 0, COPTMEX_FEASRELAX_OBJ, mrelaxinfo.relaxobj); - - if (nCol > 0) { - // 'relaxvalue' - mxAddField(relaxInfo, COPTMEX_FEASRELAX_VALUE); - mxSetField(relaxInfo, 0, COPTMEX_FEASRELAX_VALUE, mrelaxinfo.relaxvalue); - // 'relaxlb' - mxAddField(relaxInfo, COPTMEX_FEASRELAX_LB); - mxSetField(relaxInfo, 0, COPTMEX_FEASRELAX_LB, mrelaxinfo.relaxlb); - // 'relaxub' - mxAddField(relaxInfo, COPTMEX_FEASRELAX_UB); - mxSetField(relaxInfo, 0, COPTMEX_FEASRELAX_UB, mrelaxinfo.relaxub); - } - - if (nRow > 0) { - // 'relaxlhs' - mxAddField(relaxInfo, COPTMEX_FEASRELAX_LHS); - mxSetField(relaxInfo, 0, COPTMEX_FEASRELAX_LHS, mrelaxinfo.relaxlhs); - // 'relaxrhs' - mxAddField(relaxInfo, COPTMEX_FEASRELAX_RHS); - mxSetField(relaxInfo, 0, COPTMEX_FEASRELAX_RHS, mrelaxinfo.relaxrhs); - } - - // Write out feasibility relaxation problem - COPTMEX_CALL(COPT_WriteRelax(prob, "result.relax")); - - *out_relax = relaxInfo; - -exit_cleanup: - if (retcode != COPT_RETCODE_OK) { - *out_relax = NULL; - } - - return retcode; -} - -int COPTMEX_feasRelax(copt_prob *prob, const mxArray *penalty, mxArray **out_relax, int ifRetResult) { - int retcode = COPT_RETCODE_OK; - - mxArray *lbpen = NULL; - mxArray *ubpen = NULL; - mxArray *rhspen = NULL; - mxArray *upppen = NULL; - - double *colLowPen = NULL; - double *colUppPen = NULL; - double *rowBndPen = NULL; - double *rowUppPen = NULL; - - if (COPTMEX_checkPenalty(prob, penalty) == 0) { - goto exit_cleanup; - } - - lbpen = mxGetField(penalty, 0, COPTMEX_PENALTY_LBPEN); - ubpen = mxGetField(penalty, 0, COPTMEX_PENALTY_UBPEN); - rhspen = mxGetField(penalty, 0, COPTMEX_PENALTY_RHSPEN); - upppen = mxGetField(penalty, 0, COPTMEX_PENALTY_UPPPEN); - - if (lbpen != NULL) { - colLowPen = mxGetDoubles(lbpen); - } - if (ubpen != NULL) { - colUppPen = mxGetDoubles(ubpen); - } - if (rhspen != NULL) { - rowBndPen = mxGetDoubles(rhspen); - } - if (upppen != NULL) { - rowUppPen = mxGetDoubles(upppen); - } - - // Compute the feasibility relaxation - COPTMEX_CALL(COPT_FeasRelax(prob, colLowPen, colUppPen, rowBndPen, rowUppPen)); - - // Extract feasibility relaxation information - if (ifRetResult == 1) { - COPTMEX_CALL(COPTMEX_getFeasRelax(prob, out_relax)); - } - -exit_cleanup: - return retcode; -} +#include "coptmex.h" + +/* Uncomment the following line for use with legacy MEX APIs */ +// #define COPTMEX_USE_LEGACYMEX +#ifdef COPTMEX_USE_LEGACYMEX +#define mxGetDoubles mxGetPr +#endif + +extern int COPT_SearchParamAttr(copt_prob* prob, const char* name, int* p_type); + +extern int +COPT_GetPSDSolution(copt_prob* prob, double* psdColValue, double* psdRowSlack, double* psdRowDual, double* psdColDual); + +extern int COPT_LoadConeProb(copt_prob* prob, + int nCol, + int nRow, + int nFree, + int nPositive, + int nBox, + int nCone, + int nRotateCone, + int nPrimalExp, + int nDualExp, + int nPrimalPow, + int nDualPow, + int nPSD, + int nQObjElem, + int iObjSense, + double dObjConst, + const double* colObj, + const int* qObjRow, + const int* qObjCol, + const double* qObjElem, + const int* colMatBeg, + const int* colMatCnt, + const int* colMatIdx, + const double* colMatElem, + const double* rowRhs, + const double* boxLower, + const double* boxUpper, + const int* coneDim, + const int* rotateConeDim, + const int* primalPowDim, + const int* dualPowDim, + const double* primalPowAlpha, + const double* dualPowAlpha, + const int* psdDim, + const char* colType, + char const* const* colNames, + char const* const* rowNames, + char const* const* psdColNames, + int* outRowMap); + +/* Convert status code from integer to string */ +static const char* COPTMEX_statusInt2Str(int status) +{ + switch (status) + { + case 0: // unstarted + return COPTMEX_STATUS_UNSTARTED; + case 1: // optimal + return COPTMEX_STATUS_OPTIMAL; + case 2: // infeasible + return COPTMEX_STATUS_INFEASIBLE; + case 3: // unbounded + return COPTMEX_STATUS_UNBOUNDED; + case 4: // inf_or_unb + return COPTMEX_STATUS_INF_OF_UNB; + case 5: // numerical + return COPTMEX_STATUS_NUMERICAL; + case 6: // nodelimit + return COPTMEX_STATUS_NODELIMIT; + case 8: // timeout + return COPTMEX_STATUS_TIMEOUT; + case 9: // unfinished + return COPTMEX_STATUS_UNFINISHED; + case 10: // interrupted + return COPTMEX_STATUS_INTERRUPTED; + default: // unknown + return "unknown"; + } +} + +/* Convert objective sense from string to integer */ +static int COPTMEX_objsenStr2Int(char* objsen) +{ + if (mystrcmp(objsen, "max") == 0 || mystrcmp(objsen, "maximize") == 0) + { + return COPT_MAXIMIZE; + } + return COPT_MINIMIZE; +} + +/* Convert objective sense from integer to string */ +static const char* COPTMEX_objsenInt2Str(int objsen) +{ + if (objsen == COPT_MAXIMIZE) + { + return "max"; + } + return "min"; +} + +/* Extract string from MEX */ +static int COPTMEX_getString(const mxArray* in_array, char** out_str) +{ + int retcode = 0; + + int bufflen = mxGetNumberOfElements(in_array) + 1; + char* buffer = (char*)mxCalloc(bufflen, sizeof(char)); + if (!buffer) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + mxGetString(in_array, buffer, bufflen); + *out_str = buffer; + +exit_cleanup: + return retcode; +} + +/* Free string allocated by MEX */ +static void COPTMEX_freeString(char** in_str) +{ + if (in_str != NULL && *in_str != NULL) + { + mxFree(*in_str); + } + return; +} + +/* Display error message */ +void COPTMEX_errorMsg(int errcode, const char* errinfo) +{ + char* errid = NULL; + char* errtxt = NULL; + + switch (errcode) + { + case COPTMEX_ERROR_BAD_TYPE: + errid = "coptmex:BadType"; + errtxt = "Invalid type of '%s'."; + break; + case COPTMEX_ERROR_BAD_NAME: + errid = "coptmex:BadName"; + errtxt = "Invalid name of '%s'."; + break; + case COPTMEX_ERROR_BAD_DATA: + errid = "coptmex:BadData"; + errtxt = "Invalid data of '%s'."; + break; + case COPTMEX_ERROR_BAD_NUM: + errid = "coptmex:BadNum"; + errtxt = "Invalid number of elemtents in '%s'."; + break; + case COPTMEX_ERROR_BAD_API: + errid = "coptmex:BadAPI"; + errtxt = "%s."; + break; + default: + return; + } + + mexErrMsgIdAndTxt(errid, errtxt, errinfo); +} + +/* Convert CSC matrix to COO matrix */ +void COPTMEX_csc2coo(mxArray* q, int* qMatRow, int* qMatCol, double* qMatElem) +{ + int ncol = mxGetN(q); + mwIndex* jc = mxGetJc(q); + mwIndex* ir = mxGetIr(q); + double* val = mxGetDoubles(q); + + for (int i = 0; i < ncol; ++i) + { + int nColElem = (int)jc[i]; + int nColLast = (int)jc[i + 1]; + for (; nColElem < nColLast; ++nColElem) + { + qMatRow[nColElem] = (int)ir[nColElem]; + qMatCol[nColElem] = i; + qMatElem[nColElem] = val[nColElem]; + } + } + + return; +} + +/* Convert COO matrix to CSC matrix */ +int COPTMEX_coo2csc(int nQElem, int* qMatRow, int* qMatCol, double* qMatElem, mxArray* q) +{ + int ncol = mxGetN(q); + mwIndex* jc = mxGetJc(q); + mwIndex* ir = mxGetIr(q); + double* val = mxGetDoubles(q); + + int* colMatCnt = (int*)mxCalloc(ncol, sizeof(int)); + if (!colMatCnt) + { + return COPT_RETCODE_MEMORY; + } + + for (int i = 0; i < nQElem; ++i) + { + colMatCnt[qMatCol[i]]++; + } + + jc[0] = 0; + for (int i = 1; i <= ncol; ++i) + { + jc[i] = jc[i - 1] + colMatCnt[i - 1]; + } + + for (int i = 0; i < nQElem; ++i) + { + int iCol = qMatCol[i]; + int iElem = (int)jc[iCol]; + + ir[iElem] = qMatRow[i]; + val[iElem] = qMatElem[i]; + + jc[iCol]++; + } + + for (int i = 0, last = 0; i <= ncol; ++i) + { + int tmp = jc[i]; + jc[i] = last; + last = tmp; + } + + mxFree(colMatCnt); + return COPT_RETCODE_OK; +} + +#include "coptinit.c" + +/* Display banner */ +int COPTMEX_dispBanner(void) +{ + int retcode = 0; + char msgbuf[COPT_BUFFSIZE]; + + COPTMEX_CALL(COPT_GetBanner(msgbuf, COPT_BUFFSIZE)); + mexPrintf("%s", msgbuf); + +exit_cleanup: + return retcode; +} + +/* Extract version of COPT */ +int COPTMEX_getVersion(mxArray** out_version) +{ + int retcode = COPT_RETCODE_OK; + mxArray* retver = NULL; + coptmex_mversion coptver; + + COPTMEX_initVersion(&coptver); + + coptver.major = mxCreateDoubleMatrix(1, 1, mxREAL); + coptver.minor = mxCreateDoubleMatrix(1, 1, mxREAL); + coptver.technical = mxCreateDoubleMatrix(1, 1, mxREAL); + if (!coptver.major || !coptver.minor || !coptver.technical) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + *mxGetDoubles(coptver.major) = COPT_VERSION_MAJOR; + *mxGetDoubles(coptver.minor) = COPT_VERSION_MINOR; + *mxGetDoubles(coptver.technical) = COPT_VERSION_TECHNICAL; + + retver = mxCreateStructMatrix(1, 1, 0, NULL); + if (!retver) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + // 'major' + mxAddField(retver, COPTMEX_VERSION_MAJOR); + mxSetField(retver, 0, COPTMEX_VERSION_MAJOR, coptver.major); + // 'minor' + mxAddField(retver, COPTMEX_VERSION_MINOR); + mxSetField(retver, 0, COPTMEX_VERSION_MINOR, coptver.minor); + // 'technical' + mxAddField(retver, COPTMEX_VERSION_TECHNICAL); + mxSetField(retver, 0, COPTMEX_VERSION_TECHNICAL, coptver.technical); + + *out_version = retver; + +exit_cleanup: + if (retcode != COPT_RETCODE_OK) + { + *out_version = NULL; + } + + return retcode; +} + +/* Extract objective sense */ +int COPTMEX_getObjsen(const mxArray* in_objsen, int* out_objsen) +{ + int retcode = COPT_RETCODE_OK; + char* objsen = NULL; + + COPTMEX_CALL(COPTMEX_getString(in_objsen, &objsen)); + *out_objsen = COPTMEX_objsenStr2Int(objsen); + +exit_cleanup: + COPTMEX_freeString(&objsen); + return retcode; +} + +/* Extract LP solution */ +static int COPTMEX_getLpResult(copt_prob* prob, mxArray** out_lpresult) +{ + int retcode = COPT_RETCODE_OK; + mxArray* lpResult = NULL; + coptmex_clpsol csol; + coptmex_mlpsol msol; + + COPTMEX_initCLpSol(&csol); + COPTMEX_initMLpSol(&msol); + + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_ROWS, &csol.nRow)); + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_COLS, &csol.nCol)); + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_PSDCOLS, &csol.nPSD)); + COPTMEX_CALL(COPT_GetIntAttr(prob, "PSDLens", &csol.nPSDLen)); + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_PSDCONSTRS, &csol.nPSDConstr)); + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_QCONSTRS, &csol.nQConstr)); + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_LPSTATUS, &csol.nStatus)); + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_HASBASIS, &csol.hasBasis)); + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_HASLPSOL, &csol.hasLpSol)); + + msol.status = mxCreateString(COPTMEX_statusInt2Str(csol.nStatus)); + msol.simplexiter = mxCreateDoubleMatrix(1, 1, mxREAL); + msol.barrieriter = mxCreateDoubleMatrix(1, 1, mxREAL); + msol.solvingtime = mxCreateDoubleMatrix(1, 1, mxREAL); + if (!msol.status || !msol.simplexiter || !msol.barrieriter || !msol.solvingtime) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + if (csol.hasLpSol) + { + msol.objval = mxCreateDoubleMatrix(1, 1, mxREAL); + msol.value = mxCreateDoubleMatrix(csol.nCol, 1, mxREAL); + msol.redcost = mxCreateDoubleMatrix(csol.nCol, 1, mxREAL); + msol.slack = mxCreateDoubleMatrix(csol.nRow, 1, mxREAL); + msol.dual = mxCreateDoubleMatrix(csol.nRow, 1, mxREAL); + if (!msol.objval || !msol.value || !msol.redcost || !msol.slack || !msol.dual) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + csol.colValue = mxGetDoubles(msol.value); + csol.colDual = mxGetDoubles(msol.redcost); + csol.rowSlack = mxGetDoubles(msol.slack); + csol.rowDual = mxGetDoubles(msol.dual); + + if (csol.nQConstr > 0) + { + msol.qcslack = mxCreateDoubleMatrix(csol.nQConstr, 1, mxREAL); + if (!msol.qcslack) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + csol.qRowSlack = mxGetDoubles(msol.qcslack); + } + + if (csol.nPSD > 0) + { + msol.psdcolvalue = mxCreateDoubleMatrix(csol.nPSDLen, 1, mxREAL); + msol.psdcoldual = mxCreateDoubleMatrix(csol.nPSDLen, 1, mxREAL); + if (!msol.psdcolvalue || !msol.psdcoldual) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + csol.psdColValue = mxGetDoubles(msol.psdcolvalue); + csol.psdColDual = mxGetDoubles(msol.psdcoldual); + } + + if (csol.nPSDConstr > 0) + { + msol.psdrowslack = mxCreateDoubleMatrix(csol.nPSDConstr, 1, mxREAL); + msol.psdrowdual = mxCreateDoubleMatrix(csol.nPSDConstr, 1, mxREAL); + if (!msol.psdrowslack || !msol.psdrowdual) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + csol.psdRowSlack = mxGetDoubles(msol.psdrowslack); + csol.psdRowDual = mxGetDoubles(msol.psdrowdual); + } + } + + if (csol.nStatus == COPT_LPSTATUS_INFEASIBLE || csol.nStatus == COPT_LPSTATUS_UNBOUNDED) + { + int iReqFarkasRay = 0; + COPTMEX_CALL(COPT_GetIntParam(prob, COPT_INTPARAM_REQFARKASRAY, &iReqFarkasRay)); + + if (iReqFarkasRay) + { + if (csol.nStatus == COPT_LPSTATUS_INFEASIBLE) + { + msol.farkas = mxCreateDoubleMatrix(csol.nRow, 1, mxREAL); + if (!msol.farkas) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + csol.dualFarkas = mxGetDoubles(msol.farkas); + } + + if (csol.nStatus == COPT_LPSTATUS_UNBOUNDED) + { + msol.ray = mxCreateDoubleMatrix(csol.nCol, 1, mxREAL); + if (!msol.ray) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + csol.primalRay = mxGetDoubles(msol.ray); + } + } + } + + if (csol.hasBasis) + { + msol.varbasis = mxCreateDoubleMatrix(csol.nCol, 1, mxREAL); + msol.constrbasis = mxCreateDoubleMatrix(csol.nRow, 1, mxREAL); + if (!msol.varbasis || !msol.constrbasis) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + csol.colBasis = (int*)mxCalloc(csol.nCol, sizeof(int)); + csol.rowBasis = (int*)mxCalloc(csol.nRow, sizeof(int)); + if (!csol.colBasis || !csol.rowBasis) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + } + + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_SIMPLEXITER, &csol.nSimplexIter)); + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_BARRIERITER, &csol.nBarrierIter)); + COPTMEX_CALL(COPT_GetDblAttr(prob, COPT_DBLATTR_SOLVINGTIME, &csol.dSolvingTime)); + + if (csol.hasLpSol) + { + COPTMEX_CALL(COPT_GetDblAttr(prob, COPT_DBLATTR_LPOBJVAL, &csol.dObjVal)); + COPTMEX_CALL(COPT_GetLpSolution(prob, csol.colValue, csol.rowSlack, csol.rowDual, csol.colDual)); + + if (csol.nQConstr > 0) + { + COPTMEX_CALL(COPT_GetQConstrInfo(prob, COPT_DBLINFO_SLACK, csol.nQConstr, NULL, csol.qRowSlack)); + } + + if (csol.nPSD > 0) + { + COPTMEX_CALL(COPT_GetPSDSolution(prob, csol.psdColValue, NULL, NULL, csol.psdColDual)); + } + + if (csol.nPSDConstr > 0) + { + COPTMEX_CALL(COPT_GetPSDSolution(prob, NULL, csol.psdRowSlack, csol.psdRowDual, NULL)); + } + } + + if (csol.dualFarkas != NULL) + { + COPTMEX_CALL(COPT_GetRowInfo(prob, COPT_DBLINFO_DUALFARKAS, csol.nRow, NULL, csol.dualFarkas)); + } + + if (csol.primalRay != NULL) + { + COPTMEX_CALL(COPT_GetColInfo(prob, COPT_DBLINFO_PRIMALRAY, csol.nCol, NULL, csol.primalRay)); + } + + if (csol.hasBasis) + { + COPTMEX_CALL(COPT_GetBasis(prob, csol.colBasis, csol.rowBasis)); + } + + *mxGetDoubles(msol.simplexiter) = csol.nSimplexIter; + *mxGetDoubles(msol.barrieriter) = csol.nBarrierIter; + *mxGetDoubles(msol.solvingtime) = csol.dSolvingTime; + + if (csol.hasLpSol) + { + *mxGetDoubles(msol.objval) = csol.dObjVal; + } + + if (csol.hasBasis) + { + double* colBasis_data = mxGetDoubles(msol.varbasis); + double* rowBasis_data = mxGetDoubles(msol.constrbasis); + for (int i = 0; i < csol.nCol; ++i) + { + colBasis_data[i] = csol.colBasis[i]; + } + for (int i = 0; i < csol.nRow; ++i) + { + rowBasis_data[i] = csol.rowBasis[i]; + } + + mxFree(csol.colBasis); + mxFree(csol.rowBasis); + } + + lpResult = mxCreateStructMatrix(1, 1, 0, NULL); + if (!lpResult) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + // 'status' + mxAddField(lpResult, COPTMEX_RESULT_STATUS); + mxSetField(lpResult, 0, COPTMEX_RESULT_STATUS, msol.status); + // 'simplexiter' + mxAddField(lpResult, COPTMEX_RESULT_SIMITER); + mxSetField(lpResult, 0, COPTMEX_RESULT_SIMITER, msol.simplexiter); + // 'barrieriter' + mxAddField(lpResult, COPTMEX_RESULT_BARITER); + mxSetField(lpResult, 0, COPTMEX_RESULT_BARITER, msol.barrieriter); + // 'solvingtime' + mxAddField(lpResult, COPTMEX_RESULT_SOLVETIME); + mxSetField(lpResult, 0, COPTMEX_RESULT_SOLVETIME, msol.solvingtime); + + if (csol.hasLpSol) + { + // 'objval' + mxAddField(lpResult, COPTMEX_RESULT_OBJVAL); + mxSetField(lpResult, 0, COPTMEX_RESULT_OBJVAL, msol.objval); + // 'x' + mxAddField(lpResult, COPTMEX_RESULT_VALUE); + mxSetField(lpResult, 0, COPTMEX_RESULT_VALUE, msol.value); + // 'rc' + mxAddField(lpResult, COPTMEX_RESULT_REDCOST); + mxSetField(lpResult, 0, COPTMEX_RESULT_REDCOST, msol.redcost); + // 'slack; + mxAddField(lpResult, COPTMEX_RESULT_SLACK); + mxSetField(lpResult, 0, COPTMEX_RESULT_SLACK, msol.slack); + // 'pi' + mxAddField(lpResult, COPTMEX_RESULT_DUAL); + mxSetField(lpResult, 0, COPTMEX_RESULT_DUAL, msol.dual); + + // 'qcslack' + if (csol.nQConstr > 0) + { + mxAddField(lpResult, COPTMEX_RESULT_QCSLACK); + mxSetField(lpResult, 0, COPTMEX_RESULT_QCSLACK, msol.qcslack); + } + + if (csol.nPSD > 0) + { + // 'psdx' + mxAddField(lpResult, COPTMEX_RESULT_PSDX); + mxSetField(lpResult, 0, COPTMEX_RESULT_PSDX, msol.psdcolvalue); + + // 'psdrc' + mxAddField(lpResult, COPTMEX_RESULT_PSDRC); + mxSetField(lpResult, 0, COPTMEX_RESULT_PSDRC, msol.psdcoldual); + } + + if (csol.nPSDConstr > 0) + { + // 'psdslack' + mxAddField(lpResult, COPTMEX_RESULT_PSDSLACK); + mxSetField(lpResult, 0, COPTMEX_RESULT_PSDSLACK, msol.psdrowslack); + + // 'psdpi' + mxAddField(lpResult, COPTMEX_RESULT_PSDPI); + mxSetField(lpResult, 0, COPTMEX_RESULT_PSDPI, msol.psdrowdual); + } + } + + if (msol.farkas != NULL) + { + // 'dualfarkas' + mxAddField(lpResult, COPTMEX_RESULT_DUALFARKAS); + mxSetField(lpResult, 0, COPTMEX_RESULT_DUALFARKAS, msol.farkas); + } + + if (msol.ray != NULL) + { + // 'primalray' + mxAddField(lpResult, COPTMEX_RESULT_PRIMALRAY); + mxSetField(lpResult, 0, COPTMEX_RESULT_PRIMALRAY, msol.ray); + } + + if (csol.hasBasis) + { + // 'varbasis' + mxAddField(lpResult, COPTMEX_RESULT_VARBASIS); + mxSetField(lpResult, 0, COPTMEX_RESULT_VARBASIS, msol.varbasis); + // 'constrbasis' + mxAddField(lpResult, COPTMEX_RESULT_CONBASIS); + mxSetField(lpResult, 0, COPTMEX_RESULT_CONBASIS, msol.constrbasis); + } + + *out_lpresult = lpResult; + +exit_cleanup: + if (retcode != COPT_RETCODE_OK) + { + *out_lpresult = NULL; + } + + return retcode; +} + +/* Extract MIP solution */ +static int COPTMEX_getMipResult(copt_prob* prob, mxArray** out_mipresult) +{ + int retcode = COPT_RETCODE_OK; + mxArray* mipResult = NULL; + coptmex_cmipsol csol; + coptmex_mmipsol msol; + + COPTMEX_initCMipSol(&csol); + COPTMEX_initMMipSol(&msol); + + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_ROWS, &csol.nRow)); + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_COLS, &csol.nCol)); + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_HASMIPSOL, &csol.hasMipSol)); + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_POOLSOLS, &csol.nSolPool)); + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_MIPSTATUS, &csol.nStatus)); + + msol.status = mxCreateString(COPTMEX_statusInt2Str(csol.nStatus)); + msol.simplexiter = mxCreateDoubleMatrix(1, 1, mxREAL); + msol.nodecnt = mxCreateDoubleMatrix(1, 1, mxREAL); + msol.solvingtime = mxCreateDoubleMatrix(1, 1, mxREAL); + if (!msol.status || !msol.simplexiter || !msol.nodecnt || !msol.solvingtime) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + if (csol.hasMipSol) + { + msol.bestgap = mxCreateDoubleMatrix(1, 1, mxREAL); + msol.objval = mxCreateDoubleMatrix(1, 1, mxREAL); + msol.bestbnd = mxCreateDoubleMatrix(1, 1, mxREAL); + msol.value = mxCreateDoubleMatrix(csol.nCol, 1, mxREAL); + if (!msol.bestgap || !msol.objval || !msol.bestbnd || !msol.value) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + csol.colValue = mxGetDoubles(msol.value); + } + + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_SIMPLEXITER, &csol.nSimplexIter)); + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_NODECNT, &csol.nNodeCnt)); + COPTMEX_CALL(COPT_GetDblAttr(prob, COPT_DBLATTR_SOLVINGTIME, &csol.dSolvingTime)); + + if (csol.hasMipSol) + { + COPTMEX_CALL(COPT_GetDblAttr(prob, COPT_DBLATTR_BESTGAP, &csol.dBestGap)); + COPTMEX_CALL(COPT_GetDblAttr(prob, COPT_DBLATTR_BESTOBJ, &csol.dObjVal)); + COPTMEX_CALL(COPT_GetDblAttr(prob, COPT_DBLATTR_BESTBND, &csol.dBestBnd)); + COPTMEX_CALL(COPT_GetSolution(prob, csol.colValue)); + } + + if (csol.nSolPool > 0) + { + const char* solpoolfields[] = {COPTMEX_RESULT_POOLOBJ, COPTMEX_RESULT_POOLXN}; + msol.solpool = mxCreateStructMatrix(csol.nSolPool, 1, 2, solpoolfields); + if (!msol.solpool) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + for (int i = 0; i < csol.nSolPool; ++i) + { + mxArray* poolobjval = mxCreateDoubleMatrix(1, 1, mxREAL); + mxArray* poolxn = mxCreateDoubleMatrix(csol.nCol, 1, mxREAL); + if (!poolobjval || !poolxn) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + double dPoolObjVal = +COPT_INFINITY; + double* dPoolColValue = mxGetDoubles(poolxn); + + COPTMEX_CALL(COPT_GetPoolObjVal(prob, i, &dPoolObjVal)); + COPTMEX_CALL(COPT_GetPoolSolution(prob, i, csol.nCol, NULL, dPoolColValue)); + + *mxGetDoubles(poolobjval) = dPoolObjVal; + + mxSetField(msol.solpool, i, COPTMEX_RESULT_POOLOBJ, poolobjval); + mxSetField(msol.solpool, i, COPTMEX_RESULT_POOLXN, poolxn); + } + } + + *mxGetDoubles(msol.simplexiter) = csol.nSimplexIter; + *mxGetDoubles(msol.nodecnt) = csol.nNodeCnt; + *mxGetDoubles(msol.solvingtime) = csol.dSolvingTime; + + if (csol.hasMipSol) + { + *mxGetDoubles(msol.bestgap) = csol.dBestGap; + *mxGetDoubles(msol.objval) = csol.dObjVal; + *mxGetDoubles(msol.bestbnd) = csol.dBestBnd; + } + + mipResult = mxCreateStructMatrix(1, 1, 0, NULL); + if (!mipResult) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + // 'status' + mxAddField(mipResult, COPTMEX_RESULT_STATUS); + mxSetField(mipResult, 0, COPTMEX_RESULT_STATUS, msol.status); + // 'simplexiter' + mxAddField(mipResult, COPTMEX_RESULT_SIMITER); + mxSetField(mipResult, 0, COPTMEX_RESULT_SIMITER, msol.simplexiter); + // 'nodecnt' + mxAddField(mipResult, COPTMEX_RESULT_NODECNT); + mxSetField(mipResult, 0, COPTMEX_RESULT_NODECNT, msol.nodecnt); + // 'solvingtime' + mxAddField(mipResult, COPTMEX_RESULT_SOLVETIME); + mxSetField(mipResult, 0, COPTMEX_RESULT_SOLVETIME, msol.solvingtime); + + if (csol.hasMipSol) + { + // 'bestgap' + mxAddField(mipResult, COPTMEX_RESULT_BESTGAP); + mxSetField(mipResult, 0, COPTMEX_RESULT_BESTGAP, msol.bestgap); + // 'objval' + mxAddField(mipResult, COPTMEX_RESULT_OBJVAL); + mxSetField(mipResult, 0, COPTMEX_RESULT_OBJVAL, msol.objval); + // 'bestbnd' + mxAddField(mipResult, COPTMEX_RESULT_BESTBND); + mxSetField(mipResult, 0, COPTMEX_RESULT_BESTBND, msol.bestbnd); + // 'x' + mxAddField(mipResult, COPTMEX_RESULT_VALUE); + mxSetField(mipResult, 0, COPTMEX_RESULT_VALUE, msol.value); + } + + if (csol.nSolPool > 0) + { + // 'pool' + mxAddField(mipResult, COPTMEX_RESULT_POOL); + mxSetField(mipResult, 0, COPTMEX_RESULT_POOL, msol.solpool); + } + + *out_mipresult = mipResult; + +exit_cleanup: + if (retcode != COPT_RETCODE_OK) + { + *out_mipresult = NULL; + } + + return retcode; +} + +/* Extract and save result */ +int COPTMEX_getResult(copt_prob* prob, mxArray** out_result) +{ + int retcode = 0; + int isMip = 0; + + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_ISMIP, &isMip)); + if (isMip) + { + COPTMEX_CALL(COPTMEX_getMipResult(prob, out_result)); + } + else + { + COPTMEX_CALL(COPTMEX_getLpResult(prob, out_result)); + } + +exit_cleanup: + return retcode; +} + +/* Extract model data */ +int COPTMEX_getModel(copt_prob* prob, int nfiles, const mxArray** in_files, mxArray** out_model) +{ + int retcode = COPT_RETCODE_OK; + int hasInfoFile = 0; + mxArray* retmodel = NULL; + coptmex_cprob cprob; + coptmex_mprob mprob; + + // Read model from file + if (nfiles == 1 || nfiles == 2) + { + COPTMEX_CALL(COPTMEX_readModel(prob, in_files[0])); + if (nfiles == 2) + { + COPTMEX_CALL(COPTMEX_readInfo(prob, in_files[1])); + hasInfoFile = 1; + } + } + + COPTMEX_initCProb(&cprob); + COPTMEX_initMProb(&mprob); + + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_ROWS, &cprob.nRow)); + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_COLS, &cprob.nCol)); + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_ELEMS, &cprob.nElem)); + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_QELEMS, &cprob.nQElem)); + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_SOSS, &cprob.nSos)); + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_INDICATORS, &cprob.nIndicator)); + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_CONES, &cprob.nCone)); + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_QCONSTRS, &cprob.nQConstr)); + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_OBJSENSE, &cprob.nObjSen)); + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_HASBASIS, &cprob.hasBasis)); + + mprob.objsen = mxCreateString(COPTMEX_objsenInt2Str(cprob.nObjSen)); + mprob.objcon = mxCreateDoubleMatrix(1, 1, mxREAL); + if (!mprob.objsen || !mprob.objcon) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + COPTMEX_CALL(COPT_GetDblAttr(prob, COPT_DBLATTR_OBJCONST, &cprob.dObjConst)); + *mxGetDoubles(mprob.objcon) = cprob.dObjConst; + + if (cprob.nRow > 0 && cprob.nCol > 0) + { + int nRealElem = 0; + if (cprob.nElem == 0) + { + nRealElem = 1; + } + else + { + nRealElem = cprob.nElem; + } + + mprob.A = mxCreateSparse(cprob.nRow, cprob.nCol, nRealElem, mxREAL); + if (!mprob.A) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + cprob.colMatBeg = (int*)mxCalloc(cprob.nCol + 1, sizeof(int)); + cprob.colMatIdx = (int*)mxCalloc(nRealElem, sizeof(int)); + if (!cprob.colMatBeg || !cprob.colMatIdx) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + cprob.colMatElem = mxGetDoubles(mprob.A); + + if (cprob.nElem > 0) + { + COPTMEX_CALL(COPT_GetCols(prob, cprob.nCol, NULL, cprob.colMatBeg, NULL, cprob.colMatIdx, cprob.colMatElem, + cprob.nElem, NULL)); + } + + mwIndex* colMatBeg_data = mxGetJc(mprob.A); + mwIndex* colMatIdx_data = mxGetIr(mprob.A); + + for (int i = 0; i < cprob.nCol + 1; ++i) + { + colMatBeg_data[i] = cprob.colMatBeg[i]; + } + for (int i = 0; i < nRealElem; ++i) + { + colMatIdx_data[i] = cprob.colMatIdx[i]; + } + + mxFree(cprob.colMatBeg); + mxFree(cprob.colMatIdx); + } + + if (cprob.nCol > 0) + { + mprob.obj = mxCreateDoubleMatrix(cprob.nCol, 1, mxREAL); + mprob.lb = mxCreateDoubleMatrix(cprob.nCol, 1, mxREAL); + mprob.ub = mxCreateDoubleMatrix(cprob.nCol, 1, mxREAL); + mprob.varnames = mxCreateCellMatrix(cprob.nCol, 1); + if (!mprob.obj || !mprob.lb || !mprob.ub || !mprob.varnames) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + cprob.colCost = mxGetDoubles(mprob.obj); + cprob.colLower = mxGetDoubles(mprob.lb); + cprob.colUpper = mxGetDoubles(mprob.ub); + + COPTMEX_CALL(COPT_GetColInfo(prob, COPT_DBLINFO_OBJ, cprob.nCol, NULL, cprob.colCost)); + COPTMEX_CALL(COPT_GetColInfo(prob, COPT_DBLINFO_LB, cprob.nCol, NULL, cprob.colLower)); + COPTMEX_CALL(COPT_GetColInfo(prob, COPT_DBLINFO_UB, cprob.nCol, NULL, cprob.colUpper)); + + char* colType_c = (char*)mxCalloc(2 * cprob.nCol, sizeof(char)); + char** colType_s = (char**)mxCalloc(cprob.nCol, sizeof(char*)); + if (!colType_c || !colType_s) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + COPTMEX_CALL(COPT_GetColType(prob, cprob.nCol, NULL, colType_c)); + + for (int i = cprob.nCol - 1; i >= 0; --i) + { + colType_c[2 * i] = colType_c[i]; + colType_c[2 * i + 1] = 0; + } + + for (int i = 0; i < cprob.nCol; ++i) + { + colType_s[i] = colType_c + 2 * i; + } + + mprob.vtype = mxCreateCharMatrixFromStrings(cprob.nCol, (const char**)colType_s); + + int colNameLen = 0; + char** colNames = (char**)mxCalloc(cprob.nCol, sizeof(char*)); + if (!colNames) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + for (int i = 0; i < cprob.nCol; ++i) + { + COPTMEX_CALL(COPT_GetColName(prob, i, NULL, 0, &colNameLen)); + colNames[i] = (char*)mxCalloc(colNameLen, sizeof(char)); + if (!colNames[i]) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + COPTMEX_CALL(COPT_GetColName(prob, i, colNames[i], colNameLen, NULL)); + + mxSetCell(mprob.varnames, i, mxCreateString(colNames[i])); + } + } + + if (cprob.nRow > 0) + { + mprob.lhs = mxCreateDoubleMatrix(cprob.nRow, 1, mxREAL); + mprob.rhs = mxCreateDoubleMatrix(cprob.nRow, 1, mxREAL); + mprob.constrnames = mxCreateCellMatrix(cprob.nRow, 1); + if (!mprob.lhs || !mprob.rhs || !mprob.constrnames) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + cprob.rowLower = mxGetDoubles(mprob.lhs); + cprob.rowUpper = mxGetDoubles(mprob.rhs); + + COPTMEX_CALL(COPT_GetRowInfo(prob, COPT_DBLINFO_LB, cprob.nRow, NULL, cprob.rowLower)); + COPTMEX_CALL(COPT_GetRowInfo(prob, COPT_DBLINFO_UB, cprob.nRow, NULL, cprob.rowUpper)); + + int rowNameLen = 0; + // TODO: rowSense + char** rowNames = (char**)mxCalloc(cprob.nRow, sizeof(char*)); + if (!rowNames) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + for (int i = 0; i < cprob.nRow; ++i) + { + COPTMEX_CALL(COPT_GetRowName(prob, i, NULL, 0, &rowNameLen)); + rowNames[i] = (char*)mxCalloc(rowNameLen, sizeof(char)); + if (!rowNames[i]) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + COPTMEX_CALL(COPT_GetRowName(prob, i, rowNames[i], rowNameLen, NULL)); + + mxSetCell(mprob.constrnames, i, mxCreateString(rowNames[i])); + } + } + + if (cprob.nSos > 0) + { + const char* sosfields[] = {COPTMEX_MODEL_SOSTYPE, COPTMEX_MODEL_SOSVARS, COPTMEX_MODEL_SOSWEIGHT}; + mprob.sos = mxCreateStructMatrix(cprob.nSos, 1, 3, sosfields); + if (!mprob.sos) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + COPTMEX_CALL(COPT_GetSOSs(prob, cprob.nSos, NULL, NULL, NULL, NULL, NULL, NULL, 0, &cprob.nSosSize)); + + cprob.sosType = (int*)mxCalloc(cprob.nSos, sizeof(int)); + cprob.sosMatBeg = (int*)mxCalloc(cprob.nSos, sizeof(int)); + cprob.sosMatCnt = (int*)mxCalloc(cprob.nSos, sizeof(int)); + cprob.sosMatIdx = (int*)mxCalloc(cprob.nSosSize, sizeof(int)); + cprob.sosMatWt = (double*)mxCalloc(cprob.nSosSize, sizeof(double)); + if (!cprob.sosType || !cprob.sosMatBeg || !cprob.sosMatCnt || !cprob.sosMatIdx || !cprob.sosMatWt) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + COPTMEX_CALL(COPT_GetSOSs(prob, cprob.nSos, NULL, cprob.sosType, cprob.sosMatBeg, cprob.sosMatCnt, cprob.sosMatIdx, + cprob.sosMatWt, cprob.nSosSize, NULL)); + + for (int i = 0; i < cprob.nSos; ++i) + { + mxArray* sosType = mxCreateDoubleMatrix(1, 1, mxREAL); + mxArray* sosIdx = mxCreateDoubleMatrix(cprob.sosMatCnt[i], 1, mxREAL); + mxArray* sosWts = mxCreateDoubleMatrix(cprob.sosMatCnt[i], 1, mxREAL); + if (!sosType || !sosIdx || !sosWts) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + *mxGetDoubles(sosType) = cprob.sosType[i]; + + int iSosElem = cprob.sosMatBeg[i]; + int iSosLast = cprob.sosMatCnt[i] + iSosElem; + double* sosIdx_data = mxGetDoubles(sosIdx); + double* sosWts_data = mxGetDoubles(sosWts); + for (int iElem = 0; iElem < cprob.sosMatCnt[i]; ++iElem) + { + sosIdx_data[iElem] = cprob.sosMatIdx[iSosElem] + 1; + sosWts_data[iElem] = cprob.sosMatWt[iSosElem]; + iSosElem++; + } + + mxSetField(mprob.sos, i, COPTMEX_MODEL_SOSTYPE, sosType); + mxSetField(mprob.sos, i, COPTMEX_MODEL_SOSVARS, sosIdx); + mxSetField(mprob.sos, i, COPTMEX_MODEL_SOSWEIGHT, sosWts); + } + } + + if (cprob.nIndicator > 0) + { + const char* indicfields[] = {COPTMEX_MODEL_INDICBINVAR, COPTMEX_MODEL_INDICBINVAL, COPTMEX_MODEL_INDICROW, + COPTMEX_MODEL_INDICSENSE, COPTMEX_MODEL_INDICRHS}; + mprob.indicator = mxCreateStructMatrix(cprob.nIndicator, 1, 5, indicfields); + if (!mprob.indicator) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + for (int i = 0; i < cprob.nIndicator; ++i) + { + int rowElemCnt = 0; + COPTMEX_CALL(COPT_GetIndicator(prob, i, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, &rowElemCnt)); + + mxArray* binVar = mxCreateDoubleMatrix(1, 1, mxREAL); + mxArray* binVal = mxCreateDoubleMatrix(1, 1, mxREAL); + mxArray* indicA = mxCreateSparse(cprob.nCol, 1, rowElemCnt, mxREAL); + mxArray* indicSense = NULL; + mxArray* indicRhs = mxCreateDoubleMatrix(1, 1, mxREAL); + + int binColIdx = 0; + int binColVal = 0; + int nRowMatCnt = 0; + int* rowMatIdx = (int*)mxCalloc(rowElemCnt, sizeof(int)); + double* rowMatElem = (double*)mxCalloc(rowElemCnt, sizeof(double)); + char cRowSense[2] = {0}; + double dRowBound = 0; + + COPTMEX_CALL(COPT_GetIndicator(prob, i, &binColIdx, &binColVal, &nRowMatCnt, rowMatIdx, rowMatElem, &cRowSense[0], + &dRowBound, rowElemCnt, NULL)); + + *mxGetDoubles(binVar) = binColIdx + 1; + *mxGetDoubles(binVal) = binColVal; + + mwIndex* jc_data = mxGetJc(indicA); + mwIndex* ir_data = mxGetIr(indicA); + double* val_data = mxGetDoubles(indicA); + + jc_data[0] = 0; + jc_data[1] = rowElemCnt; + for (int i = 0; i < rowElemCnt; ++i) + { + ir_data[i] = rowMatIdx[i]; + val_data[i] = rowMatElem[i]; + } + + indicSense = mxCreateString(cRowSense); + *mxGetDoubles(indicRhs) = dRowBound; + + mxFree(rowMatIdx); + mxFree(rowMatElem); + + mxSetField(mprob.indicator, i, COPTMEX_MODEL_INDICBINVAR, binVar); + mxSetField(mprob.indicator, i, COPTMEX_MODEL_INDICBINVAL, binVal); + mxSetField(mprob.indicator, i, COPTMEX_MODEL_INDICROW, indicA); + mxSetField(mprob.indicator, i, COPTMEX_MODEL_INDICSENSE, indicSense); + mxSetField(mprob.indicator, i, COPTMEX_MODEL_INDICRHS, indicRhs); + } + } + + if (cprob.nCone > 0) + { + const char* conefields[] = {COPTMEX_MODEL_CONETYPE, COPTMEX_MODEL_CONEVARS}; + mprob.cone = mxCreateStructMatrix(cprob.nCone, 1, 2, conefields); + if (!mprob.cone) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + COPTMEX_CALL(COPT_GetCones(prob, cprob.nCone, NULL, NULL, NULL, NULL, NULL, 0, &cprob.nConeSize)); + + cprob.coneType = (int*)mxCalloc(cprob.nCone, sizeof(int)); + cprob.coneBeg = (int*)mxCalloc(cprob.nCone, sizeof(int)); + cprob.coneCnt = (int*)mxCalloc(cprob.nCone, sizeof(int)); + cprob.coneIdx = (int*)mxCalloc(cprob.nConeSize, sizeof(int)); + if (!cprob.coneType || !cprob.coneBeg || !cprob.coneCnt || !cprob.coneIdx) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + COPTMEX_CALL(COPT_GetCones(prob, cprob.nCone, NULL, cprob.coneType, cprob.coneBeg, cprob.coneCnt, cprob.coneIdx, + cprob.nConeSize, NULL)); + + for (int i = 0; i < cprob.nCone; ++i) + { + mxArray* coneType = mxCreateDoubleMatrix(1, 1, mxREAL); + mxArray* coneIdx = mxCreateDoubleMatrix(cprob.coneCnt[i], 1, mxREAL); + if (!coneType || !coneIdx) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + *mxGetDoubles(coneType) = cprob.coneType[i]; + + int iConeElem = cprob.coneBeg[i]; + int iConeLast = cprob.coneCnt[i] + iConeElem; + double* coneIdx_data = mxGetDoubles(coneIdx); + for (int iElem = 0; iElem < cprob.coneCnt[i]; ++iElem) + { + coneIdx_data[iElem] = cprob.coneIdx[iConeElem] + 1; + iConeElem++; + } + + mxSetField(mprob.cone, i, COPTMEX_MODEL_CONETYPE, coneType); + mxSetField(mprob.cone, i, COPTMEX_MODEL_CONEVARS, coneIdx); + } + } + + if (cprob.nQElem > 0) + { + mprob.qobj = mxCreateSparse(cprob.nCol, cprob.nCol, cprob.nQElem, mxREAL); + if (!mprob.qobj) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + int* qObjRow = (int*)mxCalloc(cprob.nQElem, sizeof(int)); + int* qObjCol = (int*)mxCalloc(cprob.nQElem, sizeof(int)); + double* qObjElem = (double*)mxCalloc(cprob.nQElem, sizeof(double)); + if (!qObjRow || !qObjCol || !qObjElem) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + COPTMEX_CALL(COPT_GetQuadObj(prob, NULL, qObjRow, qObjCol, qObjElem)); + COPTMEX_CALL(COPTMEX_coo2csc(cprob.nQElem, qObjRow, qObjCol, qObjElem, mprob.qobj)); + + mxFree(qObjRow); + mxFree(qObjCol); + mxFree(qObjElem); + } + + if (cprob.nQConstr > 0) + { + const char* qconstrfields[] = {COPTMEX_MODEL_QCROW, COPTMEX_MODEL_QCCOL, COPTMEX_MODEL_QCVAL, + COPTMEX_MODEL_QCLINEAR, COPTMEX_MODEL_QCSENSE, COPTMEX_MODEL_QCRHS, COPTMEX_MODEL_QCNAME}; + mprob.quadcon = mxCreateStructMatrix(cprob.nQConstr, 1, 7, qconstrfields); + if (!mprob.quadcon) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + for (int i = 0; i < cprob.nQConstr; ++i) + { + int nQMatElem = 0; + int nQRowElem = 0; + COPTMEX_CALL(COPT_GetQConstr(prob, i, NULL, NULL, NULL, 0, &nQMatElem, NULL, NULL, NULL, NULL, 0, &nQRowElem)); + + mxArray* QcRow = mxCreateDoubleMatrix(nQMatElem, 1, mxREAL); + mxArray* QcCol = mxCreateDoubleMatrix(nQMatElem, 1, mxREAL); + mxArray* QcVal = mxCreateDoubleMatrix(nQMatElem, 1, mxREAL); + mxArray* QcLinear = mxCreateSparse(cprob.nCol, 1, nQRowElem, mxREAL); + mxArray* QcSense = NULL; + mxArray* QcRhs = mxCreateDoubleMatrix(1, 1, mxREAL); + mxArray* QcName = NULL; + + int* qMatRow = (int*)mxCalloc(nQMatElem, sizeof(int)); + int* qMatCol = (int*)mxCalloc(nQMatElem, sizeof(int)); + double* qMatElem = mxGetDoubles(QcVal); + int* qRowMatIdx = (int*)mxCalloc(nQRowElem, sizeof(int)); + double* qRowMatElem = mxGetDoubles(QcLinear); + char qRowSense[2]; + double qRowBound = 0.0; + char* qRowName = NULL; + + COPTMEX_CALL(COPT_GetQConstr(prob, i, qMatRow, qMatCol, qMatElem, nQMatElem, NULL, qRowMatIdx, qRowMatElem, + qRowSense, &qRowBound, nQRowElem, NULL)); + + double* qMatRow_data = mxGetDoubles(QcRow); + double* qMatCol_data = mxGetDoubles(QcCol); + for (int i = 0; i < nQMatElem; ++i) + { + qMatRow_data[i] = qMatRow[i]; + qMatCol_data[i] = qMatCol[i]; + } + + mwIndex* jc_data = mxGetJc(QcLinear); + mwIndex* ir_data = mxGetIr(QcLinear); + + jc_data[0] = 0; + jc_data[1] = nQRowElem; + for (int i = 0; i < nQRowElem; ++i) + { + ir_data[i] = qRowMatIdx[i]; + } + + QcSense = mxCreateString(qRowSense); + *mxGetDoubles(QcRhs) = qRowBound; + + int nQcNameSize = 0; + COPTMEX_CALL(COPT_GetQConstrName(prob, i, NULL, 0, &nQcNameSize)); + + qRowName = (char*)mxCalloc(nQcNameSize + 1, sizeof(char)); + if (!qRowName) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + COPTMEX_CALL(COPT_GetQConstrName(prob, i, qRowName, nQcNameSize, NULL)); + QcName = mxCreateString(qRowName); + + mxSetField(mprob.quadcon, i, COPTMEX_MODEL_QCROW, QcRow); + mxSetField(mprob.quadcon, i, COPTMEX_MODEL_QCCOL, QcCol); + mxSetField(mprob.quadcon, i, COPTMEX_MODEL_QCVAL, QcVal); + mxSetField(mprob.quadcon, i, COPTMEX_MODEL_QCLINEAR, QcLinear); + mxSetField(mprob.quadcon, i, COPTMEX_MODEL_QCSENSE, QcSense); + mxSetField(mprob.quadcon, i, COPTMEX_MODEL_QCRHS, QcRhs); + mxSetField(mprob.quadcon, i, COPTMEX_MODEL_QCNAME, QcName); + + mxFree(qMatRow); + mxFree(qMatCol); + mxFree(qRowMatIdx); + mxFree(qRowName); + } + } + + if (hasInfoFile && cprob.hasBasis) + { + mprob.varbasis = mxCreateDoubleMatrix(cprob.nCol, 1, mxREAL); + mprob.constrbasis = mxCreateDoubleMatrix(cprob.nRow, 1, mxREAL); + if (!mprob.varbasis || !mprob.constrbasis) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + cprob.colBasis = (int*)mxCalloc(cprob.nCol, sizeof(int)); + cprob.rowBasis = (int*)mxCalloc(cprob.nRow, sizeof(int)); + if (!cprob.colBasis || !cprob.rowBasis) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + COPTMEX_CALL(COPT_GetColBasis(prob, cprob.nCol, NULL, cprob.colBasis)); + COPTMEX_CALL(COPT_GetRowBasis(prob, cprob.nRow, NULL, cprob.rowBasis)); + + double* colBasis_data = mxGetDoubles(mprob.varbasis); + double* rowBasis_data = mxGetDoubles(mprob.constrbasis); + for (int i = 0; i < cprob.nCol; ++i) + { + colBasis_data[i] = cprob.colBasis[i]; + } + for (int i = 0; i < cprob.nRow; ++i) + { + rowBasis_data[i] = cprob.rowBasis[i]; + } + + mxFree(cprob.colBasis); + mxFree(cprob.rowBasis); + } + + retmodel = mxCreateStructMatrix(1, 1, 0, NULL); + if (!retmodel) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + // 'objsen' + mxAddField(retmodel, COPTMEX_MODEL_OBJSEN); + mxSetField(retmodel, 0, COPTMEX_MODEL_OBJSEN, mprob.objsen); + // 'objcon' + mxAddField(retmodel, COPTMEX_MODEL_OBJCON); + mxSetField(retmodel, 0, COPTMEX_MODEL_OBJCON, mprob.objcon); + + if (mprob.A != NULL) + { + // 'A' + mxAddField(retmodel, COPTMEX_MODEL_A); + mxSetField(retmodel, 0, COPTMEX_MODEL_A, mprob.A); + } + + if (cprob.nCol > 0) + { + // 'obj' + mxAddField(retmodel, COPTMEX_MODEL_OBJ); + mxSetField(retmodel, 0, COPTMEX_MODEL_OBJ, mprob.obj); + // 'lb' + mxAddField(retmodel, COPTMEX_MODEL_LB); + mxSetField(retmodel, 0, COPTMEX_MODEL_LB, mprob.lb); + // 'ub' + mxAddField(retmodel, COPTMEX_MODEL_UB); + mxSetField(retmodel, 0, COPTMEX_MODEL_UB, mprob.ub); + // 'vtype' + mxAddField(retmodel, COPTMEX_MODEL_VTYPE); + mxSetField(retmodel, 0, COPTMEX_MODEL_VTYPE, mprob.vtype); + // 'varnames' + mxAddField(retmodel, COPTMEX_MODEL_VARNAME); + mxSetField(retmodel, 0, COPTMEX_MODEL_VARNAME, mprob.varnames); + } + + if (cprob.nRow > 0) + { + // TODO: 'sense' + // 'lhs' + mxAddField(retmodel, COPTMEX_MODEL_LHS); + mxSetField(retmodel, 0, COPTMEX_MODEL_LHS, mprob.lhs); + // 'rhs' + mxAddField(retmodel, COPTMEX_MODEL_RHS); + mxSetField(retmodel, 0, COPTMEX_MODEL_RHS, mprob.rhs); + // 'constrnames' + mxAddField(retmodel, COPTMEX_MODEL_CONNAME); + mxSetField(retmodel, 0, COPTMEX_MODEL_CONNAME, mprob.constrnames); + } + + // 'sos' + if (cprob.nSos > 0) + { + mxAddField(retmodel, COPTMEX_MODEL_SOS); + mxSetField(retmodel, 0, COPTMEX_MODEL_SOS, mprob.sos); + } + + // 'indicator' + if (cprob.nIndicator > 0) + { + mxAddField(retmodel, COPTMEX_MODEL_INDICATOR); + mxSetField(retmodel, 0, COPTMEX_MODEL_INDICATOR, mprob.indicator); + } + + // 'cone' + if (cprob.nCone > 0) + { + mxAddField(retmodel, COPTMEX_MODEL_CONE); + mxSetField(retmodel, 0, COPTMEX_MODEL_CONE, mprob.cone); + } + + // 'Q' + if (cprob.nQElem > 0) + { + mxAddField(retmodel, COPTMEX_MODEL_QUADOBJ); + mxSetField(retmodel, 0, COPTMEX_MODEL_QUADOBJ, mprob.qobj); + } + + // 'quadcon' + if (cprob.nQConstr > 0) + { + mxAddField(retmodel, COPTMEX_MODEL_QUADCON); + mxSetField(retmodel, 0, COPTMEX_MODEL_QUADCON, mprob.quadcon); + } + + if (hasInfoFile && cprob.hasBasis) + { + // 'varbasis' + mxAddField(retmodel, COPTMEX_RESULT_VARBASIS); + mxSetField(retmodel, 0, COPTMEX_RESULT_VARBASIS, mprob.varbasis); + // 'constrbasis' + mxAddField(retmodel, COPTMEX_RESULT_CONBASIS); + mxSetField(retmodel, 0, COPTMEX_RESULT_CONBASIS, mprob.constrbasis); + } + + *out_model = retmodel; + +exit_cleanup: + if (retcode != COPT_RETCODE_OK) + { + *out_model = NULL; + } + + return retcode; +} + +/* Load parameters to problem */ +int COPTMEX_setParam(copt_prob* prob, const mxArray* in_param) +{ + int retcode = 0; + char msgbuf[COPT_BUFFSIZE]; + + int islogging = 1; + mxArray* logging = NULL; + for (int i = mxGetNumberOfFields(in_param) - 1; i >= 0; --i) + { + const char* loggingname = mxGetFieldNameByNumber(in_param, i); + if (mystrcmp(loggingname, COPT_INTPARAM_LOGGING) == 0) + { + logging = mxGetField(in_param, 0, loggingname); + if (!mxIsScalar(logging) || mxIsChar(logging)) + { + snprintf(msgbuf, COPT_BUFFSIZE, "parameter.%s", COPT_INTPARAM_LOGGING); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + + islogging = (int)mxGetScalar(logging); + break; + } + } + + if (islogging == 1) + { + COPTMEX_CALL(COPTMEX_dispBanner()); + } + + if (logging != NULL && islogging == 0) + { + COPTMEX_CALL(COPT_SetIntParam(prob, COPT_INTPARAM_LOGGING, islogging)); + } + + for (int i = 0; i < mxGetNumberOfFields(in_param); ++i) + { + int partype = -1; + const char* parname = mxGetFieldNameByNumber(in_param, i); + mxArray* pararray = mxGetField(in_param, 0, parname); + + if (mystrcmp(parname, COPT_INTPARAM_LOGGING) == 0) + { + continue; + } + + COPTMEX_CALL(COPT_SearchParamAttr(prob, parname, &partype)); + if (partype != 0 && partype != 1) + { + snprintf(msgbuf, COPT_BUFFSIZE, "parameter.%s", parname); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_NAME, msgbuf); + goto exit_cleanup; + } + + if (!mxIsScalar(pararray) || mxIsChar(pararray)) + { + snprintf(msgbuf, COPT_BUFFSIZE, "parameter.%s", parname); + COPTMEX_errorMsg(COPTMEX_ERROR_BAD_TYPE, msgbuf); + goto exit_cleanup; + } + + if (partype == 0) + { + double dDefVal = 0.0; + COPTMEX_CALL(COPT_GetDblParamDef(prob, parname, &dDefVal)); + if (dDefVal != mxGetScalar(pararray)) + { + COPTMEX_CALL(COPT_SetDblParam(prob, parname, mxGetScalar(pararray))); + } + } + else if (partype == 1) + { + int nDefVal = 0; + COPTMEX_CALL(COPT_GetIntParamDef(prob, parname, &nDefVal)); + if (nDefVal != (int)mxGetScalar(pararray)) + { + COPTMEX_CALL(COPT_SetIntParam(prob, parname, (int)mxGetScalar(pararray))); + } + } + } + +exit_cleanup: + return retcode; +} + +static char* COPTMEX_getFileExt(const char* filename) +{ + char* tmpfilename = NULL; + char* lastdot = NULL; + int lenfile = strlen(filename); + + tmpfilename = (char*)mxCalloc(lenfile + 1, sizeof(char)); + memcpy(tmpfilename, filename, lenfile + 1); + + lastdot = strrchr(tmpfilename, '.'); + if (!lastdot || lastdot == tmpfilename) + { + return ""; + } + + if (lastdot != NULL) + { + if (strcmp(lastdot, ".gz") == 0) + { + *lastdot = '\0'; + + lastdot = strrchr(tmpfilename, '.'); + if (!lastdot || lastdot == tmpfilename) + { + return ""; + } + } + } + + return lastdot + 1; +} + +/* Read optional information from file */ +int COPTMEX_readInfo(copt_prob* prob, const mxArray* in_info) +{ + int retcode = 0; + char* filename = NULL; + char* fileext = NULL; + + COPTMEX_CALL(COPTMEX_getString(in_info, &filename)); + + fileext = COPTMEX_getFileExt(filename); + if (strcmp(fileext, "bas") == 0) + { + COPTMEX_CALL(COPT_ReadBasis(prob, filename)); + } + else + { + retcode = COPT_RETCODE_INVALID; + } + +exit_cleanup: + COPTMEX_freeString(&filename); + return retcode; +} + +/* Read model from file */ +int COPTMEX_readModel(copt_prob* prob, const mxArray* in_model) +{ + int retcode = 0; + char* filename = NULL; + char* fileext = NULL; + + COPTMEX_CALL(COPTMEX_getString(in_model, &filename)); + + fileext = COPTMEX_getFileExt(filename); + if (strcmp(fileext, "mps") == 0) + { + COPTMEX_CALL(COPT_ReadMps(prob, filename)); + } + else if (strcmp(fileext, "lp") == 0) + { + COPTMEX_CALL(COPT_ReadLp(prob, filename)); + } + else if (strcmp(fileext, "bin") == 0) + { + COPTMEX_CALL(COPT_ReadBin(prob, filename)); + } + else if (strcmp(fileext, "dat-s") == 0) + { + COPTMEX_CALL(COPT_ReadSDPA(prob, filename)); + } + else if (strcmp(fileext, "cbf") == 0) + { + COPTMEX_CALL(COPT_ReadCbf(prob, filename)); + } + else + { + retcode = COPT_RETCODE_INVALID; + } + +exit_cleanup: + COPTMEX_freeString(&filename); + return retcode; +} + +/* Write model to file */ +int COPTMEX_writeModel(copt_prob* prob, const mxArray* out_file) +{ + int retcode = 0; + char* filename = NULL; + char* fileext = NULL; + + COPTMEX_CALL(COPTMEX_getString(out_file, &filename)); + + fileext = COPTMEX_getFileExt(filename); + if (strcmp(fileext, "mps") == 0) + { + COPTMEX_CALL(COPT_WriteMps(prob, filename)); + } + else if (strcmp(fileext, "lp") == 0) + { + COPTMEX_CALL(COPT_WriteLp(prob, filename)); + } + else if (strcmp(fileext, "bin") == 0) + { + COPTMEX_CALL(COPT_WriteBin(prob, filename)); + } + else if (strcmp(fileext, "cbf") == 0) + { + COPTMEX_CALL(COPT_WriteCbf(prob, filename)); + } + else + { + retcode = COPT_RETCODE_INVALID; + } + +exit_cleanup: + COPTMEX_freeString(&filename); + return retcode; +} + +/* Check if solve problem via cone data */ +int COPTMEX_isConeModel(const mxArray* in_model) +{ + int ifConeData = 0; + mxArray* conedata = NULL; + + conedata = mxGetField(in_model, 0, COPTMEX_MODEL_CONEDATA); + if (conedata != NULL) + { + if (COPTMEX_checkConeModel(conedata)) + { + ifConeData = 1; + } + } + + return ifConeData; +} + +/* Solve cone problem with cone data */ +int COPTMEX_solveConeModel(copt_prob* prob, const mxArray* in_model, mxArray** out_result, int ifRetResult) +{ + int retcode = 0; + coptmex_cconeprob cconeprob; + coptmex_mconeprob mconeprob; + mxArray* conedata = NULL; + int* outRowMap = NULL; + + COPTMEX_initCConeProb(&cconeprob); + COPTMEX_initMConeProb(&mconeprob); + + conedata = mxGetField(in_model, 0, COPTMEX_MODEL_CONEDATA); + + mconeprob.c = mxGetField(conedata, 0, COPTMEX_MODEL_CONE_C); + mconeprob.A = mxGetField(conedata, 0, COPTMEX_MODEL_CONE_A); + mconeprob.b = mxGetField(conedata, 0, COPTMEX_MODEL_CONE_B); + + mconeprob.K = mxGetField(conedata, 0, COPTMEX_MODEL_CONE_K); + mconeprob.f = mxGetField(mconeprob.K, 0, COPTMEX_MODEL_CONEK_F); + mconeprob.l = mxGetField(mconeprob.K, 0, COPTMEX_MODEL_CONEK_L); + mconeprob.q = mxGetField(mconeprob.K, 0, COPTMEX_MODEL_CONEK_Q); + mconeprob.r = mxGetField(mconeprob.K, 0, COPTMEX_MODEL_CONEK_R); + mconeprob.s = mxGetField(mconeprob.K, 0, COPTMEX_MODEL_CONEK_S); + + mconeprob.objsen = mxGetField(conedata, 0, COPTMEX_MODEL_CONE_OBJSEN); + mconeprob.objcon = mxGetField(conedata, 0, COPTMEX_MODEL_CONE_OBJCON); + mconeprob.Q = mxGetField(conedata, 0, COPTMEX_MODEL_CONE_Q); + + // 'objsen' + if (mconeprob.objsen != NULL) + { + COPTMEX_CALL(COPTMEX_getObjsen(mconeprob.objsen, &cconeprob.nObjSense)); + } + // 'objcon' + if (mconeprob.objcon != NULL) + { + cconeprob.dObjConst = mxGetScalar(mconeprob.objcon); + } + // 'Q' + if (mconeprob.Q != NULL) + { + cconeprob.nQObjElem = mxGetNzmax(mconeprob.Q); + + cconeprob.qObjRow = (int*)mxCalloc(cconeprob.nQObjElem, sizeof(int)); + cconeprob.qObjCol = (int*)mxCalloc(cconeprob.nQObjElem, sizeof(int)); + cconeprob.qObjElem = (double*)mxCalloc(cconeprob.nQObjElem, sizeof(double)); + if (!cconeprob.qObjRow || !cconeprob.qObjCol || !cconeprob.qObjElem) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + COPTMEX_csc2coo(mconeprob.Q, cconeprob.qObjRow, cconeprob.qObjCol, cconeprob.qObjElem); + } + + // 'c' + if (mconeprob.c != NULL) + { + cconeprob.colObj = mxGetDoubles(mconeprob.c); + } + // 'A' + if (mconeprob.A != NULL) + { + cconeprob.nRow = mxGetM(mconeprob.A); + cconeprob.nCol = mxGetN(mconeprob.A); + cconeprob.nElem = mxGetNzmax(mconeprob.A); + cconeprob.colMatBeg = (int*)mxCalloc(cconeprob.nCol + 1, sizeof(int)); + cconeprob.colMatIdx = (int*)mxCalloc(cconeprob.nElem, sizeof(int)); + if (!cconeprob.colMatBeg || !cconeprob.colMatIdx) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + mwIndex* colMatBeg_data = mxGetJc(mconeprob.A); + mwIndex* colMatIdx_data = mxGetIr(mconeprob.A); + for (int i = 0; i < cconeprob.nCol + 1; ++i) + { + cconeprob.colMatBeg[i] = (int)colMatBeg_data[i]; + } + for (int i = 0; i < cconeprob.nElem; ++i) + { + cconeprob.colMatIdx[i] = (int)colMatIdx_data[i]; + } + + cconeprob.colMatElem = mxGetDoubles(mconeprob.A); + } + // 'b' + if (mconeprob.b != NULL) + { + cconeprob.rowRhs = (double*)mxCalloc(cconeprob.nRow, sizeof(double)); + + double* rowRhs = mxGetDoubles(mconeprob.b); + for (int i = 0; i < cconeprob.nRow; ++i) + { + if (mxIsInf(rowRhs[i])) + { + if (rowRhs[i] > 0) + { + cconeprob.rowRhs[i] = +COPT_INFINITY; + } + else + { + cconeprob.rowRhs[i] = -COPT_INFINITY; + } + } + else + { + cconeprob.rowRhs[i] = rowRhs[i]; + } + } + } + + // 'K' + if (mconeprob.K != NULL) + { + // 'f' + if (mconeprob.f != NULL) + { + cconeprob.nFree = (int)mxGetScalar(mconeprob.f); + } + // 'l' + if (mconeprob.l != NULL) + { + cconeprob.nPositive = (int)mxGetScalar(mconeprob.l); + } + // 'q' + if (mconeprob.q != NULL) + { + int nCone = mxGetNumberOfElements(mconeprob.q); + double* coneDim_data = mxGetDoubles(mconeprob.q); + + if (nCone > 1 || (nCone == 1 && coneDim_data[0] > 0)) + { + cconeprob.nCone = nCone; + cconeprob.coneDim = (int*)mxCalloc(cconeprob.nCone, sizeof(int)); + + for (int i = 0; i < cconeprob.nCone; ++i) + { + cconeprob.coneDim[i] = (int)coneDim_data[i]; + } + } + } + // 'r' + if (mconeprob.r != NULL) + { + int nRotateCone = mxGetNumberOfElements(mconeprob.r); + double* rotateConeDim_data = mxGetDoubles(mconeprob.r); + + if (nRotateCone > 1 || (nRotateCone == 1 && rotateConeDim_data[0] > 0)) + { + cconeprob.nRotateCone = nRotateCone; + cconeprob.rotateConeDim = (int*)mxCalloc(cconeprob.nRotateCone, sizeof(int)); + + for (int i = 0; i < cconeprob.nRotateCone; ++i) + { + cconeprob.rotateConeDim[i] = (int)rotateConeDim_data[i]; + } + } + } + // 's' + if (mconeprob.s != NULL) + { + int nPSD = mxGetNumberOfElements(mconeprob.s); + double* psdDim_data = mxGetDoubles(mconeprob.s); + + if (nPSD > 1 || (nPSD == 1 && psdDim_data[0] > 0)) + { + cconeprob.nPSD = nPSD; + cconeprob.psdDim = (int*)mxCalloc(cconeprob.nPSD, sizeof(int)); + + for (int i = 0; i < cconeprob.nPSD; ++i) + { + cconeprob.psdDim[i] = (int)psdDim_data[i]; + } + } + } + } + + outRowMap = (int*)mxCalloc(cconeprob.nRow, sizeof(int)); + if (!outRowMap) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + // Load cone problem data + COPTMEX_CALL( + COPT_LoadConeProb(prob, cconeprob.nCol, cconeprob.nRow, cconeprob.nFree, cconeprob.nPositive, 0, cconeprob.nCone, + cconeprob.nRotateCone, 0, 0, 0, 0, cconeprob.nPSD, cconeprob.nQObjElem, cconeprob.nObjSense, cconeprob.dObjConst, + cconeprob.colObj, cconeprob.qObjRow, cconeprob.qObjCol, cconeprob.qObjElem, cconeprob.colMatBeg, NULL, + cconeprob.colMatIdx, cconeprob.colMatElem, cconeprob.rowRhs, NULL, NULL, cconeprob.coneDim, + cconeprob.rotateConeDim, NULL, NULL, NULL, NULL, cconeprob.psdDim, NULL, NULL, NULL, NULL, outRowMap)); + + COPTMEX_CALL(COPT_Solve(prob)); + + if (ifRetResult == 1) + { + COPTMEX_CALL(COPTMEX_getResult(prob, out_result)); + + if (*out_result != NULL) + { + mxArray* rowMap = mxCreateDoubleMatrix(cconeprob.nRow, 1, mxREAL); + if (rowMap == NULL) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + double* rowMap_data = mxGetDoubles(rowMap); + for (int i = 0; i < cconeprob.nRow; ++i) + { + rowMap_data[i] = outRowMap[i]; + } + + mxAddField(*out_result, "rowmap"); + mxSetField(*out_result, 0, "rowmap", rowMap); + } + } + +exit_cleanup: + if (outRowMap != NULL) + { + mxFree(outRowMap); + } + + if (cconeprob.qObjRow != NULL) + { + mxFree(cconeprob.qObjRow); + } + if (cconeprob.qObjCol != NULL) + { + mxFree(cconeprob.qObjCol); + } + if (cconeprob.qObjElem != NULL) + { + mxFree(cconeprob.qObjElem); + } + + if (cconeprob.coneDim != NULL) + { + mxFree(cconeprob.coneDim); + } + if (cconeprob.rotateConeDim != NULL) + { + mxFree(cconeprob.rotateConeDim); + } + if (cconeprob.psdDim != NULL) + { + mxFree(cconeprob.psdDim); + } + + if (cconeprob.colMatBeg != NULL) + { + mxFree(cconeprob.colMatBeg); + } + if (cconeprob.colMatIdx != NULL) + { + mxFree(cconeprob.colMatIdx); + } + + if (cconeprob.rowRhs != NULL) + { + mxFree(cconeprob.rowRhs); + } + return retcode; +} + +/* Extract and load data to problem */ +int COPTMEX_loadModel(copt_prob* prob, const mxArray* in_model) +{ + int retcode = 0; + coptmex_cprob cprob; + coptmex_mprob mprob; + + COPTMEX_initCProb(&cprob); + COPTMEX_initMProb(&mprob); + + mprob.objsen = mxGetField(in_model, 0, COPTMEX_MODEL_OBJSEN); + mprob.objcon = mxGetField(in_model, 0, COPTMEX_MODEL_OBJCON); + mprob.A = mxGetField(in_model, 0, COPTMEX_MODEL_A); + mprob.obj = mxGetField(in_model, 0, COPTMEX_MODEL_OBJ); + mprob.lb = mxGetField(in_model, 0, COPTMEX_MODEL_LB); + mprob.ub = mxGetField(in_model, 0, COPTMEX_MODEL_UB); + mprob.vtype = mxGetField(in_model, 0, COPTMEX_MODEL_VTYPE); + mprob.varnames = mxGetField(in_model, 0, COPTMEX_MODEL_VARNAME); + mprob.sense = mxGetField(in_model, 0, COPTMEX_MODEL_SENSE); + mprob.lhs = mxGetField(in_model, 0, COPTMEX_MODEL_LHS); + mprob.rhs = mxGetField(in_model, 0, COPTMEX_MODEL_RHS); + mprob.constrnames = mxGetField(in_model, 0, COPTMEX_MODEL_CONNAME); + + mprob.sos = mxGetField(in_model, 0, COPTMEX_MODEL_SOS); + mprob.indicator = mxGetField(in_model, 0, COPTMEX_MODEL_INDICATOR); + mprob.cone = mxGetField(in_model, 0, COPTMEX_MODEL_CONE); + + mprob.qobj = mxGetField(in_model, 0, COPTMEX_MODEL_QUADOBJ); + mprob.quadcon = mxGetField(in_model, 0, COPTMEX_MODEL_QUADCON); + + mprob.varbasis = mxGetField(in_model, 0, COPTMEX_RESULT_VARBASIS); + mprob.constrbasis = mxGetField(in_model, 0, COPTMEX_RESULT_CONBASIS); + + mprob.value = mxGetField(in_model, 0, COPTMEX_RESULT_VALUE); + mprob.slack = mxGetField(in_model, 0, COPTMEX_RESULT_SLACK); + mprob.dual = mxGetField(in_model, 0, COPTMEX_RESULT_DUAL); + mprob.redcost = mxGetField(in_model, 0, COPTMEX_RESULT_REDCOST); + + mprob.mipstart = mxGetField(in_model, 0, COPTMEX_ADVINFO_MIPSTART); + + if (COPTMEX_checkModel(&mprob) == 0) + { + goto exit_cleanup; + } + + // 'objsen' + if (mprob.objsen != NULL) + { + COPTMEX_CALL(COPTMEX_getObjsen(mprob.objsen, &cprob.nObjSen)); + } + // 'objcon' + if (mprob.objcon != NULL) + { + cprob.dObjConst = mxGetScalar(mprob.objcon); + } + // 'A' + if (mprob.A != NULL) + { + cprob.nRow = mxGetM(mprob.A); + cprob.nCol = mxGetN(mprob.A); + cprob.nElem = mxGetNzmax(mprob.A); + cprob.colMatBeg = (int*)mxCalloc(cprob.nCol + 1, sizeof(int)); + cprob.colMatIdx = (int*)mxCalloc(cprob.nElem, sizeof(int)); + if (!cprob.colMatBeg || !cprob.colMatIdx) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + mwIndex* colMatBeg_data = mxGetJc(mprob.A); + mwIndex* colMatIdx_data = mxGetIr(mprob.A); + for (int i = 0; i < cprob.nCol + 1; ++i) + { + cprob.colMatBeg[i] = (int)colMatBeg_data[i]; + } + for (int i = 0; i < cprob.nElem; ++i) + { + cprob.colMatIdx[i] = (int)colMatIdx_data[i]; + } + + cprob.colMatElem = mxGetDoubles(mprob.A); + } + // 'obj' + if (mprob.obj != NULL) + { + cprob.colCost = mxGetDoubles(mprob.obj); + } + // 'lb' + if (mprob.lb != NULL) + { + cprob.colLower = (double*)mxCalloc(cprob.nCol, sizeof(double)); + + double* colLower = mxGetDoubles(mprob.lb); + for (int i = 0; i < cprob.nCol; ++i) + { + if (mxIsInf(colLower[i])) + { + if (colLower[i] > 0) + { + cprob.colLower[i] = +COPT_INFINITY; + } + else + { + cprob.colLower[i] = -COPT_INFINITY; + } + } + else + { + cprob.colLower[i] = colLower[i]; + } + } + } + // 'ub' + if (mprob.ub != NULL) + { + cprob.colUpper = (double*)mxCalloc(cprob.nCol, sizeof(double)); + + double* colUpper = mxGetDoubles(mprob.ub); + for (int i = 0; i < cprob.nCol; ++i) + { + if (mxIsInf(colUpper[i])) + { + if (colUpper[i] > 0) + { + cprob.colUpper[i] = +COPT_INFINITY; + } + else + { + cprob.colUpper[i] = -COPT_INFINITY; + } + } + else + { + cprob.colUpper[i] = colUpper[i]; + } + } + } + // 'vtype' + if (mprob.vtype != NULL) + { + if (mxGetNumberOfElements(mprob.vtype) == cprob.nCol) + { + COPTMEX_CALL(COPTMEX_getString(mprob.vtype, &cprob.colType)); + } + else + { + char* vtype = NULL; + COPTMEX_CALL(COPTMEX_getString(mprob.vtype, &vtype)); + + cprob.colType = (char*)mxCalloc(cprob.nCol + 1, sizeof(char)); + if (!cprob.colType) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + for (int i = 0; i < cprob.nCol; ++i) + { + cprob.colType[i] = vtype[0]; + } + } + } + // 'varnames' + if (mprob.varnames != NULL) + { + cprob.colNames = (char**)mxCalloc(cprob.nCol, sizeof(char*)); + for (int i = 0; i < cprob.nCol; ++i) + { + mxArray* nameCell = mxGetCell(mprob.varnames, i); + COPTMEX_CALL(COPTMEX_getString(nameCell, &cprob.colNames[i])); + } + } + // 'sense', 'lhs' and 'rhs' + if (mprob.sense == NULL) + { + cprob.rowLower = (double*)mxCalloc(cprob.nRow, sizeof(double)); + cprob.rowUpper = (double*)mxCalloc(cprob.nRow, sizeof(double)); + + double* rowLower = mxGetDoubles(mprob.lhs); + for (int i = 0; i < cprob.nRow; ++i) + { + if (mxIsInf(rowLower[i])) + { + if (rowLower[i] > 0) + { + cprob.rowLower[i] = +COPT_INFINITY; + } + else + { + cprob.rowLower[i] = -COPT_INFINITY; + } + } + else + { + cprob.rowLower[i] = rowLower[i]; + } + } + + double* rowUpper = mxGetDoubles(mprob.rhs); + for (int i = 0; i < cprob.nRow; ++i) + { + if (mxIsInf(rowUpper[i])) + { + if (rowUpper[i] > 0) + { + cprob.rowUpper[i] = +COPT_INFINITY; + } + else + { + cprob.rowUpper[i] = -COPT_INFINITY; + } + } + else + { + cprob.rowUpper[i] = rowUpper[i]; + } + } + } + else + { + if (mxGetNumberOfElements(mprob.sense) == cprob.nRow) + { + COPTMEX_CALL(COPTMEX_getString(mprob.sense, &cprob.rowSense)); + } + else + { + char* rsense = NULL; + COPTMEX_CALL(COPTMEX_getString(mprob.sense, &rsense)); + + cprob.rowSense = (char*)mxCalloc(cprob.nRow + 1, sizeof(char)); + if (!cprob.rowSense) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + for (int i = 0; i < cprob.nRow; ++i) + { + cprob.rowSense[i] = rsense[0]; + } + } + + cprob.rowUpper = (double*)mxCalloc(cprob.nRow, sizeof(double)); + + double* rowUpper = mxGetDoubles(mprob.rhs); + for (int i = 0; i < cprob.nRow; ++i) + { + if (mxIsInf(rowUpper[i])) + { + if (rowUpper[i] > 0) + { + cprob.rowUpper[i] = +COPT_INFINITY; + } + else + { + cprob.rowUpper[i] = -COPT_INFINITY; + } + } + else + { + cprob.rowUpper[i] = rowUpper[i]; + } + } + } + // 'constrnames' + if (mprob.constrnames != NULL) + { + cprob.rowNames = (char**)mxCalloc(cprob.nRow, sizeof(char*)); + for (int i = 0; i < cprob.nRow; ++i) + { + mxArray* namecell = mxGetCell(mprob.constrnames, i); + COPTMEX_CALL(COPTMEX_getString(namecell, &cprob.rowNames[i])); + } + } + + // Load problem data to COPT problem + if (cprob.rowSense == NULL) + { + COPTMEX_CALL(COPT_LoadProb(prob, cprob.nCol, cprob.nRow, cprob.nObjSen, cprob.dObjConst, cprob.colCost, + cprob.colMatBeg, NULL, cprob.colMatIdx, cprob.colMatElem, cprob.colType, cprob.colLower, cprob.colUpper, NULL, + cprob.rowLower, cprob.rowUpper, cprob.colNames, cprob.rowNames)); + } + else + { + COPTMEX_CALL(COPT_LoadProb(prob, cprob.nCol, cprob.nRow, cprob.nObjSen, cprob.dObjConst, cprob.colCost, + cprob.colMatBeg, NULL, cprob.colMatIdx, cprob.colMatElem, cprob.colType, cprob.colLower, cprob.colUpper, + cprob.rowSense, cprob.rowUpper, NULL, cprob.colNames, cprob.rowNames)); + } + + // Extract and load the optional SOS part + if (mprob.sos != NULL) + { + for (int i = 0; i < mxGetNumberOfElements(mprob.sos); ++i) + { + mxArray* sostype_m = mxGetField(mprob.sos, i, COPTMEX_MODEL_SOSTYPE); + mxArray* sosvars_m = mxGetField(mprob.sos, i, COPTMEX_MODEL_SOSVARS); + mxArray* soswgts_m = mxGetField(mprob.sos, i, COPTMEX_MODEL_SOSWEIGHT); + + int sosType = (int)mxGetScalar(sostype_m); + int sosMatBeg = 0; + int sosMatCnt = (int)mxGetNumberOfElements(sosvars_m); + int* sosMatIdx = (int*)mxCalloc(sosMatCnt, sizeof(int)); + if (!sosMatIdx) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + double* sosvars_data = mxGetDoubles(sosvars_m); + for (int i = 0; i < sosMatCnt; ++i) + { + sosMatIdx[i] = (int)sosvars_data[i] - 1; + } + + double* sosMatWt = NULL; + if (soswgts_m != NULL) + { + sosMatWt = mxGetDoubles(soswgts_m); + } + + COPTMEX_CALL(COPT_AddSOSs(prob, 1, &sosType, &sosMatBeg, &sosMatCnt, sosMatIdx, sosMatWt)); + + mxFree(sosMatIdx); + } + } + + // Extract and load the optional indicator part + if (mprob.indicator != NULL) + { + for (int i = 0; i < mxGetNumberOfElements(mprob.indicator); ++i) + { + mxArray* binVar = mxGetField(mprob.indicator, i, COPTMEX_MODEL_INDICBINVAR); + mxArray* binVal = mxGetField(mprob.indicator, i, COPTMEX_MODEL_INDICBINVAL); + mxArray* indicA = mxGetField(mprob.indicator, i, COPTMEX_MODEL_INDICROW); + mxArray* rSense = mxGetField(mprob.indicator, i, COPTMEX_MODEL_INDICSENSE); + mxArray* rowBnd = mxGetField(mprob.indicator, i, COPTMEX_MODEL_INDICRHS); + + int binColIdx = (int)mxGetScalar(binVar) - 1; + int binColVal = (int)mxGetScalar(binVal); + int nRowMatCnt = 0; + int* rowMatIdx = NULL; + double* rowMatElem = NULL; + + if (mxIsSparse(indicA)) + { + nRowMatCnt = mxGetNzmax(indicA); + rowMatIdx = (int*)mxCalloc(nRowMatCnt, sizeof(int)); + if (!rowMatIdx) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + mwIndex* rowMatIdx_data = mxGetIr(indicA); + for (int i = 0; i < nRowMatCnt; ++i) + { + rowMatIdx[i] = rowMatIdx_data[i]; + } + rowMatElem = mxGetDoubles(indicA); + } + else + { + double* rowMatElem_data = mxGetDoubles(indicA); + for (int i = 0; i < mxGetNumberOfElements(indicA); ++i) + { + if (rowMatElem_data[i] != 0) + { + ++nRowMatCnt; + } + } + rowMatIdx = (int*)mxCalloc(nRowMatCnt, sizeof(int)); + rowMatElem = (double*)mxCalloc(nRowMatCnt, sizeof(double)); + if (!rowMatIdx || !rowMatElem) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + for (int i = 0, iElem = 0; i < mxGetNumberOfElements(indicA); ++i) + { + if (rowMatElem_data[i] != 0) + { + rowMatIdx[iElem] = i; + rowMatElem[iElem] = rowMatElem_data[i]; + iElem++; + } + } + } + + char cRowSense[2]; + mxGetString(rSense, cRowSense, 2); + + double dRowBound = mxGetScalar(rowBnd); + if (mxIsInf(dRowBound)) + { + if (dRowBound > 0) + { + dRowBound = +COPT_INFINITY; + } + else + { + dRowBound = -COPT_INFINITY; + } + } + + COPTMEX_CALL( + COPT_AddIndicator(prob, binColIdx, binColVal, nRowMatCnt, rowMatIdx, rowMatElem, cRowSense[0], dRowBound)); + + mxFree(rowMatIdx); + if (!mxIsSparse(indicA)) + { + mxFree(rowMatElem); + } + } + } + + // Extract and load the optional cone part + if (mprob.cone != NULL) + { + for (int i = 0; i < mxGetNumberOfElements(mprob.cone); ++i) + { + mxArray* conetype_m = mxGetField(mprob.cone, i, COPTMEX_MODEL_CONETYPE); + mxArray* conevars_m = mxGetField(mprob.cone, i, COPTMEX_MODEL_CONEVARS); + + int coneType = (int)mxGetScalar(conetype_m); + int coneBeg = 0; + int coneCnt = (int)mxGetNumberOfElements(conevars_m); + int* coneIdx = (int*)mxCalloc(coneCnt, sizeof(int)); + if (!coneIdx) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + double* conevars_data = mxGetDoubles(conevars_m); + for (int i = 0; i < coneCnt; ++i) + { + coneIdx[i] = (int)conevars_data[i] - 1; + } + + COPTMEX_CALL(COPT_AddCones(prob, 1, &coneType, &coneBeg, &coneCnt, coneIdx)); + + mxFree(coneIdx); + } + } + + // Extract and load optional Q objective part + if (mprob.qobj != NULL) + { + cprob.nQElem = mxGetNzmax(mprob.qobj); + int* qObjRow = (int*)mxCalloc(cprob.nQElem, sizeof(int)); + int* qObjCol = (int*)mxCalloc(cprob.nQElem, sizeof(int)); + double* qObjElem = (double*)mxCalloc(cprob.nQElem, sizeof(double)); + if (!qObjRow || !qObjCol || !qObjElem) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + COPTMEX_csc2coo(mprob.qobj, qObjRow, qObjCol, qObjElem); + COPTMEX_CALL(COPT_SetQuadObj(prob, cprob.nQElem, qObjRow, qObjCol, qObjElem)); + + mxFree(qObjRow); + mxFree(qObjCol); + mxFree(qObjElem); + } + + // Extract and load optional quadratic constraint part + if (mprob.quadcon != NULL) + { + for (int i = 0; i < mxGetNumberOfElements(mprob.quadcon); ++i) + { + mxArray* QcMat = mxGetField(mprob.quadcon, i, COPTMEX_MODEL_QCSPMAT); + mxArray* QcRow = mxGetField(mprob.quadcon, i, COPTMEX_MODEL_QCROW); + mxArray* QcCol = mxGetField(mprob.quadcon, i, COPTMEX_MODEL_QCCOL); + mxArray* QcVal = mxGetField(mprob.quadcon, i, COPTMEX_MODEL_QCVAL); + mxArray* QcLinear = mxGetField(mprob.quadcon, i, COPTMEX_MODEL_QCLINEAR); + mxArray* QcSense = mxGetField(mprob.quadcon, i, COPTMEX_MODEL_QCSENSE); + mxArray* QcRhs = mxGetField(mprob.quadcon, i, COPTMEX_MODEL_QCRHS); + mxArray* QcName = mxGetField(mprob.quadcon, i, COPTMEX_MODEL_QCNAME); + + int nQMatElem = 0; + int* qMatRow = NULL; + int* qMatCol = NULL; + double* qMatElem = NULL; + int nQRowElem = 0; + int* qRowMatIdx = NULL; + double* qRowMatElem = NULL; + char qRowSense[2]; + double qRowBound = 0.0; + char qRowName[COPT_BUFFSIZE] = {0}; + + if (QcMat != NULL) + { + nQMatElem = mxGetNzmax(QcMat); + qMatRow = (int*)mxCalloc(nQMatElem, sizeof(int)); + qMatCol = (int*)mxCalloc(nQMatElem, sizeof(int)); + qMatElem = (double*)mxCalloc(nQMatElem, sizeof(double)); + if (!qMatRow || !qMatCol || !qMatElem) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + COPTMEX_csc2coo(QcMat, qMatRow, qMatCol, qMatElem); + } + else + { + if (QcRow != NULL && QcCol != NULL && QcVal != NULL) + { + nQMatElem = mxGetNumberOfElements(QcRow); + qMatRow = (int*)mxCalloc(nQMatElem, sizeof(int)); + qMatCol = (int*)mxCalloc(nQMatElem, sizeof(int)); + if (!qMatRow || !qMatCol) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + double* qMatRow_data = mxGetDoubles(QcRow); + double* qMatCol_data = mxGetDoubles(QcCol); + qMatElem = mxGetDoubles(QcVal); + for (int i = 0; i < nQMatElem; ++i) + { + qMatRow[i] = (int)qMatRow_data[i] - 1; + qMatCol[i] = (int)qMatCol_data[i] - 1; + } + } + } + + if (QcLinear != NULL) + { + if (mxIsSparse(QcLinear)) + { + double* qRowMatElem_data = mxGetDoubles(QcLinear); + for (int i = 0; i < mxGetNzmax(QcLinear); ++i) + { + if (qRowMatElem_data[i] != 0.0) + { + ++nQRowElem; + } + } + if (nQRowElem > 0) + { + qRowMatIdx = (int*)mxCalloc(nQRowElem, sizeof(int)); + qRowMatElem = (double*)mxCalloc(nQRowElem, sizeof(double)); + if (!qRowMatIdx || !qRowMatElem) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + mwIndex* qRowMatIdx_data = mxGetIr(QcLinear); + for (int i = 0, iElem = 0; i < mxGetNzmax(QcLinear); ++i) + { + if (qRowMatElem_data[i] != 0.0) + { + qRowMatIdx[iElem] = (int)qRowMatIdx_data[i]; + qRowMatElem[iElem] = qRowMatElem_data[i]; + iElem++; + } + } + } + } + else + { + double* qRowMatElem_data = mxGetDoubles(QcLinear); + for (int i = 0; i < mxGetNumberOfElements(QcLinear); ++i) + { + if (qRowMatElem_data[i] != 0.0) + { + ++nQRowElem; + } + } + if (nQRowElem > 0) + { + qRowMatIdx = (int*)mxCalloc(nQRowElem, sizeof(int)); + qRowMatElem = (double*)mxCalloc(nQRowElem, sizeof(double)); + if (!qRowMatIdx || !qRowMatElem) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + for (int i = 0, iElem = 0; i < mxGetNumberOfElements(QcLinear); ++i) + { + if (qRowMatElem_data[i] != 0.0) + { + qRowMatIdx[iElem] = i; + qRowMatElem[iElem] = qRowMatElem_data[i]; + iElem++; + } + } + } + } + } + + if (QcSense != NULL) + { + mxGetString(QcSense, qRowSense, 2); + } + else + { + qRowSense[0] = COPT_LESS_EQUAL; + } + + qRowBound = mxGetScalar(QcRhs); + if (mxIsInf(qRowBound)) + { + if (qRowBound > 0) + { + qRowBound = +COPT_INFINITY; + } + else + { + qRowBound = -COPT_INFINITY; + } + } + + if (QcName != NULL) + { + mxGetString(QcName, qRowName, COPT_BUFFSIZE); + } + + COPTMEX_CALL(COPT_AddQConstr(prob, nQRowElem, qRowMatIdx, qRowMatElem, nQMatElem, qMatRow, qMatCol, qMatElem, + qRowSense[0], qRowBound, qRowName)); + + mxFree(qMatRow); + mxFree(qMatCol); + if (QcMat != NULL) + { + mxFree(qMatElem); + } + + if (nQRowElem > 0) + { + mxFree(qRowMatIdx); + mxFree(qRowMatElem); + } + } + } + + // Extract and load the optional advanced information + if (mprob.varbasis != NULL && mprob.constrbasis != NULL) + { + cprob.colBasis = (int*)mxCalloc(cprob.nCol, sizeof(int)); + cprob.rowBasis = (int*)mxCalloc(cprob.nRow, sizeof(int)); + if (!cprob.colBasis || !cprob.rowBasis) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + double* colBasis_data = mxGetDoubles(mprob.varbasis); + double* rowBasis_data = mxGetDoubles(mprob.constrbasis); + for (int i = 0; i < cprob.nCol; ++i) + { + cprob.colBasis[i] = (int)colBasis_data[i]; + } + for (int i = 0; i < cprob.nRow; ++i) + { + cprob.rowBasis[i] = (int)rowBasis_data[i]; + } + + COPTMEX_CALL(COPT_SetBasis(prob, cprob.colBasis, cprob.rowBasis)); + + mxFree(cprob.colBasis); + mxFree(cprob.rowBasis); + } + + if (mprob.value != NULL && mprob.slack != NULL && mprob.dual != NULL && mprob.redcost != NULL) + { + double* colValue = mxGetDoubles(mprob.value); + double* colDual = mxGetDoubles(mprob.redcost); + double* rowSlack = mxGetDoubles(mprob.slack); + double* rowDual = mxGetDoubles(mprob.dual); + + COPTMEX_CALL(COPT_SetLpSolution(prob, colValue, rowSlack, rowDual, colDual)); + } + + if (mprob.mipstart != NULL) + { + int nRowCnt = 0; + int* rowIdx = NULL; + double* rowElem = NULL; + + if (mxIsSparse(mprob.mipstart)) + { + nRowCnt = mxGetNzmax(mprob.mipstart); + rowIdx = (int*)mxCalloc(nRowCnt, sizeof(int)); + if (!rowIdx) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + mwIndex* rowIdx_data = mxGetIr(mprob.mipstart); + for (int i = 0; i < nRowCnt; ++i) + { + rowIdx[i] = rowIdx_data[i]; + } + rowElem = mxGetDoubles(mprob.mipstart); + + COPTMEX_CALL(COPT_AddMipStart(prob, nRowCnt, rowIdx, rowElem)); + + mxFree(rowIdx); + } + else + { + double* rowElem_data = mxGetDoubles(mprob.mipstart); + + nRowCnt = mxGetNumberOfElements(mprob.mipstart); + rowElem = (double*)mxCalloc(nRowCnt, sizeof(double)); + if (!rowElem) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + for (int i = 0; i < nRowCnt; ++i) + { + if (mxIsNaN(rowElem_data[i])) + { + rowElem[i] = COPT_UNDEFINED; + } + else + { + rowElem[i] = rowElem_data[i]; + } + } + + COPTMEX_CALL(COPT_AddMipStart(prob, nRowCnt, NULL, rowElem)); + + mxFree(rowElem); + } + } + +exit_cleanup: + if (cprob.colLower != NULL) + { + mxFree(cprob.colLower); + } + if (cprob.colUpper != NULL) + { + mxFree(cprob.colUpper); + } + if (cprob.rowLower != NULL) + { + mxFree(cprob.rowLower); + } + if (cprob.rowUpper != NULL) + { + mxFree(cprob.rowUpper); + } + return retcode; +} + +/* Extract IIS information */ +static int COPTMEX_getIIS(copt_prob* prob, mxArray** out_iis) +{ + int retcode = COPT_RETCODE_OK; + int nRow = 0, nCol = 0, nSos = 0, nIndicator = 0; + int hasIIS = 0; + int isMinIIS = 0; + mxArray* iisInfo = NULL; + coptmex_ciisinfo ciisinfo; + coptmex_miisinfo miisinfo; + + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_HASIIS, &hasIIS)); + if (hasIIS == 0) + { + *out_iis = NULL; + goto exit_cleanup; + } + + COPTMEX_initCIISInfo(&ciisinfo); + COPTMEX_initMIISInfo(&miisinfo); + + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_ROWS, &nRow)); + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_COLS, &nCol)); + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_SOSS, &nSos)); + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_INDICATORS, &nIndicator)); + + miisinfo.isminiis = mxCreateDoubleMatrix(1, 1, mxREAL); + if (!miisinfo.isminiis) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + if (nCol > 0) + { + miisinfo.varlb = mxCreateLogicalMatrix(nCol, 1); + miisinfo.varub = mxCreateLogicalMatrix(nCol, 1); + if (!miisinfo.varlb || !miisinfo.varub) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + } + + if (nRow > 0) + { + miisinfo.constrlb = mxCreateLogicalMatrix(nRow, 1); + miisinfo.construb = mxCreateLogicalMatrix(nRow, 1); + if (!miisinfo.constrlb || !miisinfo.construb) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + } + + if (nSos > 0) + { + miisinfo.sos = mxCreateLogicalMatrix(nSos, 1); + if (!miisinfo.sos) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + } + + if (nIndicator > 0) + { + miisinfo.indicator = mxCreateLogicalMatrix(nIndicator, 1); + if (!miisinfo.indicator) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + } + + if (nCol > 0) + { + ciisinfo.colLowerIIS = (int*)mxCalloc(nCol, sizeof(int)); + ciisinfo.colUpperIIS = (int*)mxCalloc(nCol, sizeof(int)); + if (!ciisinfo.colLowerIIS || !ciisinfo.colUpperIIS) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + } + + if (nRow > 0) + { + ciisinfo.rowLowerIIS = (int*)mxCalloc(nRow, sizeof(int)); + ciisinfo.rowUpperIIS = (int*)mxCalloc(nRow, sizeof(int)); + if (!ciisinfo.rowLowerIIS || !ciisinfo.rowUpperIIS) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + } + + if (nSos > 0) + { + ciisinfo.sosIIS = (int*)mxCalloc(nSos, sizeof(int)); + if (!ciisinfo.sosIIS) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + } + + if (nIndicator > 0) + { + ciisinfo.indicatorIIS = (int*)mxCalloc(nIndicator, sizeof(int)); + if (!ciisinfo.indicatorIIS) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + } + + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_ISMINIIS, &isMinIIS)); + + if (nCol > 0) + { + COPTMEX_CALL(COPT_GetColLowerIIS(prob, nCol, NULL, ciisinfo.colLowerIIS)); + COPTMEX_CALL(COPT_GetColUpperIIS(prob, nCol, NULL, ciisinfo.colUpperIIS)); + } + + if (nRow > 0) + { + COPTMEX_CALL(COPT_GetRowLowerIIS(prob, nRow, NULL, ciisinfo.rowLowerIIS)); + COPTMEX_CALL(COPT_GetRowUpperIIS(prob, nRow, NULL, ciisinfo.rowUpperIIS)); + } + + if (nSos > 0) + { + COPTMEX_CALL(COPT_GetSOSIIS(prob, nSos, NULL, ciisinfo.sosIIS)); + } + + if (nIndicator > 0) + { + COPTMEX_CALL(COPT_GetIndicatorIIS(prob, nIndicator, NULL, ciisinfo.indicatorIIS)); + } + + *mxGetDoubles(miisinfo.isminiis) = isMinIIS; + + if (nCol > 0) + { + mxLogical* colLowerIIS_data = mxGetLogicals(miisinfo.varlb); + mxLogical* colUpperIIS_data = mxGetLogicals(miisinfo.varub); + for (int i = 0; i < nCol; ++i) + { + colLowerIIS_data[i] = ciisinfo.colLowerIIS[i]; + colUpperIIS_data[i] = ciisinfo.colUpperIIS[i]; + } + mxFree(ciisinfo.colLowerIIS); + mxFree(ciisinfo.colUpperIIS); + } + + if (nRow > 0) + { + mxLogical* rowLowerIIS_data = mxGetLogicals(miisinfo.constrlb); + mxLogical* rowUpperIIS_data = mxGetLogicals(miisinfo.construb); + for (int i = 0; i < nRow; ++i) + { + rowLowerIIS_data[i] = ciisinfo.rowLowerIIS[i]; + rowUpperIIS_data[i] = ciisinfo.rowUpperIIS[i]; + } + mxFree(ciisinfo.rowLowerIIS); + mxFree(ciisinfo.rowUpperIIS); + } + + if (nSos > 0) + { + mxLogical* sosIIS_data = mxGetLogicals(miisinfo.sos); + for (int i = 0; i < nSos; ++i) + { + sosIIS_data[i] = ciisinfo.sosIIS[i]; + } + mxFree(ciisinfo.sosIIS); + } + + if (nIndicator > 0) + { + mxLogical* indicatorIIS_data = mxGetLogicals(miisinfo.indicator); + for (int i = 0; i < nIndicator; ++i) + { + indicatorIIS_data[i] = ciisinfo.indicatorIIS[i]; + } + mxFree(ciisinfo.indicatorIIS); + } + + iisInfo = mxCreateStructMatrix(1, 1, 0, NULL); + if (!iisInfo) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + // 'isminiis' + mxAddField(iisInfo, COPTMEX_IIS_ISMINIIS); + mxSetField(iisInfo, 0, COPTMEX_IIS_ISMINIIS, miisinfo.isminiis); + + if (nCol > 0) + { + // 'varlb' + mxAddField(iisInfo, COPTMEX_IIS_VARLB); + mxSetField(iisInfo, 0, COPTMEX_IIS_VARLB, miisinfo.varlb); + // 'varub' + mxAddField(iisInfo, COPTMEX_IIS_VARUB); + mxSetField(iisInfo, 0, COPTMEX_IIS_VARUB, miisinfo.varub); + } + + if (nRow > 0) + { + // 'constrlb' + mxAddField(iisInfo, COPTMEX_IIS_CONSTRLB); + mxSetField(iisInfo, 0, COPTMEX_IIS_CONSTRLB, miisinfo.constrlb); + // 'construb' + mxAddField(iisInfo, COPTMEX_IIS_CONSTRUB); + mxSetField(iisInfo, 0, COPTMEX_IIS_CONSTRUB, miisinfo.construb); + } + + if (nSos > 0) + { + // 'sos' + mxAddField(iisInfo, COPTMEX_IIS_SOS); + mxSetField(iisInfo, 0, COPTMEX_IIS_SOS, miisinfo.sos); + } + + if (nIndicator > 0) + { + // 'indicator' + mxAddField(iisInfo, COPTMEX_IIS_INDICATOR); + mxSetField(iisInfo, 0, COPTMEX_IIS_INDICATOR, miisinfo.indicator); + } + + // Write out IIS problem + COPTMEX_CALL(COPT_WriteIIS(prob, "result.iis")); + + *out_iis = iisInfo; + +exit_cleanup: + if (retcode != COPT_RETCODE_OK) + { + *out_iis = NULL; + } + + return retcode; +} + +/* Compute IIS for infeasible problem */ +int COPTMEX_computeIIS(copt_prob* prob, mxArray** out_iis, int ifRetResult) +{ + int retcode = COPT_RETCODE_OK; + int modelStatus = 0; + int isMIP = 0; + + // Try to find IIS for the given problem + COPTMEX_CALL(COPT_ComputeIIS(prob)); + + // Extract IIS information + if (ifRetResult == 1) + { + COPTMEX_CALL(COPTMEX_getIIS(prob, out_iis)); + } + +exit_cleanup: + return retcode; +} + +/* Extract feasibility relaxation information */ +static int COPTMEX_getFeasRelax(copt_prob* prob, mxArray** out_relax) +{ + int retcode = COPT_RETCODE_OK; + int nRow = 0, nCol = 0; + int hasFeasRelax = 0; + mxArray* relaxInfo = NULL; + coptmex_crelaxinfo crelaxinfo; + coptmex_mrelaxinfo mrelaxinfo; + + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_HASFEASRELAXSOL, &hasFeasRelax)); + if (hasFeasRelax == 0) + { + *out_relax = NULL; + goto exit_cleanup; + } + + COPTMEX_initCRelaxInfo(&crelaxinfo); + COPTMEX_initMRelaxInfo(&mrelaxinfo); + + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_ROWS, &nRow)); + COPTMEX_CALL(COPT_GetIntAttr(prob, COPT_INTATTR_COLS, &nCol)); + + mrelaxinfo.relaxobj = mxCreateDoubleMatrix(1, 1, mxREAL); + if (!mrelaxinfo.relaxobj) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + if (nCol > 0) + { + mrelaxinfo.relaxvalue = mxCreateDoubleMatrix(nCol, 1, mxREAL); + mrelaxinfo.relaxlb = mxCreateDoubleMatrix(nCol, 1, mxREAL); + mrelaxinfo.relaxub = mxCreateDoubleMatrix(nCol, 1, mxREAL); + if (!mrelaxinfo.relaxvalue || !mrelaxinfo.relaxlb || !mrelaxinfo.relaxub) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + } + + if (nRow > 0) + { + mrelaxinfo.relaxlhs = mxCreateDoubleMatrix(nRow, 1, mxREAL); + mrelaxinfo.relaxrhs = mxCreateDoubleMatrix(nRow, 1, mxREAL); + if (!mrelaxinfo.relaxlhs || !mrelaxinfo.relaxrhs) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + } + + if (nCol > 0) + { + crelaxinfo.colValue = mxGetDoubles(mrelaxinfo.relaxvalue); + crelaxinfo.colLowRlx = mxGetDoubles(mrelaxinfo.relaxlb); + crelaxinfo.colUppRlx = mxGetDoubles(mrelaxinfo.relaxub); + } + + if (nRow > 0) + { + crelaxinfo.rowLowRlx = mxGetDoubles(mrelaxinfo.relaxlhs); + crelaxinfo.rowUppRlx = mxGetDoubles(mrelaxinfo.relaxrhs); + } + + COPTMEX_CALL(COPT_GetDblAttr(prob, COPT_DBLATTR_FEASRELAXOBJ, &crelaxinfo.dObjVal)); + *mxGetDoubles(mrelaxinfo.relaxobj) = crelaxinfo.dObjVal; + + if (nCol > 0) + { + COPTMEX_CALL(COPT_GetColInfo(prob, COPT_DBLINFO_RELAXVALUE, nCol, NULL, crelaxinfo.colValue)); + COPTMEX_CALL(COPT_GetColInfo(prob, COPT_DBLINFO_RELAXLB, nCol, NULL, crelaxinfo.colLowRlx)); + COPTMEX_CALL(COPT_GetColInfo(prob, COPT_DBLINFO_RELAXUB, nCol, NULL, crelaxinfo.colUppRlx)); + } + + if (nRow > 0) + { + COPTMEX_CALL(COPT_GetRowInfo(prob, COPT_DBLINFO_RELAXLB, nRow, NULL, crelaxinfo.rowLowRlx)); + COPTMEX_CALL(COPT_GetRowInfo(prob, COPT_DBLINFO_RELAXUB, nRow, NULL, crelaxinfo.rowUppRlx)); + } + + relaxInfo = mxCreateStructMatrix(1, 1, 0, NULL); + if (!relaxInfo) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + // 'relaxobj' + mxAddField(relaxInfo, COPTMEX_FEASRELAX_OBJ); + mxSetField(relaxInfo, 0, COPTMEX_FEASRELAX_OBJ, mrelaxinfo.relaxobj); + + if (nCol > 0) + { + // 'relaxvalue' + mxAddField(relaxInfo, COPTMEX_FEASRELAX_VALUE); + mxSetField(relaxInfo, 0, COPTMEX_FEASRELAX_VALUE, mrelaxinfo.relaxvalue); + // 'relaxlb' + mxAddField(relaxInfo, COPTMEX_FEASRELAX_LB); + mxSetField(relaxInfo, 0, COPTMEX_FEASRELAX_LB, mrelaxinfo.relaxlb); + // 'relaxub' + mxAddField(relaxInfo, COPTMEX_FEASRELAX_UB); + mxSetField(relaxInfo, 0, COPTMEX_FEASRELAX_UB, mrelaxinfo.relaxub); + } + + if (nRow > 0) + { + // 'relaxlhs' + mxAddField(relaxInfo, COPTMEX_FEASRELAX_LHS); + mxSetField(relaxInfo, 0, COPTMEX_FEASRELAX_LHS, mrelaxinfo.relaxlhs); + // 'relaxrhs' + mxAddField(relaxInfo, COPTMEX_FEASRELAX_RHS); + mxSetField(relaxInfo, 0, COPTMEX_FEASRELAX_RHS, mrelaxinfo.relaxrhs); + } + + // Write out feasibility relaxation problem + COPTMEX_CALL(COPT_WriteRelax(prob, "result.relax")); + + *out_relax = relaxInfo; + +exit_cleanup: + if (retcode != COPT_RETCODE_OK) + { + *out_relax = NULL; + } + + return retcode; +} + +int COPTMEX_feasRelax(copt_prob* prob, const mxArray* penalty, mxArray** out_relax, int ifRetResult) +{ + int retcode = COPT_RETCODE_OK; + + mxArray* lbpen = NULL; + mxArray* ubpen = NULL; + mxArray* rhspen = NULL; + mxArray* upppen = NULL; + + double* colLowPen = NULL; + double* colUppPen = NULL; + double* rowBndPen = NULL; + double* rowUppPen = NULL; + + if (COPTMEX_checkPenalty(prob, penalty) == 0) + { + goto exit_cleanup; + } + + lbpen = mxGetField(penalty, 0, COPTMEX_PENALTY_LBPEN); + ubpen = mxGetField(penalty, 0, COPTMEX_PENALTY_UBPEN); + rhspen = mxGetField(penalty, 0, COPTMEX_PENALTY_RHSPEN); + upppen = mxGetField(penalty, 0, COPTMEX_PENALTY_UPPPEN); + + if (lbpen != NULL) + { + colLowPen = mxGetDoubles(lbpen); + } + if (ubpen != NULL) + { + colUppPen = mxGetDoubles(ubpen); + } + if (rhspen != NULL) + { + rowBndPen = mxGetDoubles(rhspen); + } + if (upppen != NULL) + { + rowUppPen = mxGetDoubles(upppen); + } + + // Compute the feasibility relaxation + COPTMEX_CALL(COPT_FeasRelax(prob, colLowPen, colUppPen, rowBndPen, rowUppPen)); + + // Extract feasibility relaxation information + if (ifRetResult == 1) + { + COPTMEX_CALL(COPTMEX_getFeasRelax(prob, out_relax)); + } + +exit_cleanup: + return retcode; +} + +/* Get default parameters */ +int COPTMEX_getDefaultParams(copt_prob* prob, mxArray** out_param) +{ + int retcode = COPT_RETCODE_OK; + mxArray* defParam = NULL; + int nDefVal = 0; + double dDefVal = 0.0; + + defParam = mxCreateStructMatrix(1, 1, 0, NULL); + if (!defParam) + { + retcode = COPT_RETCODE_MEMORY; + goto exit_cleanup; + } + + /* + * Double parameters + */ + { + // 'timelimit' + COPTMEX_CALL(COPT_GetDblParamDef(prob, COPT_DBLPARAM_TIMELIMIT, &dDefVal)); + + mxArray* dblParam = mxCreateDoubleScalar(dDefVal); + mxAddField(defParam, COPT_DBLPARAM_TIMELIMIT); + mxSetField(defParam, 0, COPT_DBLPARAM_TIMELIMIT, dblParam); + } + { + // 'matrixtol' + COPTMEX_CALL(COPT_GetDblParamDef(prob, COPT_DBLPARAM_MATRIXTOL, &dDefVal)); + + mxArray* dblParam = mxCreateDoubleScalar(dDefVal); + mxAddField(defParam, COPT_DBLPARAM_MATRIXTOL); + mxSetField(defParam, 0, COPT_DBLPARAM_MATRIXTOL, dblParam); + } + { + // 'feastol' + COPTMEX_CALL(COPT_GetDblParamDef(prob, COPT_DBLPARAM_FEASTOL, &dDefVal)); + + mxArray* dblParam = mxCreateDoubleScalar(dDefVal); + mxAddField(defParam, COPT_DBLPARAM_FEASTOL); + mxSetField(defParam, 0, COPT_DBLPARAM_FEASTOL, dblParam); + } + { + // 'dualtol' + COPTMEX_CALL(COPT_GetDblParamDef(prob, COPT_DBLPARAM_DUALTOL, &dDefVal)); + + mxArray* dblParam = mxCreateDoubleScalar(dDefVal); + mxAddField(defParam, COPT_DBLPARAM_DUALTOL); + mxSetField(defParam, 0, COPT_DBLPARAM_DUALTOL, dblParam); + } + { + // 'inttol' + COPTMEX_CALL(COPT_GetDblParamDef(prob, COPT_DBLPARAM_INTTOL, &dDefVal)); + + mxArray* dblParam = mxCreateDoubleScalar(dDefVal); + mxAddField(defParam, COPT_DBLPARAM_INTTOL); + mxSetField(defParam, 0, COPT_DBLPARAM_INTTOL, dblParam); + } + { + // 'relgap' + COPTMEX_CALL(COPT_GetDblParamDef(prob, COPT_DBLPARAM_RELGAP, &dDefVal)); + + mxArray* dblParam = mxCreateDoubleScalar(dDefVal); + mxAddField(defParam, COPT_DBLPARAM_RELGAP); + mxSetField(defParam, 0, COPT_DBLPARAM_RELGAP, dblParam); + } + { + // 'absgap' + COPTMEX_CALL(COPT_GetDblParamDef(prob, COPT_DBLPARAM_ABSGAP, &dDefVal)); + + mxArray* dblParam = mxCreateDoubleScalar(dDefVal); + mxAddField(defParam, COPT_DBLPARAM_ABSGAP); + mxSetField(defParam, 0, COPT_DBLPARAM_ABSGAP, dblParam); + } + { + // 'tunetimelimit' + COPTMEX_CALL(COPT_GetDblParamDef(prob, COPT_DBLPARAM_TUNETIMELIMIT, &dDefVal)); + + mxArray* dblParam = mxCreateDoubleScalar(dDefVal); + mxAddField(defParam, COPT_DBLPARAM_TUNETIMELIMIT); + mxSetField(defParam, 0, COPT_DBLPARAM_TUNETIMELIMIT, dblParam); + } + { + // 'tunetargettime' + COPTMEX_CALL(COPT_GetDblParamDef(prob, COPT_DBLPARAM_TUNETARGETTIME, &dDefVal)); + + mxArray* dblParam = mxCreateDoubleScalar(dDefVal); + mxAddField(defParam, COPT_DBLPARAM_TUNETARGETTIME); + mxSetField(defParam, 0, COPT_DBLPARAM_TUNETARGETTIME, dblParam); + } + { + // 'tunetargetrelgap' + COPTMEX_CALL(COPT_GetDblParamDef(prob, COPT_DBLPARAM_TUNETARGETRELGAP, &dDefVal)); + + mxArray* dblParam = mxCreateDoubleScalar(dDefVal); + mxAddField(defParam, COPT_DBLPARAM_TUNETARGETRELGAP); + mxSetField(defParam, 0, COPT_DBLPARAM_TUNETARGETRELGAP, dblParam); + } + + /* + * Integer parameters + */ + { + // 'logging' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_LOGGING, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_LOGGING); + mxSetField(defParam, 0, COPT_INTPARAM_LOGGING, intParam); + } + { + // 'logtoconsole' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_LOGTOCONSOLE, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_LOGTOCONSOLE); + mxSetField(defParam, 0, COPT_INTPARAM_LOGTOCONSOLE, intParam); + } + { + // 'presolve' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_PRESOLVE, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_PRESOLVE); + mxSetField(defParam, 0, COPT_INTPARAM_PRESOLVE, intParam); + } + { + // 'scaling' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_SCALING, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_SCALING); + mxSetField(defParam, 0, COPT_INTPARAM_SCALING, intParam); + } + { + // 'dualize' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_DUALIZE, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_DUALIZE); + mxSetField(defParam, 0, COPT_INTPARAM_DUALIZE, intParam); + } + { + // 'lpmethod' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_LPMETHOD, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_LPMETHOD); + mxSetField(defParam, 0, COPT_INTPARAM_LPMETHOD, intParam); + } + { + // 'reqfarkasray' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_REQFARKASRAY, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_REQFARKASRAY); + mxSetField(defParam, 0, COPT_INTPARAM_REQFARKASRAY, intParam); + } + { + // 'dualprice' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_DUALPRICE, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_DUALPRICE); + mxSetField(defParam, 0, COPT_INTPARAM_DUALPRICE, intParam); + } + { + // 'dualperturb' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_DUALPERTURB, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_DUALPERTURB); + mxSetField(defParam, 0, COPT_INTPARAM_DUALPERTURB, intParam); + } + { + // 'cutlevel' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_CUTLEVEL, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_CUTLEVEL); + mxSetField(defParam, 0, COPT_INTPARAM_CUTLEVEL, intParam); + } + { + // 'rootcutlevel' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_ROOTCUTLEVEL, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_ROOTCUTLEVEL); + mxSetField(defParam, 0, COPT_INTPARAM_ROOTCUTLEVEL, intParam); + } + { + // 'treecutlevel' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_TREECUTLEVEL, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_TREECUTLEVEL); + mxSetField(defParam, 0, COPT_INTPARAM_TREECUTLEVEL, intParam); + } + { + // 'rootcutrounds' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_ROOTCUTROUNDS, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_ROOTCUTROUNDS); + mxSetField(defParam, 0, COPT_INTPARAM_ROOTCUTROUNDS, intParam); + } + { + // 'nodecutrounds' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_NODECUTROUNDS, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_NODECUTROUNDS); + mxSetField(defParam, 0, COPT_INTPARAM_NODECUTROUNDS, intParam); + } + { + // 'heurlevel' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_HEURLEVEL, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_HEURLEVEL); + mxSetField(defParam, 0, COPT_INTPARAM_HEURLEVEL, intParam); + } + { + // 'roundingheurlevel' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_ROUNDINGHEURLEVEL, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_ROUNDINGHEURLEVEL); + mxSetField(defParam, 0, COPT_INTPARAM_ROUNDINGHEURLEVEL, intParam); + } + { + // 'divingheurlevel' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_DIVINGHEURLEVEL, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_DIVINGHEURLEVEL); + mxSetField(defParam, 0, COPT_INTPARAM_DIVINGHEURLEVEL, intParam); + } + { + // 'submipheurlevel' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_SUBMIPHEURLEVEL, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_SUBMIPHEURLEVEL); + mxSetField(defParam, 0, COPT_INTPARAM_SUBMIPHEURLEVEL, intParam); + } + { + // 'strongbranching' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_STRONGBRANCHING, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_STRONGBRANCHING); + mxSetField(defParam, 0, COPT_INTPARAM_STRONGBRANCHING, intParam); + } + { + // 'conflictanalysis' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_CONFLICTANALYSIS, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_CONFLICTANALYSIS); + mxSetField(defParam, 0, COPT_INTPARAM_CONFLICTANALYSIS, intParam); + } + { + // 'nodelimit' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_NODELIMIT, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_NODELIMIT); + mxSetField(defParam, 0, COPT_INTPARAM_NODELIMIT, intParam); + } + { + // 'miptasks' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_MIPTASKS, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_MIPTASKS); + mxSetField(defParam, 0, COPT_INTPARAM_MIPTASKS, intParam); + } + { + // 'barhomogeneous' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_BARHOMOGENEOUS, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_BARHOMOGENEOUS); + mxSetField(defParam, 0, COPT_INTPARAM_BARHOMOGENEOUS, intParam); + } + { + // 'barorder' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_BARORDER, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_BARORDER); + mxSetField(defParam, 0, COPT_INTPARAM_BARORDER, intParam); + } + { + // 'bariterlimit' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_BARITERLIMIT, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_BARITERLIMIT); + mxSetField(defParam, 0, COPT_INTPARAM_BARITERLIMIT, intParam); + } + { + // 'threads' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_THREADS, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_THREADS); + mxSetField(defParam, 0, COPT_INTPARAM_THREADS, intParam); + } + { + // 'barthreads' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_BARTHREADS, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_BARTHREADS); + mxSetField(defParam, 0, COPT_INTPARAM_BARTHREADS, intParam); + } + { + // 'simplexthreads' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_SIMPLEXTHREADS, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_SIMPLEXTHREADS); + mxSetField(defParam, 0, COPT_INTPARAM_SIMPLEXTHREADS, intParam); + } + { + // 'crossoverthreads' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_CROSSOVERTHREADS, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_CROSSOVERTHREADS); + mxSetField(defParam, 0, COPT_INTPARAM_CROSSOVERTHREADS, intParam); + } + { + // 'crossover' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_CROSSOVER, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_CROSSOVER); + mxSetField(defParam, 0, COPT_INTPARAM_CROSSOVER, intParam); + } + { + // 'sdpmethod' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_SDPMETHOD, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_SDPMETHOD); + mxSetField(defParam, 0, COPT_INTPARAM_SDPMETHOD, intParam); + } + { + // 'iismethod' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_IISMETHOD, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_IISMETHOD); + mxSetField(defParam, 0, COPT_INTPARAM_IISMETHOD, intParam); + } + { + // 'feasrelaxmode' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_FEASRELAXMODE, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_FEASRELAXMODE); + mxSetField(defParam, 0, COPT_INTPARAM_FEASRELAXMODE, intParam); + } + { + // 'mipstartmode' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_MIPSTARTMODE, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_MIPSTARTMODE); + mxSetField(defParam, 0, COPT_INTPARAM_MIPSTARTMODE, intParam); + } + { + // 'mipstartnodelimit' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_MIPSTARTNODELIMIT, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_MIPSTARTNODELIMIT); + mxSetField(defParam, 0, COPT_INTPARAM_MIPSTARTNODELIMIT, intParam); + } + { + // 'tunemethod' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_TUNEMETHOD, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_TUNEMETHOD); + mxSetField(defParam, 0, COPT_INTPARAM_TUNEMETHOD, intParam); + } + { + // 'tunemode' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_TUNEMODE, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_TUNEMODE); + mxSetField(defParam, 0, COPT_INTPARAM_TUNEMODE, intParam); + } + { + // 'tunemeasure' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_TUNEMEASURE, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_TUNEMEASURE); + mxSetField(defParam, 0, COPT_INTPARAM_TUNEMEASURE, intParam); + } + { + // 'tunepermutes' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_TUNEPERMUTES, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_TUNEPERMUTES); + mxSetField(defParam, 0, COPT_INTPARAM_TUNEPERMUTES, intParam); + } + { + // 'tuneoutputlevel' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_TUNEOUTPUTLEVEL, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_TUNEOUTPUTLEVEL); + mxSetField(defParam, 0, COPT_INTPARAM_TUNEOUTPUTLEVEL, intParam); + } + { + // 'lazyconstraints' + COPTMEX_CALL(COPT_GetIntParamDef(prob, COPT_INTPARAM_LAZYCONSTRAINTS, &nDefVal)); + + mxArray* intParam = mxCreateDoubleScalar((double)nDefVal); + mxAddField(defParam, COPT_INTPARAM_LAZYCONSTRAINTS); + mxSetField(defParam, 0, COPT_INTPARAM_LAZYCONSTRAINTS, intParam); + } + + *out_param = defParam; + +exit_cleanup: + if (retcode != COPT_RETCODE_OK) + { + *out_param = NULL; + } + return retcode; +} diff --git a/src/coptmex.h b/src/coptmex.h index 11831bf..3eb9bab 100755 --- a/src/coptmex.h +++ b/src/coptmex.h @@ -1,481 +1,503 @@ -#ifndef __COPTMEX_H__ -#define __COPTMEX_H__ - -#include "copt.h" -#include "mex.h" - -#include -#include -#include - -#ifdef _WIN32 -#define mystrcmp _stricmp -#else -#include -#define mystrcmp strcasecmp -#endif - -#ifndef NDEBUG -#define COPTMEX_CALL(func) \ - do { \ - if ((retcode = (func)) != COPT_RETCODE_OK) { \ - mexPrintf("ERROR %d: %s:%d\n", retcode, __FILE__, __LINE__); \ - goto exit_cleanup; \ - } \ - } while (0) -#else -#define COPTMEX_CALL(func) \ - do { if ((retcode = (func)) != COPT_RETCODE_OK) goto exit_cleanup; } while (0) -#endif - -/* The solution status in string format */ -#define COPTMEX_STATUS_UNSTARTED "unstarted" -#define COPTMEX_STATUS_OPTIMAL "optimal" -#define COPTMEX_STATUS_INFEASIBLE "infeasible" -#define COPTMEX_STATUS_UNBOUNDED "unbounded" -#define COPTMEX_STATUS_INF_OF_UNB "inf_or_unb" -#define COPTMEX_STATUS_NUMERICAL "numerical" -#define COPTMEX_STATUS_NODELIMIT "nodelimit" -#define COPTMEX_STATUS_TIMEOUT "timeout" -#define COPTMEX_STATUS_UNFINISHED "unfinished" -#define COPTMEX_STATUS_INTERRUPTED "interrupted" - -/* The main part of model struct fields */ -#define COPTMEX_MODEL_OBJSEN "objsen" -#define COPTMEX_MODEL_OBJCON "objcon" -#define COPTMEX_MODEL_A "A" -#define COPTMEX_MODEL_OBJ "obj" -#define COPTMEX_MODEL_LB "lb" -#define COPTMEX_MODEL_UB "ub" -#define COPTMEX_MODEL_VTYPE "vtype" -#define COPTMEX_MODEL_VARNAME "varnames" -#define COPTMEX_MODEL_SENSE "sense" -#define COPTMEX_MODEL_LHS "lhs" -#define COPTMEX_MODEL_RHS "rhs" -#define COPTMEX_MODEL_CONNAME "constrnames" - -/* The optional part of model struct fields */ -#define COPTMEX_MODEL_SOS "sos" -#define COPTMEX_MODEL_SOSTYPE "type" -#define COPTMEX_MODEL_SOSVARS "vars" -#define COPTMEX_MODEL_SOSWEIGHT "weights" - -#define COPTMEX_MODEL_INDICATOR "indicator" -#define COPTMEX_MODEL_INDICBINVAR "binvar" -#define COPTMEX_MODEL_INDICBINVAL "binval" -#define COPTMEX_MODEL_INDICROW "a" -#define COPTMEX_MODEL_INDICSENSE "sense" -#define COPTMEX_MODEL_INDICRHS "rhs" - -#define COPTMEX_MODEL_QUADOBJ "Q" - -#define COPTMEX_MODEL_QUADCON "quadcon" -#define COPTMEX_MODEL_QCSPMAT "Qc" -#define COPTMEX_MODEL_QCROW "Qrow" -#define COPTMEX_MODEL_QCCOL "Qcol" -#define COPTMEX_MODEL_QCVAL "Qval" -#define COPTMEX_MODEL_QCLINEAR "q" -#define COPTMEX_MODEL_QCSENSE "sense" -#define COPTMEX_MODEL_QCRHS "rhs" -#define COPTMEX_MODEL_QCNAME "name" - -#define COPTMEX_MODEL_CONE "cone" -#define COPTMEX_MODEL_CONETYPE "type" -#define COPTMEX_MODEL_CONEVARS "vars" - -#define COPTMEX_MODEL_CONEDATA "conedata" -#define COPTMEX_MODEL_CONE_OBJSEN "objsen" -#define COPTMEX_MODEL_CONE_OBJCON "objcon" -#define COPTMEX_MODEL_CONE_C "c" -#define COPTMEX_MODEL_CONE_A "A" -#define COPTMEX_MODEL_CONE_B "b" -#define COPTMEX_MODEL_CONE_K "K" -#define COPTMEX_MODEL_CONE_Q "Q" - -#define COPTMEX_MODEL_CONEK_F "f" -#define COPTMEX_MODEL_CONEK_L "l" -#define COPTMEX_MODEL_CONEK_Q "q" -#define COPTMEX_MODEL_CONEK_R "r" -#define COPTMEX_MODEL_CONEK_S "s" - -/* The penalty struct fields */ -#define COPTMEX_PENALTY_LBPEN "lbpen" -#define COPTMEX_PENALTY_UBPEN "ubpen" -#define COPTMEX_PENALTY_RHSPEN "rhspen" -#define COPTMEX_PENALTY_UPPPEN "upppen" - -/* The result struct fields */ -#define COPTMEX_RESULT_STATUS "status" -#define COPTMEX_RESULT_SIMITER "simplexiter" -#define COPTMEX_RESULT_BARITER "barrieriter" -#define COPTMEX_RESULT_NODECNT "nodecnt" -#define COPTMEX_RESULT_BESTGAP "bestgap" -#define COPTMEX_RESULT_SOLVETIME "solvingtime" -#define COPTMEX_RESULT_OBJVAL "objval" -#define COPTMEX_RESULT_BESTBND "bestbnd" -#define COPTMEX_RESULT_VARBASIS "varbasis" -#define COPTMEX_RESULT_CONBASIS "constrbasis" -#define COPTMEX_RESULT_VALUE "x" -#define COPTMEX_RESULT_REDCOST "rc" -#define COPTMEX_RESULT_SLACK "slack" -#define COPTMEX_RESULT_DUAL "pi" -#define COPTMEX_RESULT_PRIMALRAY "primalray" -#define COPTMEX_RESULT_DUALFARKAS "dualfarkas" - -#define COPTMEX_RESULT_QCSLACK "qcslack" - -#define COPTMEX_RESULT_POOL "pool" -#define COPTMEX_RESULT_POOLOBJ "objval" -#define COPTMEX_RESULT_POOLXN "xn" - -#define COPTMEX_RESULT_PSDX "psdx" -#define COPTMEX_RESULT_PSDRC "psdrc" -#define COPTMEX_RESULT_PSDSLACK "psdslack" -#define COPTMEX_RESULT_PSDPI "psdpi" - -/* The advanced information */ -#define COPTMEX_ADVINFO_MIPSTART "start" - -/* The IIS result struct fields */ -#define COPTMEX_IIS_ISMINIIS "isminiis" -#define COPTMEX_IIS_VARLB "varlb" -#define COPTMEX_IIS_VARUB "varub" -#define COPTMEX_IIS_CONSTRLB "constrlb" -#define COPTMEX_IIS_CONSTRUB "construb" -#define COPTMEX_IIS_SOS "sos" -#define COPTMEX_IIS_INDICATOR "indicator" - -/* The feasibility relaxation result fields */ -#define COPTMEX_FEASRELAX_OBJ "relaxobj" -#define COPTMEX_FEASRELAX_VALUE "relaxvalue" -#define COPTMEX_FEASRELAX_LB "relaxlb" -#define COPTMEX_FEASRELAX_UB "relaxub" -#define COPTMEX_FEASRELAX_LHS "relaxlhs" -#define COPTMEX_FEASRELAX_RHS "relaxrhs" - -/* The version fields */ -#define COPTMEX_VERSION_MAJOR "major" -#define COPTMEX_VERSION_MINOR "minor" -#define COPTMEX_VERSION_TECHNICAL "technical" - -/* Error types */ -#define COPTMEX_ERROR_BAD_TYPE 0 -#define COPTMEX_ERROR_BAD_NAME 1 -#define COPTMEX_ERROR_BAD_DATA 2 -#define COPTMEX_ERROR_BAD_NUM 3 -#define COPTMEX_ERROR_BAD_API 4 - -typedef struct coptmex_mversion_s { - mxArray *major; - mxArray *minor; - mxArray *technical; -} coptmex_mversion; - -typedef struct coptmex_cprob_s { - /* The main part of problem */ - int nCol; - int nRow; - int nElem; - int nObjSen; - double dObjConst; - - int *colMatBeg; - int *colMatIdx; - double *colMatElem; - - double *colCost; - double *colLower; - double *colUpper; - double *rowLower; - double *rowUpper; - - char *colType; - char *rowSense; - char **colNames; - char **rowNames; - - /* The optional SOS part */ - int nSos; - int nSosSize; - int *sosType; - int *sosMatBeg; - int *sosMatCnt; - int *sosMatIdx; - double *sosMatWt; - - /* The optional indicator part */ - int nIndicator; - - /* The optional cone part */ - int nCone; - int nConeSize; - int *coneType; - int *coneBeg; - int *coneCnt; - int *coneIdx; - - /* The optional Q objective part */ - int nQElem; - - /* The optional quadratic constraint part */ - int nQConstr; - - /* The optional advanced information */ - int hasBasis; - int *colBasis; - int *rowBasis; -} coptmex_cprob; - -typedef struct coptmex_mprob_s { - /* The main part of model */ - mxArray *objsen; - mxArray *objcon; - mxArray *A; - mxArray *obj; - mxArray *lb; - mxArray *ub; - mxArray *vtype; - mxArray *varnames; - mxArray *sense; - mxArray *lhs; - mxArray *rhs; - mxArray *constrnames; - - /* The optional sos part of model */ - mxArray *sos; - - /* The optional indicator part of model */ - mxArray *indicator; - - /* The optional cone part of model */ - mxArray *cone; - - /* The optional Q objective part of model */ - mxArray *qobj; - - /* The optional quadratic constraint part of model */ - mxArray *quadcon; - - /* The optional advanced information */ - mxArray *varbasis; - mxArray *constrbasis; - - mxArray *value; - mxArray *slack; - mxArray *dual; - mxArray *redcost; - - mxArray *mipstart; -} coptmex_mprob; - -typedef struct coptmex_cconeprob_s { - int nCol; - int nRow; - int nElem; - - int nObjSense; - double dObjConst; - - int nFree; - int nPositive; - int nCone; - int nRotateCone; - int nPSD; - - int *coneDim; - int *rotateConeDim; - int *psdDim; - - double *colObj; - - int nQObjElem; - int *qObjRow; - int *qObjCol; - double *qObjElem; - - int *colMatBeg; - int *colMatIdx; - double *colMatElem; - - double *rowRhs; -} coptmex_cconeprob; - -typedef struct coptmex_mconeprob_s { - /* Main cone data */ - mxArray *c; - mxArray *A; - mxArray *b; - - mxArray *K; - mxArray *f; - mxArray *l; - mxArray *q; - mxArray *r; - mxArray *s; - - /* Optional parts */ - mxArray *objsen; - mxArray *objcon; - mxArray *Q; -} coptmex_mconeprob; - -typedef struct coptmex_clpsol_s { - int nRow; - int nCol; - int nPSD; - int nPSDLen; - int nPSDConstr; - int nQConstr; - int hasBasis; - int hasLpSol; - - int nStatus; - int nSimplexIter; - int nBarrierIter; - double dSolvingTime; - double dObjVal; - - int *colBasis; - int *rowBasis; - double *colValue; - double *colDual; - double *rowSlack; - double *rowDual; - double *primalRay; - double *dualFarkas; - - double *qRowSlack; - - double *psdColValue; - double *psdColDual; - double *psdRowSlack; - double *psdRowDual; -} coptmex_clpsol; - -typedef struct coptmex_cmipsol_s { - int nRow; - int nCol; - int hasMipSol; - - int nStatus; - int nSimplexIter; - int nNodeCnt; - double dBestGap; - double dSolvingTime; - double dObjVal; - double dBestBnd; - - double *colValue; - - int nSolPool; -} coptmex_cmipsol; - -typedef struct coptmex_ciisinfo_s { - int isMinIIS; - int *colLowerIIS; - int *colUpperIIS; - int *rowLowerIIS; - int *rowUpperIIS; - int *sosIIS; - int *indicatorIIS; -} coptmex_ciisinfo; - -typedef struct coptmex_crelaxinfo_s { - double dObjVal; - double *colValue; - double *colLowRlx; - double *colUppRlx; - double *rowLowRlx; - double *rowUppRlx; -} coptmex_crelaxinfo; - -typedef struct coptmex_mlpsol_s { - mxArray *status; - mxArray *simplexiter; - mxArray *barrieriter; - mxArray *solvingtime; - mxArray *objval; - mxArray *varbasis; - mxArray *constrbasis; - mxArray *value; - mxArray *redcost; - mxArray *slack; - mxArray *dual; - mxArray *ray; - mxArray *farkas; - mxArray *qcslack; - mxArray *psdcolvalue; - mxArray *psdcoldual; - mxArray *psdrowslack; - mxArray *psdrowdual; -} coptmex_mlpsol; - -typedef struct coptmex_mmipsol_s { - mxArray *status; - mxArray *simplexiter; - mxArray *nodecnt; - mxArray *bestgap; - mxArray *solvingtime; - mxArray *objval; - mxArray *bestbnd; - mxArray *value; - - mxArray *solpool; -} coptmex_mmipsol; - -typedef struct coptmex_miisinfo_s { - mxArray *isminiis; - mxArray *varlb; - mxArray *varub; - mxArray *constrlb; - mxArray *construb; - mxArray *sos; - mxArray *indicator; -} coptmex_miisinfo; - -typedef struct coptmex_mrelaxinfo_s { - mxArray *relaxobj; - mxArray *relaxvalue; - mxArray *relaxlb; - mxArray *relaxub; - mxArray *relaxlhs; - mxArray *relaxrhs; -} coptmex_mrelaxinfo; - -/* Display error message */ -void COPTMEX_errorMsg(int errcode, const char *errinfo); -/* Display banner */ -int COPTMEX_dispBanner(void); - -/* Extract version of COPT */ -int COPTMEX_getVersion(mxArray **out_version); -/* Extract objective sense */ -int COPTMEX_getObjsen(const mxArray *in_objsen, int *out_objsen); -/* Extract and save result */ -int COPTMEX_getResult(copt_prob *prob, mxArray **out_result); -/* Extract model data */ -int COPTMEX_getModel(copt_prob *prob, int nfiles, const mxArray **in_files, mxArray **out_model); - -/* Load parameters to problem */ -int COPTMEX_setParam(copt_prob *prob, const mxArray *in_param); -/* Read optional information from file */ -int COPTMEX_readInfo(copt_prob *prob, const mxArray *in_info); -/* Read model from file */ -int COPTMEX_readModel(copt_prob *prob, const mxArray *in_model); -/* Write model to file */ -int COPTMEX_writeModel(copt_prob *prob, const mxArray *out_file); -/* Extract and load data to model */ -int COPTMEX_loadModel(copt_prob *prob, const mxArray *in_model); - -/* Check if solve problem via cone data */ -int COPTMEX_isConeModel(const mxArray *in_model); -/* Solve cone problem with cone data */ -int COPTMEX_solveConeModel(copt_prob *prob, const mxArray *in_model, mxArray **out_result, int ifRetResult); - -/* Compute IIS for infeasible problem */ -int COPTMEX_computeIIS(copt_prob *prob, mxArray **out_iis, int ifRetResult); - -/* Feasibility relaxation for infeasible problem */ -int COPTMEX_feasRelax(copt_prob *prob, const mxArray *penalty, mxArray **out_relax, int ifRetResult); - -#endif +#ifndef __COPTMEX_H__ +#define __COPTMEX_H__ + +#include "copt.h" +#include "mex.h" + +#include +#include +#include + +#ifdef _WIN32 +#define mystrcmp _stricmp +#else +#include +#define mystrcmp strcasecmp +#endif + +#ifndef NDEBUG +#define COPTMEX_CALL(func) \ + do \ + { \ + if ((retcode = (func)) != COPT_RETCODE_OK) \ + { \ + mexPrintf("ERROR %d: %s:%d\n", retcode, __FILE__, __LINE__); \ + goto exit_cleanup; \ + } \ + } while (0) +#else +#define COPTMEX_CALL(func) \ + do \ + { \ + if ((retcode = (func)) != COPT_RETCODE_OK) \ + goto exit_cleanup; \ + } while (0) +#endif + +/* The solution status in string format */ +#define COPTMEX_STATUS_UNSTARTED "unstarted" +#define COPTMEX_STATUS_OPTIMAL "optimal" +#define COPTMEX_STATUS_INFEASIBLE "infeasible" +#define COPTMEX_STATUS_UNBOUNDED "unbounded" +#define COPTMEX_STATUS_INF_OF_UNB "inf_or_unb" +#define COPTMEX_STATUS_NUMERICAL "numerical" +#define COPTMEX_STATUS_NODELIMIT "nodelimit" +#define COPTMEX_STATUS_TIMEOUT "timeout" +#define COPTMEX_STATUS_UNFINISHED "unfinished" +#define COPTMEX_STATUS_INTERRUPTED "interrupted" + +/* The main part of model struct fields */ +#define COPTMEX_MODEL_OBJSEN "objsen" +#define COPTMEX_MODEL_OBJCON "objcon" +#define COPTMEX_MODEL_A "A" +#define COPTMEX_MODEL_OBJ "obj" +#define COPTMEX_MODEL_LB "lb" +#define COPTMEX_MODEL_UB "ub" +#define COPTMEX_MODEL_VTYPE "vtype" +#define COPTMEX_MODEL_VARNAME "varnames" +#define COPTMEX_MODEL_SENSE "sense" +#define COPTMEX_MODEL_LHS "lhs" +#define COPTMEX_MODEL_RHS "rhs" +#define COPTMEX_MODEL_CONNAME "constrnames" + +/* The optional part of model struct fields */ +#define COPTMEX_MODEL_SOS "sos" +#define COPTMEX_MODEL_SOSTYPE "type" +#define COPTMEX_MODEL_SOSVARS "vars" +#define COPTMEX_MODEL_SOSWEIGHT "weights" + +#define COPTMEX_MODEL_INDICATOR "indicator" +#define COPTMEX_MODEL_INDICBINVAR "binvar" +#define COPTMEX_MODEL_INDICBINVAL "binval" +#define COPTMEX_MODEL_INDICROW "a" +#define COPTMEX_MODEL_INDICSENSE "sense" +#define COPTMEX_MODEL_INDICRHS "rhs" + +#define COPTMEX_MODEL_QUADOBJ "Q" + +#define COPTMEX_MODEL_QUADCON "quadcon" +#define COPTMEX_MODEL_QCSPMAT "Qc" +#define COPTMEX_MODEL_QCROW "Qrow" +#define COPTMEX_MODEL_QCCOL "Qcol" +#define COPTMEX_MODEL_QCVAL "Qval" +#define COPTMEX_MODEL_QCLINEAR "q" +#define COPTMEX_MODEL_QCSENSE "sense" +#define COPTMEX_MODEL_QCRHS "rhs" +#define COPTMEX_MODEL_QCNAME "name" + +#define COPTMEX_MODEL_CONE "cone" +#define COPTMEX_MODEL_CONETYPE "type" +#define COPTMEX_MODEL_CONEVARS "vars" + +#define COPTMEX_MODEL_CONEDATA "conedata" +#define COPTMEX_MODEL_CONE_OBJSEN "objsen" +#define COPTMEX_MODEL_CONE_OBJCON "objcon" +#define COPTMEX_MODEL_CONE_C "c" +#define COPTMEX_MODEL_CONE_A "A" +#define COPTMEX_MODEL_CONE_B "b" +#define COPTMEX_MODEL_CONE_K "K" +#define COPTMEX_MODEL_CONE_Q "Q" + +#define COPTMEX_MODEL_CONEK_F "f" +#define COPTMEX_MODEL_CONEK_L "l" +#define COPTMEX_MODEL_CONEK_Q "q" +#define COPTMEX_MODEL_CONEK_R "r" +#define COPTMEX_MODEL_CONEK_S "s" + +/* The penalty struct fields */ +#define COPTMEX_PENALTY_LBPEN "lbpen" +#define COPTMEX_PENALTY_UBPEN "ubpen" +#define COPTMEX_PENALTY_RHSPEN "rhspen" +#define COPTMEX_PENALTY_UPPPEN "upppen" + +/* The result struct fields */ +#define COPTMEX_RESULT_STATUS "status" +#define COPTMEX_RESULT_SIMITER "simplexiter" +#define COPTMEX_RESULT_BARITER "barrieriter" +#define COPTMEX_RESULT_NODECNT "nodecnt" +#define COPTMEX_RESULT_BESTGAP "bestgap" +#define COPTMEX_RESULT_SOLVETIME "solvingtime" +#define COPTMEX_RESULT_OBJVAL "objval" +#define COPTMEX_RESULT_BESTBND "bestbnd" +#define COPTMEX_RESULT_VARBASIS "varbasis" +#define COPTMEX_RESULT_CONBASIS "constrbasis" +#define COPTMEX_RESULT_VALUE "x" +#define COPTMEX_RESULT_REDCOST "rc" +#define COPTMEX_RESULT_SLACK "slack" +#define COPTMEX_RESULT_DUAL "pi" +#define COPTMEX_RESULT_PRIMALRAY "primalray" +#define COPTMEX_RESULT_DUALFARKAS "dualfarkas" + +#define COPTMEX_RESULT_QCSLACK "qcslack" + +#define COPTMEX_RESULT_POOL "pool" +#define COPTMEX_RESULT_POOLOBJ "objval" +#define COPTMEX_RESULT_POOLXN "xn" + +#define COPTMEX_RESULT_PSDX "psdx" +#define COPTMEX_RESULT_PSDRC "psdrc" +#define COPTMEX_RESULT_PSDSLACK "psdslack" +#define COPTMEX_RESULT_PSDPI "psdpi" + +/* The advanced information */ +#define COPTMEX_ADVINFO_MIPSTART "start" + +/* The IIS result struct fields */ +#define COPTMEX_IIS_ISMINIIS "isminiis" +#define COPTMEX_IIS_VARLB "varlb" +#define COPTMEX_IIS_VARUB "varub" +#define COPTMEX_IIS_CONSTRLB "constrlb" +#define COPTMEX_IIS_CONSTRUB "construb" +#define COPTMEX_IIS_SOS "sos" +#define COPTMEX_IIS_INDICATOR "indicator" + +/* The feasibility relaxation result fields */ +#define COPTMEX_FEASRELAX_OBJ "relaxobj" +#define COPTMEX_FEASRELAX_VALUE "relaxvalue" +#define COPTMEX_FEASRELAX_LB "relaxlb" +#define COPTMEX_FEASRELAX_UB "relaxub" +#define COPTMEX_FEASRELAX_LHS "relaxlhs" +#define COPTMEX_FEASRELAX_RHS "relaxrhs" + +/* The version fields */ +#define COPTMEX_VERSION_MAJOR "major" +#define COPTMEX_VERSION_MINOR "minor" +#define COPTMEX_VERSION_TECHNICAL "technical" + +/* Error types */ +#define COPTMEX_ERROR_BAD_TYPE 0 +#define COPTMEX_ERROR_BAD_NAME 1 +#define COPTMEX_ERROR_BAD_DATA 2 +#define COPTMEX_ERROR_BAD_NUM 3 +#define COPTMEX_ERROR_BAD_API 4 + +typedef struct coptmex_mversion_s +{ + mxArray* major; + mxArray* minor; + mxArray* technical; +} coptmex_mversion; + +typedef struct coptmex_cprob_s +{ + /* The main part of problem */ + int nCol; + int nRow; + int nElem; + int nObjSen; + double dObjConst; + + int* colMatBeg; + int* colMatIdx; + double* colMatElem; + + double* colCost; + double* colLower; + double* colUpper; + double* rowLower; + double* rowUpper; + + char* colType; + char* rowSense; + char** colNames; + char** rowNames; + + /* The optional SOS part */ + int nSos; + int nSosSize; + int* sosType; + int* sosMatBeg; + int* sosMatCnt; + int* sosMatIdx; + double* sosMatWt; + + /* The optional indicator part */ + int nIndicator; + + /* The optional cone part */ + int nCone; + int nConeSize; + int* coneType; + int* coneBeg; + int* coneCnt; + int* coneIdx; + + /* The optional Q objective part */ + int nQElem; + + /* The optional quadratic constraint part */ + int nQConstr; + + /* The optional advanced information */ + int hasBasis; + int* colBasis; + int* rowBasis; +} coptmex_cprob; + +typedef struct coptmex_mprob_s +{ + /* The main part of model */ + mxArray* objsen; + mxArray* objcon; + mxArray* A; + mxArray* obj; + mxArray* lb; + mxArray* ub; + mxArray* vtype; + mxArray* varnames; + mxArray* sense; + mxArray* lhs; + mxArray* rhs; + mxArray* constrnames; + + /* The optional sos part of model */ + mxArray* sos; + + /* The optional indicator part of model */ + mxArray* indicator; + + /* The optional cone part of model */ + mxArray* cone; + + /* The optional Q objective part of model */ + mxArray* qobj; + + /* The optional quadratic constraint part of model */ + mxArray* quadcon; + + /* The optional advanced information */ + mxArray* varbasis; + mxArray* constrbasis; + + mxArray* value; + mxArray* slack; + mxArray* dual; + mxArray* redcost; + + mxArray* mipstart; +} coptmex_mprob; + +typedef struct coptmex_cconeprob_s +{ + int nCol; + int nRow; + int nElem; + + int nObjSense; + double dObjConst; + + int nFree; + int nPositive; + int nCone; + int nRotateCone; + int nPSD; + + int* coneDim; + int* rotateConeDim; + int* psdDim; + + double* colObj; + + int nQObjElem; + int* qObjRow; + int* qObjCol; + double* qObjElem; + + int* colMatBeg; + int* colMatIdx; + double* colMatElem; + + double* rowRhs; +} coptmex_cconeprob; + +typedef struct coptmex_mconeprob_s +{ + /* Main cone data */ + mxArray* c; + mxArray* A; + mxArray* b; + + mxArray* K; + mxArray* f; + mxArray* l; + mxArray* q; + mxArray* r; + mxArray* s; + + /* Optional parts */ + mxArray* objsen; + mxArray* objcon; + mxArray* Q; +} coptmex_mconeprob; + +typedef struct coptmex_clpsol_s +{ + int nRow; + int nCol; + int nPSD; + int nPSDLen; + int nPSDConstr; + int nQConstr; + int hasBasis; + int hasLpSol; + + int nStatus; + int nSimplexIter; + int nBarrierIter; + double dSolvingTime; + double dObjVal; + + int* colBasis; + int* rowBasis; + double* colValue; + double* colDual; + double* rowSlack; + double* rowDual; + double* primalRay; + double* dualFarkas; + + double* qRowSlack; + + double* psdColValue; + double* psdColDual; + double* psdRowSlack; + double* psdRowDual; +} coptmex_clpsol; + +typedef struct coptmex_cmipsol_s +{ + int nRow; + int nCol; + int hasMipSol; + + int nStatus; + int nSimplexIter; + int nNodeCnt; + double dBestGap; + double dSolvingTime; + double dObjVal; + double dBestBnd; + + double* colValue; + + int nSolPool; +} coptmex_cmipsol; + +typedef struct coptmex_ciisinfo_s +{ + int isMinIIS; + int* colLowerIIS; + int* colUpperIIS; + int* rowLowerIIS; + int* rowUpperIIS; + int* sosIIS; + int* indicatorIIS; +} coptmex_ciisinfo; + +typedef struct coptmex_crelaxinfo_s +{ + double dObjVal; + double* colValue; + double* colLowRlx; + double* colUppRlx; + double* rowLowRlx; + double* rowUppRlx; +} coptmex_crelaxinfo; + +typedef struct coptmex_mlpsol_s +{ + mxArray* status; + mxArray* simplexiter; + mxArray* barrieriter; + mxArray* solvingtime; + mxArray* objval; + mxArray* varbasis; + mxArray* constrbasis; + mxArray* value; + mxArray* redcost; + mxArray* slack; + mxArray* dual; + mxArray* ray; + mxArray* farkas; + mxArray* qcslack; + mxArray* psdcolvalue; + mxArray* psdcoldual; + mxArray* psdrowslack; + mxArray* psdrowdual; +} coptmex_mlpsol; + +typedef struct coptmex_mmipsol_s +{ + mxArray* status; + mxArray* simplexiter; + mxArray* nodecnt; + mxArray* bestgap; + mxArray* solvingtime; + mxArray* objval; + mxArray* bestbnd; + mxArray* value; + + mxArray* solpool; +} coptmex_mmipsol; + +typedef struct coptmex_miisinfo_s +{ + mxArray* isminiis; + mxArray* varlb; + mxArray* varub; + mxArray* constrlb; + mxArray* construb; + mxArray* sos; + mxArray* indicator; +} coptmex_miisinfo; + +typedef struct coptmex_mrelaxinfo_s +{ + mxArray* relaxobj; + mxArray* relaxvalue; + mxArray* relaxlb; + mxArray* relaxub; + mxArray* relaxlhs; + mxArray* relaxrhs; +} coptmex_mrelaxinfo; + +/* Display error message */ +void COPTMEX_errorMsg(int errcode, const char* errinfo); +/* Display banner */ +int COPTMEX_dispBanner(void); + +/* Extract version of COPT */ +int COPTMEX_getVersion(mxArray** out_version); +/* Extract objective sense */ +int COPTMEX_getObjsen(const mxArray* in_objsen, int* out_objsen); +/* Extract and save result */ +int COPTMEX_getResult(copt_prob* prob, mxArray** out_result); +/* Extract model data */ +int COPTMEX_getModel(copt_prob* prob, int nfiles, const mxArray** in_files, mxArray** out_model); + +/* Load parameters to problem */ +int COPTMEX_setParam(copt_prob* prob, const mxArray* in_param); +/* Read optional information from file */ +int COPTMEX_readInfo(copt_prob* prob, const mxArray* in_info); +/* Read model from file */ +int COPTMEX_readModel(copt_prob* prob, const mxArray* in_model); +/* Write model to file */ +int COPTMEX_writeModel(copt_prob* prob, const mxArray* out_file); +/* Extract and load data to model */ +int COPTMEX_loadModel(copt_prob* prob, const mxArray* in_model); + +/* Check if solve problem via cone data */ +int COPTMEX_isConeModel(const mxArray* in_model); +/* Solve cone problem with cone data */ +int COPTMEX_solveConeModel(copt_prob* prob, const mxArray* in_model, mxArray** out_result, int ifRetResult); + +/* Compute IIS for infeasible problem */ +int COPTMEX_computeIIS(copt_prob* prob, mxArray** out_iis, int ifRetResult); + +/* Feasibility relaxation for infeasible problem */ +int COPTMEX_feasRelax(copt_prob* prob, const mxArray* penalty, mxArray** out_relax, int ifRetResult); + +/* Get default parameters */ +int COPTMEX_getDefaultParams(copt_prob* prob, mxArray** out_param); + +#endif