00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00030 #include "mosek_qp.h"
00031
00032 #include <limits>
00033 #include <math.h>
00034
00035 #include "matrix.h"
00036
00037 #include "debug.h"
00038
00039 #include "mosek.h"
00040
00041 static void MSKAPI printstr(void*, char str[])
00042 {
00043 DBGP(str);
00044 }
00045
00048 class MosekEnvAutoPtr {
00049 public:
00050 MSKenv_t env;
00051 MosekEnvAutoPtr() {
00052 MSKrescodee r = MSK_makeenv(&env,NULL,NULL,NULL,NULL);
00053 if ( r!=MSK_RES_OK ) {
00054 DBGA("Failed to create Mosek environment");
00055 assert(0);
00056 }
00057 MSK_linkfunctoenvstream(env,MSK_STREAM_LOG,NULL,printstr);
00058 r = MSK_initenv(env);
00059 if ( r!=MSK_RES_OK ) {
00060 DBGA("Failed to initialize Mosek environment");
00061 assert(0);
00062 }
00063 }
00064 ~MosekEnvAutoPtr() {
00065 DBGA("Mosek environment cleaned up");
00066 MSK_deleteenv(&env);
00067 }
00068 };
00069
00070 MSKenv_t& getMosekEnv(){
00071
00072 static MosekEnvAutoPtr mskEnvPtr;
00073 return mskEnvPtr.env;
00074 }
00075
00076 int mosekNNSolverWrapper(const Matrix &Q, const Matrix &Eq, const Matrix &b,
00077 const Matrix &InEq, const Matrix &ib,
00078 const Matrix &lowerBounds, const Matrix &upperBounds,
00079 Matrix &sol, double *objVal, MosekObjectiveType objType)
00080 {
00081 DBGP("Mosek QP Wrapper started");
00082 MSKrescodee r;
00083 MSKtask_t task = NULL;
00084
00085
00086 MSKenv_t env = getMosekEnv();
00087
00088 r = MSK_maketask(env, 0, 0, &task);
00089 if ( r!=MSK_RES_OK ) {
00090 DBGA("Failed to create optimization task");
00091 return -1;
00092 }
00093 MSK_linkfunctotaskstream(task,MSK_STREAM_LOG,NULL,printstr);
00094
00095
00096
00097
00098 r = MSK_putmaxnumvar(task, sol.rows());
00099
00100 if (r == MSK_RES_OK) {
00101 r = MSK_putmaxnumcon(task, Eq.rows() + InEq.rows());
00102 }
00103
00104 assert(Q.getDefault() == 0.0);
00105 assert(Eq.getDefault() == 0.0);
00106 assert(InEq.getDefault() == 0.0);
00107
00108 if (r == MSK_RES_OK) {
00109 r = MSK_putmaxnumanz(task, Eq.numElements() + InEq.numElements() );
00110 }
00111 if ( r!=MSK_RES_OK ) {
00112 DBGA("Failed to input variables");
00113 MSK_deletetask(&task);
00114 return -1;
00115 }
00116
00117
00118
00119
00120
00121
00122 double scale = b.absMax();
00123 if (scale < 1.0e2) {
00124 scale = 1.0;
00125 } else {
00126 DBGP("Mosek solver: scaling problem down by " << scale);
00127 }
00128
00129
00130
00131
00132
00133 MSK_append(task, MSK_ACC_VAR,sol.rows());
00134
00135 MSK_append(task, MSK_ACC_CON, Eq.rows() + InEq.rows());
00136
00137 int i,j;
00138 double value;
00139 if (objType == MOSEK_OBJ_QP) {
00140
00141
00142 Q.sequentialReset();
00143 while (Q.nextSequentialElement(i, j, value)) {
00144 MSK_putqobjij(task, i, j, 2.0*value);
00145 }
00146 } else if (objType == MOSEK_OBJ_LP) {
00147
00148 for (j=0; j<Q.cols(); j++) {
00149 if ( fabs(Q.elem(0,j))>1.0e-5) {
00150 MSK_putcj(task, j, Q.elem(0,j));
00151 }
00152 }
00153 } else {
00154 assert(0);
00155 }
00156
00157
00158 assert(sol.rows() == lowerBounds.rows());
00159 assert(sol.rows() == upperBounds.rows());
00160 for (i=0; i<sol.rows(); i++) {
00161 if ( lowerBounds.elem(i,0) >= upperBounds.elem(i,0) ) {
00162 if ( lowerBounds.elem(i,0) > upperBounds.elem(i,0) ) {
00163 assert(0);
00164 }
00165 if (lowerBounds.elem(i,0) == -std::numeric_limits<double>::max()) {
00166 assert(0);
00167 }
00168 if (upperBounds.elem(i,0) == std::numeric_limits<double>::max()) {
00169 assert(0);
00170 }
00171
00172 DBGP(i << ": fixed " << lowerBounds.elem(i,0)/scale);
00173 MSK_putbound(task, MSK_ACC_VAR, i, MSK_BK_FX,
00174 lowerBounds.elem(i,0)/scale, upperBounds.elem(i,0)/scale );
00175 } else if ( lowerBounds.elem(i,0) != -std::numeric_limits<double>::max() ) {
00176
00177 if ( upperBounds.elem(i,0) != std::numeric_limits<double>::max() ) {
00178
00179 DBGP(i << ": finite bounds " << lowerBounds.elem(i,0)/scale
00180 << " " << upperBounds.elem(i,0)/scale);
00181 MSK_putbound(task, MSK_ACC_VAR, i, MSK_BK_RA,
00182 lowerBounds.elem(i,0)/scale, upperBounds.elem(i,0)/scale );
00183 } else {
00184
00185 DBGP(i << ": lower bound " << lowerBounds.elem(i,0)/scale);
00186 MSK_putbound(task, MSK_ACC_VAR, i, MSK_BK_LO,
00187 lowerBounds.elem(i,0)/scale, +MSK_INFINITY );
00188
00189 }
00190 } else {
00191
00192 if ( upperBounds.elem(i,0) != std::numeric_limits<double>::max() ) {
00193
00194 DBGP(i << ": upper bound " << upperBounds.elem(i,0)/scale);
00195 MSK_putbound(task, MSK_ACC_VAR, i, MSK_BK_UP,
00196 -MSK_INFINITY, upperBounds.elem(i,0)/scale );
00197 } else {
00198
00199 DBGP(i << ": unbounded");
00200 MSK_putbound(task, MSK_ACC_VAR, i, MSK_BK_FR,
00201 -MSK_INFINITY, +MSK_INFINITY );
00202
00203 }
00204 }
00205 }
00206
00207
00208
00209 Eq.sequentialReset();
00210 while(Eq.nextSequentialElement(i, j, value)) {
00211 MSK_putaij( task, i, j, value );
00212 }
00213 for (i=0; i<Eq.rows(); i++) {
00214 MSK_putbound(task, MSK_ACC_CON, i, MSK_BK_FX, b.elem(i,0)/scale, b.elem(i,0)/scale);
00215 }
00216
00217 InEq.sequentialReset();
00218 while(InEq.nextSequentialElement(i, j, value)) {
00219 int eqi = i + Eq.rows();
00220 MSK_putaij( task, eqi, j, value );
00221 }
00222 for (i=0; i<InEq.rows(); i++) {
00223 int eqi = i + Eq.rows();
00224 MSK_putbound(task, MSK_ACC_CON, eqi, MSK_BK_UP, -MSK_INFINITY, ib.elem(i,0)/scale);
00225 }
00226
00227 MSK_putobjsense(task, MSK_OBJECTIVE_SENSE_MINIMIZE);
00228
00229
00230 MSK_putintparam(task,MSK_IPAR_INTPNT_MAX_ITERATIONS,800);
00231
00232
00233
00234
00235 DBGP("Optimization started");
00236 r = MSK_optimize(task);
00237 DBGP("Optimization returns");
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 if (r != MSK_RES_OK) {
00254 DBGA("Mosek optimization call failed, error code " << r);
00255 MSK_deletetask(&task);
00256 return -1;
00257 }
00258 DBGP("Optimization complete");
00259
00260
00261
00262
00263
00264
00265 MSKprostae pst;
00266 MSKsolstae sst;
00267 MSK_getsolutionstatus(task, MSK_SOL_ITR, &pst, &sst);
00268 int result;
00269 if (sst == MSK_SOL_STA_OPTIMAL || sst == MSK_SOL_STA_NEAR_OPTIMAL) {
00270
00271 if (sst == MSK_SOL_STA_OPTIMAL) {DBGP("QP solution is optimal");}
00272 else {DBGA("QP solution is *nearly* optimal");}
00273 result = 0;
00274 } else if (sst == MSK_SOL_STA_PRIM_INFEAS_CER) {
00275
00276 DBGP("Mosek optimization: primal infeasible");
00277 result = 1;
00278 } else if (sst == MSK_SOL_STA_DUAL_INFEAS_CER) {
00279
00280 DBGA("Mosek optimization: dual infeasible (primal unbounded?)");
00281 result = 1;
00282 } else if (sst == MSK_SOL_STA_PRIM_AND_DUAL_FEAS) {
00283
00284
00285 DBGA("QP solution is prim and dual feasible, but not optimal");
00286 DBGA("Is Q positive semidefinite?");
00287 result = -1;
00288 } else {
00289
00290 DBGA("QP fails with solution status " << sst << " and problem status " << pst);
00291 result = -1;
00292 }
00293
00294
00295
00296
00297 if (!result) {
00298
00299 MSKrealt obj, foo;
00300 MSK_getsolutioninf(task, MSK_SOL_ITR, &pst, &sst, &obj,
00301 &foo, &foo, &foo, &foo, &foo, &foo, &foo, &foo);
00302 if (objType == MOSEK_OBJ_QP) {
00303 *objVal = obj * scale * scale;
00304 } else if (objType == MOSEK_OBJ_LP) {
00305 *objVal = obj * scale;
00306 } else {
00307 assert(0);
00308 }
00309 double* xx = new double[sol.rows()];
00310 MSK_getsolutionslice(task, MSK_SOL_ITR, MSK_SOL_ITEM_XX,
00311 0, sol.rows(), xx);
00312 for (i=0; i<sol.rows(); i++) {
00313 sol.elem(i,0) = scale * xx[i];
00314 DBGP("x" << i << ": " << xx[i]);
00315 }
00316 delete [] xx;
00317 }
00318 MSK_deletetask(&task);
00319 return result;
00320 }