SCIP-SDP  3.1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
sdpisolver_mosek.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of SCIPSDP - a solving framework for mixed-integer */
4 /* semidefinite programs based on SCIP. */
5 /* */
6 /* Copyright (C) 2011-2013 Discrete Optimization, TU Darmstadt */
7 /* EDOM, FAU Erlangen-Nürnberg */
8 /* 2014-2017 Discrete Optimization, TU Darmstadt */
9 /* */
10 /* */
11 /* This program is free software; you can redistribute it and/or */
12 /* modify it under the terms of the GNU Lesser General Public License */
13 /* as published by the Free Software Foundation; either version 3 */
14 /* of the License, or (at your option) any later version. */
15 /* */
16 /* This program is distributed in the hope that it will be useful, */
17 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
18 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
19 /* GNU Lesser General Public License for more details. */
20 /* */
21 /* You should have received a copy of the GNU Lesser General Public License */
22 /* along with this program; if not, write to the Free Software */
23 /* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.*/
24 /* */
25 /* */
26 /* Based on SCIP - Solving Constraint Integer Programs */
27 /* Copyright (C) 2002-2017 Zuse Institute Berlin */
28 /* SCIP is distributed under the terms of the SCIP Academic Licence, */
29 /* see file COPYING in the SCIP distribution. */
30 /* */
31 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
32 
33 /*#define SCIP_DEBUG*/
34 /*#define SCIP_MORE_DEBUG*/
35 /*#define SCIP_DEBUG_PRINTTOFILE *//* prints each problem inserted into MOSEK to the file mosek.task */
36 
64 #include <assert.h>
65 #include <sys/time.h>
66 
67 #include "sdpi/sdpisolver.h"
68 
69 #include "blockmemshell/memory.h" /* for memory allocation */
70 #include "scip/def.h" /* for SCIP_Real, _Bool, ... */
71 #include "scip/pub_misc.h" /* for sorting */
72 #include "mosek.h" /* for MOSEK routines */
73 #include "sdpi/sdpsolchecker.h" /* to check solution with regards to feasibility tolerance */
74 
75 /* TODO: use MSK_putexitfunc to catch errors
76  * TODO: Think about what to do with near optimality etc. (If MOSEK cannot compute a solution that has the prescribed accuracy, then it will
77  * multiply the termination tolerances with MSK_DPAR_INTPNT_CO_TOL_NEAR_REL. If the solution then satisfies the termination criteria, then
78  * the solution is denoted near optimal, near feasible and so forth.) */
79 
80 #define MIN_PENALTYPARAM 1e5
81 #define MAX_PENALTYPARAM 1e10
82 #define PENALTYPARAM_FACTOR 1e6
83 #define MAX_MAXPENALTYPARAM 1e15
84 #define MAXPENALTYPARAM_FACTOR 1e6
85 #define TOLERANCE_FACTOR 0.1
86 #define PENALTYBOUNDTOL 1E-3
88 #define INFEASFEASTOLCHANGE 0.1
89 #define INFEASMINFEASTOL 1E-9
90 #define CONVERT_ABSOLUTE_TOLERANCES TRUE
93 struct SCIP_SDPiSolver
94 {
95  SCIP_MESSAGEHDLR* messagehdlr;
96  BMS_BLKMEM* blkmem;
97  BMS_BUFMEM* bufmem;
98  MSKenv_t mskenv;
99  MSKtask_t msktask;
100  int nvars;
101  int nactivevars;
102  int* inputtomosekmapper;
105  int* mosektoinputmapper;
106  SCIP_Real* fixedvarsval;
107  SCIP_Real fixedvarsobjcontr;
108  SCIP_Real* objcoefs;
109  int nvarbounds;
110  int* varboundpos;
114  SCIP_Bool solved;
115  int sdpcounter;
116  SCIP_Real epsilon;
117  SCIP_Real gaptol;
118  SCIP_Real feastol;
119  SCIP_Real sdpsolverfeastol;
120  SCIP_Real objlimit;
121  SCIP_Bool sdpinfo;
122  SCIP_Bool penalty;
123  SCIP_Bool feasorig;
125  SCIP_Bool rbound;
126  MSKrescodee terminationcode;
127  SCIP_Bool timelimit;
128  SCIP_Bool timelimitinitial;
129  int nthreads;
130  int niterations;
131  int nsdpcalls;
132 };
133 
134 /*
135  * Local Methods
136  */
137 
139 #define MOSEK_CALL(x) do \
140  { \
141  int _mosekerrorcode_; \
142  if ( (_mosekerrorcode_ = (x)) != MSK_RES_OK ) \
143  { \
144  SCIPerrorMessage("MOSEK-Error <%d> in function call.\n", _mosekerrorcode_); \
145  return SCIP_LPERROR; \
146  } \
147  } \
148  while( FALSE )
149 
151 #define MOSEK_CALL_BOOL(x) do \
152  { \
153  int _mosekerrorcode_; \
154  if ( (_mosekerrorcode_ = (x)) != MSK_RES_OK ) \
155  { \
156  SCIPerrorMessage("MOSEK-Error <%d> in function call.\n", _mosekerrorcode_); \
157  return FALSE; \
158  } \
159  } \
160  while( FALSE )
161 
163 #define MOSEK_CALLM(x) do \
164  { \
165  int _mosekerrorcode_; \
166  if ( (_mosekerrorcode_ = (x)) != MSK_RES_OK ) \
167  { \
168  SCIPerrorMessage("MOSEK-Error <%d> in function call.\n", _mosekerrorcode_); \
169  return SCIP_NOMEMORY; \
170  } \
171  } \
172  while( FALSE )
173 
175 #define BMS_CALL(x) do \
176  { \
177  if( NULL == (x) ) \
178  { \
179  SCIPerrorMessage("No memory in function call.\n"); \
180  return SCIP_NOMEMORY; \
181  } \
182  } \
183  while( FALSE )
184 
186 #define TIMEOFDAY_CALL(x) do \
187  { \
188  int _errorcode_; \
189  if ( (_errorcode_ = (x)) != 0 ) \
190  { \
191  SCIPerrorMessage("Error in gettimeofday! \n"); \
192  return SCIP_ERROR; \
193  } \
194  } \
195  while( FALSE )
196 
198 #define CHECK_IF_SOLVED(sdpisolver) do \
199  { \
200  if (!(sdpisolver->solved)) \
201  { \
202  SCIPerrorMessage("Tried to access solution information for SDP %d ahead of solving!\n", sdpisolver->sdpcounter); \
203  return SCIP_LPERROR; \
204  } \
205  } \
206  while( FALSE )
207 
209 #define CHECK_IF_SOLVED_BOOL(sdpisolver) do \
210  { \
211  if (!(sdpisolver->solved)) \
212  { \
213  SCIPerrorMessage("Tried to access solution information for SDP %d ahead of solving!\n", sdpisolver->sdpcounter); \
214  assert( 0 ); \
215  return FALSE; \
216  } \
217  } \
218  while( FALSE )
219 
221 static
222 void MSKAPI printstr(
223  void* handle,
224  MSKCONST char str[]
225  )
226 {/*lint --e{715,818}*/
227  printf("%s",str);
228 }
229 
230 #ifndef NDEBUG
231 
232 static
233 SCIP_Bool isFixed(
234  SCIP_SDPISOLVER* sdpisolver,
235  SCIP_Real lb,
236  SCIP_Real ub
237  )
238 {/*lint --e{818}*/
239  assert( sdpisolver != NULL );
240  assert( lb < ub + sdpisolver->feastol );
241 
242  return (ub-lb <= sdpisolver->epsilon);
243 }
244 #else
245 #define isFixed(sdpisolver,lb,ub) (ub-lb <= sdpisolver->epsilon)
246 #endif
247 
248 /*
249  * Miscellaneous Methods
250  */
251 
255 char name[SCIP_MAXSTRLEN];
258 const char* SCIPsdpiSolverGetSolverName(
259  void
260  )
261 {
262  int major = 0;/*lint !e123*/
263  int minor = 0;/*lint !e123*/
264  int build = 0;
265  int revision = 0;
266  MSKrescodee rescodee;
267 #ifndef NDEBUG
268  int snprintfreturn; /* used to check the return code of snprintf */
269 #endif
270 
271  rescodee = MSK_getversion(&major, &minor, &build, &revision);/*lint !e123*/
272 
273  if ( rescodee != MSK_RES_OK )
274  return "MOSEK";
275 
276 #ifndef NDEBUG
277  snprintfreturn = SCIPsnprintf(name, SCIP_MAXSTRLEN, "MOSEK %d.%d.%d.%d", major, minor, build, revision);/*lint !e123*/
278  assert( snprintfreturn < SCIP_MAXSTRLEN ); /* check whether the name fits into the string */
279 #else
280  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "MOSEK %d.%d.%d.%d", major, minor, build, revision);
281 #endif
282 
283  return name;
284 }
285 
287 const char* SCIPsdpiSolverGetSolverDesc(
288  void
289  )
290 {
291  return "Homogeneous and self-dual interior-point solver for semidefinite programming developed by MOSEK ApS"
292  "(http://www.mosek.com)";
293 }
294 
302  SCIP_SDPISOLVER* sdpisolver
303  )
304 {/*lint --e{818}*/
305  assert( sdpisolver != NULL );
306  return (void*) NULL;
307 }
308 
311  void
312  )
313 {
314  return 1E-7;
315 }
316 
319  void
320  )
321 {
322  return 1E-5;
323 }
324 
327  void
328  )
329 {
330  return 8;
331 }
332 
335  void
336  )
337 {
338  return FALSE;
339 }
340 
344 /*
345  * SDPI Creation and Destruction Methods
346  */
347 
352 SCIP_RETCODE SCIPsdpiSolverCreate(
353  SCIP_SDPISOLVER** sdpisolver,
354  SCIP_MESSAGEHDLR* messagehdlr,
355  BMS_BLKMEM* blkmem,
356  BMS_BUFMEM* bufmem
357  )
358 {
359  assert( sdpisolver != NULL );
360  assert( blkmem != NULL );
361  assert( bufmem != NULL );
362 
363  SCIPdebugMessage("Calling SCIPsdpiCreate \n");
364 
365  BMS_CALL( BMSallocBlockMemory(blkmem, sdpisolver) );
366 
367  (*sdpisolver)->messagehdlr = messagehdlr;
368  (*sdpisolver)->blkmem = blkmem;
369  (*sdpisolver)->bufmem = bufmem;
370 
371  MOSEK_CALLM( MSK_makeenv(&((*sdpisolver)->mskenv), NULL) );/*lint !e641*/ /* the NULL-argument is a debug file, but setting this will spam the whole folder */
372 
373  /* this will be properly initialized then calling solve */
374  (*sdpisolver)->msktask = NULL;
375 
376  (*sdpisolver)->nvars = 0;
377  (*sdpisolver)->nactivevars = 0;
378  (*sdpisolver)->inputtomosekmapper = NULL;
379  (*sdpisolver)->mosektoinputmapper = NULL;
380  (*sdpisolver)->fixedvarsval = NULL;
381  (*sdpisolver)->fixedvarsobjcontr = 0.0;
382  (*sdpisolver)->objcoefs = NULL;
383  (*sdpisolver)->nvarbounds = 0;
384  (*sdpisolver)->varboundpos = NULL;
385  (*sdpisolver)->solved = FALSE;
386  (*sdpisolver)->sdpcounter = 0;
387 
388  (*sdpisolver)->epsilon = 1e-9;
389  (*sdpisolver)->gaptol = 1e-4;
390  (*sdpisolver)->feastol = 1e-6;
391  (*sdpisolver)->sdpsolverfeastol = 1e-6;
392  (*sdpisolver)->objlimit = SCIPsdpiSolverInfinity(*sdpisolver);
393  (*sdpisolver)->sdpinfo = FALSE;
394  (*sdpisolver)->nthreads = -1;
395  (*sdpisolver)->timelimit = FALSE;
396  (*sdpisolver)->timelimitinitial = FALSE;
397 
398  return SCIP_OKAY;
399 }
400 
402 SCIP_RETCODE SCIPsdpiSolverFree(
403  SCIP_SDPISOLVER** sdpisolver
404  )
405 {
406  assert( sdpisolver != NULL );
407  assert( *sdpisolver != NULL );
408 
409  SCIPdebugMessage("Freeing SDPISolver\n");
410 
411  if ( ((*sdpisolver)->msktask) != NULL )
412  {
413  MOSEK_CALL( MSK_deletetask(&((*sdpisolver)->msktask)) );/*lint !e641*/
414  }
415 
416  if ( ((*sdpisolver)->mskenv) != NULL )
417  {
418  MOSEK_CALL( MSK_deleteenv(&((*sdpisolver)->mskenv)) );/*lint !e641*/
419  }
420 
421  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->varboundpos, 2 * (*sdpisolver)->nactivevars); /*lint !e647*/
422  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->inputtomosekmapper, (*sdpisolver)->nvars);/*lint !e737*/
423  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->mosektoinputmapper, (*sdpisolver)->nactivevars);/*lint !e737*/
424  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->fixedvarsval, (*sdpisolver)->nvars - (*sdpisolver)->nactivevars); /*lint !e776*/
425  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->objcoefs, (*sdpisolver)->nactivevars); /*lint !e776*/
426 
427  BMSfreeBlockMemory((*sdpisolver)->blkmem, sdpisolver);
428 
429  return SCIP_OKAY;
430 }
431 
433 SCIP_RETCODE SCIPsdpiSolverIncreaseCounter(
434  SCIP_SDPISOLVER* sdpisolver
435  )
436 {
437  assert( sdpisolver != NULL );
438 
439  sdpisolver->sdpcounter++;
440 
441  return SCIP_OKAY;
442 }
443 
445 SCIP_RETCODE SCIPsdpiSolverResetCounter(
446  SCIP_SDPISOLVER* sdpisolver
447  )
448 {
449  assert( sdpisolver != NULL );
450 
451  SCIPdebugMessage("Resetting counter of SDP-Interface from %d to 0.\n", sdpisolver->sdpcounter);
452  sdpisolver->sdpcounter = 0;
453 
454  return SCIP_OKAY;
455 }
456 
460 /*
461  * Solving Methods
462  */
463 
482 SCIP_RETCODE SCIPsdpiSolverLoadAndSolve(
483  SCIP_SDPISOLVER* sdpisolver,
484  int nvars,
485  SCIP_Real* obj,
486  SCIP_Real* lb,
487  SCIP_Real* ub,
488  int nsdpblocks,
489  int* sdpblocksizes,
490  int* sdpnblockvars,
491  int sdpconstnnonz,
492  int* sdpconstnblocknonz,
494  int** sdpconstrow,
495  int** sdpconstcol,
496  SCIP_Real** sdpconstval,
497  int sdpnnonz,
498  int** sdpnblockvarnonz,
500  int** sdpvar,
502  int*** sdprow,
503  int*** sdpcol,
504  SCIP_Real*** sdpval,
505  int** indchanges,
507  int* nremovedinds,
508  int* blockindchanges,
509  int nremovedblocks,
510  int nlpcons,
511  int noldlpcons,
512  SCIP_Real* lplhs,
513  SCIP_Real* lprhs,
514  int* rownactivevars,
515  int lpnnonz,
516  int* lprow,
517  int* lpcol,
518  SCIP_Real* lpval,
519  SCIP_Real* starty,
520  int* startZnblocknonz,
522  int** startZrow,
524  int** startZcol,
526  SCIP_Real** startZval,
528  int* startXnblocknonz,
530  int** startXrow,
532  int** startXcol,
534  SCIP_Real** startXval,
536  SCIP_SDPSOLVERSETTING startsettings,
538  SCIP_Real timelimit
539  )
540 {
541  return SCIPsdpiSolverLoadAndSolveWithPenalty(sdpisolver, 0.0, TRUE, FALSE, nvars, obj, lb, ub, nsdpblocks, sdpblocksizes, sdpnblockvars, sdpconstnnonz,
542  sdpconstnblocknonz, sdpconstrow, sdpconstcol, sdpconstval, sdpnnonz, sdpnblockvarnonz, sdpvar, sdprow, sdpcol, sdpval, indchanges,
543  nremovedinds, blockindchanges, nremovedblocks, nlpcons, noldlpcons, lplhs, lprhs, rownactivevars, lpnnonz, lprow, lpcol, lpval,
544  starty, startZnblocknonz, startZrow, startZcol, startZval, startXnblocknonz, startXrow, startXcol, startXval, startsettings,
545  timelimit, NULL, NULL);
546 }
547 
571  SCIP_SDPISOLVER* sdpisolver,
572  SCIP_Real penaltyparam,
573  SCIP_Bool withobj,
574  SCIP_Bool rbound,
575  int nvars,
576  SCIP_Real* obj,
577  SCIP_Real* lb,
578  SCIP_Real* ub,
579  int nsdpblocks,
580  int* sdpblocksizes,
581  int* sdpnblockvars,
582  int sdpconstnnonz,
583  int* sdpconstnblocknonz,
585  int** sdpconstrow,
586  int** sdpconstcol,
587  SCIP_Real** sdpconstval,
588  int sdpnnonz,
589  int** sdpnblockvarnonz,
591  int** sdpvar,
593  int*** sdprow,
594  int*** sdpcol,
595  SCIP_Real*** sdpval,
596  int** indchanges,
598  int* nremovedinds,
599  int* blockindchanges,
600  int nremovedblocks,
601  int nlpcons,
602  int noldlpcons,
603  SCIP_Real* lplhs,
604  SCIP_Real* lprhs,
605  int* rownactivevars,
606  int lpnnonz,
607  int* lprow,
608  int* lpcol,
609  SCIP_Real* lpval,
610  SCIP_Real* starty,
611  int* startZnblocknonz,
613  int** startZrow,
615  int** startZcol,
617  SCIP_Real** startZval,
619  int* startXnblocknonz,
621  int** startXrow,
623  int** startXcol,
625  SCIP_Real** startXval,
627  SCIP_SDPSOLVERSETTING startsettings,
629  SCIP_Real timelimit,
630  SCIP_Bool* feasorig,
632  SCIP_Bool* penaltybound
634 )
635 {/*lint --e{715,818}*/
636  int b;
637  int i;
638  int j;
639  int blockvar;
640  int v;
641  int k;
642  long long ind;
643  int mosekind = 0;
644  SCIP_Real* mosekvarbounds;
645  int nfixedvars;
646  int oldnactivevars;
647  int* vartorowmapper; /* maps the lpvars to the corresponding left- and right-hand-sides of the LP constraints */
648  int* vartolhsrhsmapper; /* maps the lpvars to the corresponding entries in lplhs and lprhs */
649  int nlpvars;
650  int pos;
651  int newpos;
652  int* mosekblocksizes;
653  SCIP_Real one; /* MOSEK always wants a pointer to factors for a sum of matrices, we always use a single matrix with factor one */
654  int* mosekrow;
655  int* mosekcol;
656  SCIP_Real* mosekval;
657  int row;
658  SCIP_Real val;
659  struct timeval starttime;
660  struct timeval currenttime;
661  SCIP_Real startseconds;
662  SCIP_Real currentseconds;
663  SCIP_Real elapsedtime;
664 #ifdef SCIP_MORE_DEBUG
665  int nmosekconss;
666  int nmosekvars;
667  int nmosekcones;
668  char varname[SCIP_MAXSTRLEN];
669 #endif
670 #if CONVERT_ABSOLUTE_TOLERANCES
671  SCIP_Real maxrhscoef; /* MOSEK uses a relative feasibility tolerance, the largest rhs-coefficient is needed for converting the absolute tolerance */
672 #endif
673 
674  assert( sdpisolver != NULL );
675  assert( sdpisolver->mskenv != NULL );
676  assert( penaltyparam > -1 * sdpisolver->epsilon );
677  assert( penaltyparam < sdpisolver->epsilon || ( feasorig != NULL ) );
678  assert( nvars > 0 );
679  assert( obj != NULL );
680  assert( lb != NULL );
681  assert( ub != NULL );
682  assert( nsdpblocks >= 0 );
683  assert( nsdpblocks == 0 || sdpblocksizes != NULL );
684  assert( nsdpblocks == 0 || sdpnblockvars != NULL );
685  assert( sdpconstnnonz >= 0 );
686  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstnblocknonz != NULL );
687  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstrow != NULL );
688  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstcol != NULL );
689  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstval != NULL );
690  assert( sdpnnonz >= 0 );
691  assert( nsdpblocks == 0 || sdpnblockvarnonz != NULL );
692  assert( nsdpblocks == 0 || sdpvar != NULL );
693  assert( nsdpblocks == 0 || sdprow != NULL );
694  assert( nsdpblocks == 0 || sdpcol != NULL );
695  assert( nsdpblocks == 0 || sdpval != NULL );
696  assert( nsdpblocks == 0 || indchanges != NULL );
697  assert( nsdpblocks == 0 || nremovedinds != NULL );
698  assert( nsdpblocks == 0 || blockindchanges != NULL );
699  assert( 0 <= nremovedblocks && nremovedblocks <= nsdpblocks );
700  assert( nlpcons >= 0 );
701  assert( noldlpcons >= nlpcons );
702  assert( nlpcons == 0 || lplhs != NULL );
703  assert( nlpcons == 0 || lprhs != NULL );
704  assert( nlpcons == 0 || rownactivevars != NULL );
705  assert( lpnnonz >= 0 );
706  assert( nlpcons == 0 || lprow != NULL );
707  assert( nlpcons == 0 || lpcol != NULL );
708  assert( nlpcons == 0 || lpval != NULL );
709 
710  /* check the timelimit */
711  if ( timelimit <= 0.0 )
712  {
713  sdpisolver->timelimit = TRUE;
714  sdpisolver->timelimitinitial = TRUE;
715  sdpisolver->solved = FALSE;
716  return SCIP_OKAY;
717  }
718  sdpisolver->timelimit = FALSE;
719  sdpisolver->timelimitinitial = FALSE;
720  sdpisolver->feasorig = FALSE;
721 
722  /* start the timing */
723  TIMEOFDAY_CALL( gettimeofday(&starttime, NULL) );/*lint !e438, !e550, !e641 */
724 
725  one = 1.0;
726 #if CONVERT_ABSOLUTE_TOLERANCES
727  maxrhscoef = 0.0;
728 #endif
729 
730  /* create an empty task (second and third argument are guesses for maximum number of constraints and variables), if there already is one, delete it */
731  if ((sdpisolver->msktask) != NULL)
732  {
733  MOSEK_CALL( MSK_deletetask(&(sdpisolver->msktask)) );/*lint !e641*/
734  }
735  if ( penaltyparam < sdpisolver->epsilon )
736  {
737  MOSEK_CALLM( MSK_maketask(sdpisolver->mskenv, nvars, nsdpblocks - nremovedblocks + nlpcons + 2 * nvars, &(sdpisolver->msktask)) );/*lint !e641*/
738  }
739  else
740  {
741  MOSEK_CALLM( MSK_maketask(sdpisolver->mskenv, nvars + 1, nsdpblocks - nremovedblocks + nlpcons + 2 * nvars, &(sdpisolver->msktask)) );/*lint !e641*/
742  }
743 
744 #ifdef SCIP_MORE_DEBUG
745  MOSEK_CALL( MSK_linkfunctotaskstream (sdpisolver->msktask, MSK_STREAM_LOG, NULL, printstr) ); /* output to console */
746 #else
747  /* if sdpinfo is true, redirect output to console */
748  if ( sdpisolver->sdpinfo )
749  {
750  MOSEK_CALL( MSK_linkfunctotaskstream (sdpisolver->msktask, MSK_STREAM_LOG, NULL, printstr) );/*lint !e641*/
751  }
752 #endif
753 
754  /* set number of threads */
755  if ( sdpisolver->nthreads > 0 )
756  {
757  MOSEK_CALL( MSK_putintparam(sdpisolver->msktask, MSK_IPAR_NUM_THREADS, sdpisolver->nthreads) );/*lint !e641*/
758  }
759 
760  /* only increase the counter if we don't use the penalty formulation to stay in line with the numbers in the general interface (where this is still the
761  * same SDP) */
762  if ( penaltyparam < sdpisolver->epsilon )
763  SCIPdebugMessage("Inserting Data into MOSEK for SDP (%d) \n", ++sdpisolver->sdpcounter);
764  else
765  SCIPdebugMessage("Inserting Data again into MOSEK for SDP (%d) \n", sdpisolver->sdpcounter);
766 
767  /* set the penalty and rbound flags accordingly */
768  sdpisolver->penalty = (penaltyparam < sdpisolver->epsilon) ? FALSE : TRUE;
769  sdpisolver->rbound = rbound;
770 
771  /* allocate memory for inputtomosekmapper, mosektoinputmapper and the fixed and active variable information, for the latter this will
772  * later be shrinked if the needed size is known */
773  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->inputtomosekmapper), sdpisolver->nvars, nvars) );
774  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->mosektoinputmapper), sdpisolver->nactivevars, nvars) );
775  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->fixedvarsval), sdpisolver->nvars - sdpisolver->nactivevars, nvars) ); /*lint !e776*/
776  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->objcoefs), sdpisolver->nactivevars, nvars) ); /*lint !e776*/
777 
778  oldnactivevars = sdpisolver->nactivevars; /* we need to save this to realloc the varboundpos-array if needed */
779  sdpisolver->nvars = nvars;
780  sdpisolver->nactivevars = 0;
781  nfixedvars = 0;
782 
783  /* find the fixed variables */
784  sdpisolver->fixedvarsobjcontr = 0.0;
785  for (i = 0; i < nvars; i++)
786  {
787  if ( isFixed(sdpisolver, lb[i], ub[i]) )
788  {
789  sdpisolver->fixedvarsobjcontr += obj[i] * lb[i]; /* this is the value this fixed variable contributes to the objective */
790  sdpisolver->fixedvarsval[nfixedvars] = lb[i]; /* if lb=ub, then this is the value the variable will have in every solution */
791  nfixedvars++;
792  sdpisolver->inputtomosekmapper[i] = -nfixedvars;
793  SCIPdebugMessage("Fixing variable %d locally to %f for SDP %d in MOSEK\n", i, lb[i], sdpisolver->sdpcounter);
794  }
795  else
796  {
797  sdpisolver->mosektoinputmapper[sdpisolver->nactivevars] = i;
798  sdpisolver->inputtomosekmapper[i] = sdpisolver->nactivevars;
799  sdpisolver->objcoefs[sdpisolver->nactivevars] = obj[i];
800  sdpisolver->nactivevars++;
801 #ifdef SCIP_MORE_DEBUG
802  SCIPdebugMessage("Variable %d becomes variable %d for SDP %d in MOSEK\n", i, sdpisolver->inputtomosekmapper[i], sdpisolver->sdpcounter);
803 #endif
804  }
805  }
806  assert( sdpisolver->nactivevars + nfixedvars == sdpisolver->nvars );
807 
808  /* if we want to solve without objective, we reset fixedvarsobjcontr */
809  if ( ! withobj )
810  sdpisolver->fixedvarsobjcontr = 0.0;
811 
812  /* shrink the fixedvars, objcoefs and mosektoinputmapper arrays to the right size */
813  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->objcoefs), nvars, sdpisolver->nactivevars) );
814  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->fixedvarsval), nvars, nfixedvars) );
815  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->mosektoinputmapper), nvars, sdpisolver->nactivevars) );
816 
817  /* compute number of variable bounds and save them in mosekvarbounds */
818  sdpisolver->nvarbounds = 0;
819  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &mosekvarbounds, 2 * sdpisolver->nactivevars) ); /*lint !e647*/
820 
821  if ( sdpisolver->nactivevars != oldnactivevars )
822  {
823  if ( sdpisolver->varboundpos == NULL )
824  {
825  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->varboundpos), 2 * sdpisolver->nactivevars) ); /*lint !e647*/
826  }
827  else
828  {
829  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->varboundpos), 2 * oldnactivevars, 2 * sdpisolver->nactivevars) ); /*lint !e647*/
830  }
831  }
832  assert( sdpisolver->varboundpos != NULL );
833 
834  for (i = 0; i < sdpisolver->nactivevars; i++)
835  {
836  assert( 0 <= sdpisolver->mosektoinputmapper[i] && sdpisolver->mosektoinputmapper[i] < nvars );
837  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, lb[sdpisolver->mosektoinputmapper[i]]) )
838  {
839  mosekvarbounds[sdpisolver->nvarbounds] = lb[sdpisolver->mosektoinputmapper[i]];
840  sdpisolver->varboundpos[sdpisolver->nvarbounds] = -(i + 1); /* negative sign means lower bound */
841  (sdpisolver->nvarbounds)++;
842  }
843  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, ub[sdpisolver->mosektoinputmapper[i]]) )
844  {
845  mosekvarbounds[sdpisolver->nvarbounds] = -1 * ub[sdpisolver->mosektoinputmapper[i]]; /* we give the upper bounds a negative sign for the objective */
846  sdpisolver->varboundpos[sdpisolver->nvarbounds] = +(i + 1); /* positive sign means upper bound */
847  (sdpisolver->nvarbounds)++;
848  }
849  }
850 
851  if ( nlpcons > 0 )
852  {
853  /* allocate memory to save which lpvariable corresponds to which lp constraint, negative signs correspond to left-hand-sides of lp constraints,
854  * entry i or -i corresponds to the constraint in position |i|-1, as we have to add +1 to make the entries strictly positive or strictly negative */
855  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &vartorowmapper, 2*noldlpcons) ); /*lint !e647*/ /*lint !e530*/
856  /* allocate memory to save at which indices the corresponding lhss and rhss of the lpvars are saved */
857  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &vartolhsrhsmapper, 2*noldlpcons) ); /*lint !e647*/ /*lint !e530*/
858 
859  /* compute the number of LP constraints after splitting the ranged rows and compute the rowtovarmapper */
860  pos = 0;
861  newpos = 0; /* the position in the lhs and rhs arrays */
862  for (i = 0; i < noldlpcons; i++)
863  {
864  assert( newpos <= nlpcons );
865  if ( rownactivevars[i] >= 2 )
866  {
867  if ( lplhs[newpos] > - SCIPsdpiSolverInfinity(sdpisolver) )
868  {
869  vartorowmapper[pos] = -(i+1);
870  vartolhsrhsmapper[pos] = newpos;
871  pos++;
872 
873 #if CONVERT_ABSOLUTE_TOLERANCES
874  /* update largest rhs-entry */
875  if ( REALABS(lplhs[newpos]) > maxrhscoef )
876  maxrhscoef = REALABS(lplhs[newpos]);
877 #endif
878 
879  }
880  if ( lprhs[newpos] < SCIPsdpiSolverInfinity(sdpisolver) )
881  {
882  vartorowmapper[pos] = i+1;
883  vartolhsrhsmapper[pos] = newpos;
884  pos++;
885 
886 #if CONVERT_ABSOLUTE_TOLERANCES
887  /* update largest rhs-entry */
888  if ( REALABS(lprhs[newpos]) > maxrhscoef )
889  maxrhscoef = REALABS(lprhs[newpos]);
890 #endif
891  }
892  newpos++;
893  }
894  }
895  nlpvars = pos;
896  assert( nlpvars <= 2*nlpcons ); /* *2 comes from left- and right-hand-sides */
897  }
898  else
899  nlpvars = 0;
900 
901  /* create matrix variables */
902  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &mosekblocksizes, nsdpblocks - nremovedblocks) ); /*lint !e679 !e776*/
903 
904  for (b = 0; b < nsdpblocks; b++)
905  {
906  if ( blockindchanges[b] > -1 )
907  {
908  assert( 0 <= blockindchanges[b] && blockindchanges[b] <= b && (b - blockindchanges[b]) <= (nsdpblocks - nremovedblocks) );
909  mosekblocksizes[b - blockindchanges[b]] = sdpblocksizes[b] - nremovedinds[b];/*lint !e679*/
910  }
911  }
912  MOSEK_CALLM( MSK_appendbarvars(sdpisolver->msktask, nsdpblocks - nremovedblocks, mosekblocksizes) );/*lint !e641*/
913 
914  /* create scalar variables (since we solve the primal problem, these are not the active variables but the dual variables for the
915  * lp constraints and variable bounds) */
916  MOSEK_CALLM( MSK_appendvars(sdpisolver->msktask, nlpvars + sdpisolver->nvarbounds) );/*lint !e641*/
917 
918  /* all of these are non-negative */
919  for (v = 0; v < nlpvars + sdpisolver->nvarbounds; v++)
920  {
921  MOSEK_CALL( MSK_putvarbound(sdpisolver->msktask, v, MSK_BK_LO, 0.0, (double) MSK_DPAR_DATA_TOL_BOUND_INF) );/*lint !e641*/
922  }
923 
924  /* append empty constraints (since we solve the primal problem, we get one constraint for each active variable) */
925  MOSEK_CALLM( MSK_appendcons(sdpisolver->msktask, (penaltyparam < sdpisolver->epsilon) ? sdpisolver->nactivevars : sdpisolver->nactivevars + 1) );/*lint !e641*/
926 
927  /* set objective values for the matrix variables */
928  i = 0;
929 
930  if ( sdpconstnnonz > 0 )
931  {
932  for (b = 0; b < nsdpblocks; b++)
933  {
934  if ( blockindchanges[b] > -1 )
935  {
936  /* if some indices in the block were removed, we need to change indices accordingly */
937  if ( nremovedinds[b] > 0 )
938  {
939  int* moseksdpconstrow;
940  int* moseksdpconstcol;
941 
942  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &moseksdpconstrow, sdpconstnblocknonz[b]) );
943  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &moseksdpconstcol, sdpconstnblocknonz[b]) );
944 
945  for (k = 0; k < sdpconstnblocknonz[b]; k++)
946  {
947  /* rows and cols with active nonzeros should not be removed */
948  assert( -1 < indchanges[b][sdpconstrow[b][k]] && indchanges[b][sdpconstrow[b][k]] <= sdpconstrow[b][k] );
949  assert( -1 < indchanges[b][sdpconstcol[b][k]] && indchanges[b][sdpconstcol[b][k]] <= sdpconstcol[b][k] );
950 
951  assert( 0 <= sdpconstrow[b][k] && sdpconstrow[b][k] <= sdpblocksizes[b] );
952  assert( 0 <= sdpconstcol[b][k] && sdpconstcol[b][k] <= sdpblocksizes[b] );
953 
954  moseksdpconstrow[k] = sdpconstrow[b][k] - indchanges[b][sdpconstrow[b][k]];
955  moseksdpconstcol[k] = sdpconstcol[b][k] - indchanges[b][sdpconstcol[b][k]];
956 
957 #if CONVERT_ABSOLUTE_TOLERANCES
958  /* update largest rhs-entry */
959  if ( REALABS(sdpconstval[b][k]) > maxrhscoef )
960  maxrhscoef = REALABS(sdpconstval[b][k]);
961 #endif
962  }
963 
964  MOSEK_CALL( MSK_appendsparsesymmat(sdpisolver->msktask, mosekblocksizes[b - blockindchanges[b]], sdpconstnblocknonz[b],
965  moseksdpconstrow, moseksdpconstcol, sdpconstval[b], &ind) );/*lint !e641, !e679, !e747*/
966 
967  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &moseksdpconstcol);
968  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &moseksdpconstrow);
969  }
970  else
971  {
972  MOSEK_CALL( MSK_appendsparsesymmat(sdpisolver->msktask, mosekblocksizes[b - blockindchanges[b]], sdpconstnblocknonz[b],
973  sdpconstrow[b], sdpconstcol[b], sdpconstval[b], &ind) );/*lint !e641, !e679, !e747*/
974  }
975  MOSEK_CALL( MSK_putbarcj(sdpisolver->msktask, i, 1, &ind, &one) );/*lint !e641, !e747*/
976  i++;
977  }
978  }
979  }
980 
981  /* set objective values for the scalar variables */
982  /* first for those corresponding to LP constraints in the dual */
983  for (i = 0; i < nlpvars; i++)
984  {
985  if ( vartorowmapper[i] > 0 )/*lint !e644*/ /* right-hand side */
986  {
987  MOSEK_CALL( MSK_putcj(sdpisolver->msktask, i, -1 * lprhs[vartolhsrhsmapper[i]]) );/*lint !e641, !e644*/
988 #ifdef SCIP_MORE_DEBUG
989  /* give the variable a meaningful name for debug output */
990  (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "rhs-%d", vartorowmapper[i] - 1);
991  MOSEK_CALL( MSK_putvarname ( sdpisolver->msktask, i, varname) );
992 #endif
993  }
994  else /* left-hand side */
995  {
996  assert( vartorowmapper[i] < 0 ); /* we should not have value 0 so that we can clearly differentiate between positive and negative */
997  MOSEK_CALL( MSK_putcj(sdpisolver->msktask, i, lplhs[vartolhsrhsmapper[i]]) );/*lint !e641*/
998 #ifdef SCIP_MORE_DEBUG
999  /* give the variable a meaningful name for debug output */
1000  (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "lhs-%d", -1 * vartorowmapper[i] - 1);
1001  MOSEK_CALL( MSK_putvarname ( sdpisolver->msktask, i, varname) );
1002 #endif
1003  }
1004  }
1005 
1006  /* finally for those corresponding to variable bounds in the dual */
1007  for (i = 0; i < sdpisolver->nvarbounds; i++)
1008  {
1009  MOSEK_CALL( MSK_putcj(sdpisolver->msktask, nlpvars + i, mosekvarbounds[i]) );/*lint !e641*/ /* for the ub's we already added a negative sign in mosekvarbounds*/
1010 #ifdef SCIP_MORE_DEBUG
1011  if ( sdpisolver->varboundpos[i] < 0 ) /* lower bound */
1012  {
1013  /* give the variable a meaningful name for debug output */
1014  (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "lb-%d", sdpisolver->mosektoinputmapper[-1 * sdpisolver->varboundpos[i] - 1]);
1015  MOSEK_CALL( MSK_putvarname ( sdpisolver->msktask, nlpvars + i, varname) );
1016  }
1017  else /* upper bound */
1018  {
1019  assert( sdpisolver->varboundpos[i] > 0 ); /* we should not have value 0 so that we can clearly differentiate between positive and negative */
1020  /* give the variable a meaningful name for debug output */
1021  (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "ub-%d", sdpisolver->mosektoinputmapper[sdpisolver->varboundpos[i] - 1]);
1022  MOSEK_CALL( MSK_putvarname ( sdpisolver->msktask, nlpvars + i, varname) );
1023  }
1024 #endif
1025  }
1026 
1027  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &mosekvarbounds);
1028 
1029  /* set objective sense (since we want to minimize in the dual, we maximize in the primal) */
1030  MOSEK_CALL( MSK_putobjsense(sdpisolver->msktask, MSK_OBJECTIVE_SENSE_MAXIMIZE) );/*lint !e641*/
1031 
1032  /* start inserting the constraints */
1033 
1034  /* first add the matrices A_i */
1035  for (b = 0; b < nsdpblocks; b++)
1036  {
1037  if ( blockindchanges[b] > -1 )
1038  {
1039  for (blockvar = 0; blockvar < sdpnblockvars[b]; blockvar++)
1040  {
1041  v = sdpisolver->inputtomosekmapper[sdpvar[b][blockvar]];
1042 
1043  /* check if the variable is active */
1044  if ( v > -1 )
1045  {
1046  assert( v < sdpisolver->nactivevars );
1047  /* if there are removed indices, we have to adjust the column and row indices accordingly */
1048  if ( nremovedinds[b] > 0 )
1049  {
1050  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &mosekrow, sdpnblockvarnonz[b][blockvar]) );
1051  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &mosekcol, sdpnblockvarnonz[b][blockvar]) );
1052 
1053  for (k = 0; k < sdpnblockvarnonz[b][blockvar]; k++)
1054  {
1055  /* rows and cols with active nonzeros should not be removed */
1056  assert( -1 < indchanges[b][sdprow[b][blockvar][k]] && indchanges[b][sdprow[b][blockvar][k]] <= sdprow[b][blockvar][k] );
1057  assert( -1 < indchanges[b][sdpcol[b][blockvar][k]] && indchanges[b][sdpcol[b][blockvar][k]] <= sdpcol[b][blockvar][k] );
1058 
1059  assert( 0 <= sdprow[b][blockvar][k] && sdprow[b][blockvar][k] < sdpblocksizes[b] );
1060  assert( 0 <= sdpcol[b][blockvar][k] && sdpcol[b][blockvar][k] < sdpblocksizes[b] );
1061 
1062  mosekrow[k] = sdprow[b][blockvar][k] - indchanges[b][sdprow[b][blockvar][k]];
1063  mosekcol[k] = sdpcol[b][blockvar][k] - indchanges[b][sdpcol[b][blockvar][k]];
1064  }
1065 
1066  MOSEK_CALL( MSK_appendsparsesymmat(sdpisolver->msktask, mosekblocksizes[b - blockindchanges[b]], (long long) sdpnblockvarnonz[b][blockvar],
1067  mosekrow, mosekcol, sdpval[b][blockvar], &ind) );/*lint !e641, !e679*/
1068 
1069  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &mosekcol);
1070  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &mosekrow);
1071  }
1072  else
1073  {
1074  MOSEK_CALL( MSK_appendsparsesymmat(sdpisolver->msktask, mosekblocksizes[b - blockindchanges[b]], (long long) sdpnblockvarnonz[b][blockvar],
1075  sdprow[b][blockvar], sdpcol[b][blockvar], sdpval[b][blockvar], &ind) );/*lint !e641, !e679*/
1076  }
1077 
1078  MOSEK_CALL( MSK_putbaraij(sdpisolver->msktask, v, b - blockindchanges[b], (long long) 1, &ind, &one) );/*lint !e641*/
1079  }
1080  }
1081  }
1082  }
1083 
1084  /* add the identity matrix corresponding to the penalty variable */
1085  if ( penaltyparam >= sdpisolver->epsilon )
1086  {
1087  int* identityindices;
1088  SCIP_Real* identityvalues;
1089 
1090  for (b = 0; b < nsdpblocks; b++)
1091  {
1092  if ( blockindchanges[b] > -1 )
1093  {
1094  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &identityindices, mosekblocksizes[b - blockindchanges[b]]) );
1095  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &identityvalues, mosekblocksizes[b - blockindchanges[b]]) );
1096 
1097  for (i = 0; i < mosekblocksizes[b - blockindchanges[b]]; i++)
1098  {
1099  identityindices[i] = i;
1100  identityvalues[i] = 1.0;
1101  }
1102  MOSEK_CALL( MSK_appendsparsesymmat(sdpisolver->msktask, mosekblocksizes[b - blockindchanges[b]], (long long) mosekblocksizes[b - blockindchanges[b]],
1103  identityindices, identityindices, identityvalues, &ind) );/*lint !e641, !e679*/
1104  MOSEK_CALL( MSK_putbaraij(sdpisolver->msktask, sdpisolver->nactivevars, b - blockindchanges[b], (long long) 1, &ind, &one) );/*lint !e641, !e679*/
1105 
1106  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &identityvalues);
1107  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &identityindices);
1108  }
1109  }
1110  }
1111 
1112  /* now add the entries corresponding to the lp-constraints in the dual problem */
1113  if ( penaltyparam < sdpisolver->epsilon )
1114  {
1115  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &mosekrow, lpnnonz) );
1116  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &mosekval, lpnnonz) );
1117  }
1118  else
1119  {
1120  /* one extra entry for the penalty-constraint Trace = Gamma */
1121  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &mosekrow, lpnnonz + 1) );/*lint !e776*/
1122  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &mosekval, lpnnonz + 1) );/*lint !e776*/
1123  }
1124 
1125  ind = 0;
1126  for (i = 0; i < nlpvars; i++)
1127  {
1128  if ( vartorowmapper[i] < 0 ) /* left-hand side */
1129  {
1130  mosekind = 0;
1131  /* find the first lp-entry belonging to this variable (those in between have to belong to constraints with less than two active variables and
1132  * will therefore not be used) */
1133  while (ind < lpnnonz && lprow[ind] < -1 * vartorowmapper[i] - 1)
1134  ind++;
1135  /* iterate over all nonzeros to input them to the array given to MOSEK */
1136  while (ind < lpnnonz && lprow[ind] == -1 * vartorowmapper[i] - 1) /* they should already be sorted by rows in the sdpi */
1137  {
1138  v = sdpisolver->inputtomosekmapper[lpcol[ind]];
1139  if ( v > -1 )
1140  {
1141  mosekrow[mosekind] = v;
1142  mosekval[mosekind] = lpval[ind];
1143  mosekind++;
1144  }
1145  ind++;
1146  }
1147  assert( mosekind <= lpnnonz );
1148  }
1149  else /* right-hand side */
1150  {
1151  assert( vartorowmapper[i] > 0 ); /* we should not have value 0 so that we can clearly differentiate between positive and negative */
1152 
1153  if ( i > 0 && vartorowmapper[i] == -1 * vartorowmapper[i - 1] )
1154  {
1155  /* we already iterated over this constraint in the lp-arrays, so we keep the current ind position and as we currenlty have
1156  * the corresponding entries in the mosek-arrays, we iterate over them again just changing the signs (except for the penalty-entry) */
1157  for (j = 0; j < (penaltyparam < sdpisolver->epsilon ? mosekind : mosekind - 1); j++)/*lint !e644*/
1158  mosekval[j] *= -1;
1159  }
1160  else
1161  {
1162  /* no left hand side for this constraint exists, so we didnot yet iterate over this constraint in the lp arrays */
1163  mosekind = 0;
1164  /* find the first lp-entry belonging to this variable (those in between have to belong to constraints with less than two active variables and
1165  * will therefore not be used) */
1166  while (lprow[ind] < vartorowmapper[i] - 1)
1167  ind++;
1168  while (ind < lpnnonz && lprow[ind] == vartorowmapper[i] - 1)
1169  {
1170  v = sdpisolver->inputtomosekmapper[lpcol[ind]];
1171  if ( v > -1 )
1172  {
1173  mosekrow[mosekind] = v;
1174  mosekval[mosekind] = -1 * lpval[ind]; /* because we need to change the <= to a >= constraint */
1175  mosekind++;
1176  }
1177  ind++;
1178  }
1179  assert( mosekind <= lpnnonz );
1180  }
1181  }
1182 
1183  /* add the additional entry for the penalty constraint Trace = Gamma */
1184  if ( penaltyparam >= sdpisolver->epsilon )
1185  {
1186  /* check if we reset mosekind, in case we did not and just "copied" the lhs-entries for the rhs, we do not need to reset the extra entry,
1187  * since it is already there */
1188  if ( ! (i > 0 && vartorowmapper[i] == -1 * vartorowmapper[i - 1] ))
1189  {
1190  mosekrow[mosekind] = sdpisolver->nactivevars;
1191  mosekval[mosekind] = 1.0;
1192  mosekind++;
1193  }
1194  assert( mosekind <= lpnnonz + 1 );
1195  }
1196 
1197  MOSEK_CALL( MSK_putacol(sdpisolver->msktask, i, mosekind, mosekrow, mosekval) );/*lint !e641*/
1198  }
1199 
1200  BMSfreeBufferMemoryArrayNull(sdpisolver->bufmem, &mosekval);
1201  BMSfreeBufferMemoryArrayNull(sdpisolver->bufmem, &mosekrow);
1202 
1203  /* finally add the entries corresponding to varbounds in the dual problem, we get exactly one entry per variable */
1204  for (i = 0; i < sdpisolver->nvarbounds; i++)
1205  {
1206  if ( sdpisolver->varboundpos[i] < 0 )
1207  {
1208  /* lower bound */
1209  row =-1 * sdpisolver->varboundpos[i] - 1; /* minus one because we added one to get strictly positive/negative values */
1210  val = 1.0;
1211  }
1212  else
1213  {
1214  /* upper bound */
1215  assert( sdpisolver->varboundpos[i] > 0 ); /* we should not have a zero as we wanted a clear differentiation between positive and negative */
1216  row = sdpisolver->varboundpos[i] - 1; /* minus one because we added one to get strictly positive/negative values */
1217  val = -1.0;
1218  }
1219  MOSEK_CALL( MSK_putacol(sdpisolver->msktask, nlpvars + i, 1, &row, &val) );/*lint !e641*/
1220  }
1221 
1222  /* make all constraints equality constraints with right-hand side b_i (or 0 if we solve without objective) */
1223  for (i = 0; i < sdpisolver->nactivevars; i++)
1224  {
1225  if ( withobj )
1226  {
1227  MOSEK_CALL( MSK_putconbound(sdpisolver->msktask, i, MSK_BK_FX, obj[sdpisolver->mosektoinputmapper[i]], obj[sdpisolver->mosektoinputmapper[i]]) );/*lint !e641*/
1228  }
1229  else
1230  {
1231  MOSEK_CALL( MSK_putconbound(sdpisolver->msktask, i, MSK_BK_FX, 0.0, 0.0) );/*lint !e641*/
1232  }
1233 #ifdef SCIP_MORE_DEBUG
1234  /* give the constraint a meaningful name for debug output */
1235  (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "var-%d", sdpisolver->mosektoinputmapper[i]);
1236  MOSEK_CALL( MSK_putconname ( sdpisolver->msktask, i, varname) );
1237 #endif
1238  }
1239 
1240  /* the penalty constraint has right-hand side Gamma, it is a <=-inequality if r was bounded and an equality constraint otherwise */
1241  if ( penaltyparam >= sdpisolver->epsilon )
1242  {
1243  if ( rbound )
1244  {
1245  MOSEK_CALL( MSK_putconbound(sdpisolver->msktask, sdpisolver->nactivevars, MSK_BK_UP, (double) -1 * MSK_DPAR_DATA_TOL_BOUND_INF, penaltyparam) );/*lint !e641*/
1246  }
1247  else
1248  {
1249  MOSEK_CALL( MSK_putconbound(sdpisolver->msktask, sdpisolver->nactivevars, MSK_BK_FX, penaltyparam, penaltyparam) );/*lint !e641*/
1250  }
1251  }
1252 
1253  /* write to file if asked to */
1254 #ifdef SCIP_DEBUG_PRINTTOFILE
1255  SCIP_CALL( SCIPsdpiSolverWriteSDP(sdpisolver, "mosek.task") );
1256 #endif
1257 
1258  /* print whole problem and parameters if asked to */
1259 #ifdef SCIP_MORE_DEBUG
1260  MOSEK_CALL( MSK_getnumcon (sdpisolver->msktask, &nmosekconss) );
1261  MOSEK_CALL( MSK_getnumvar (sdpisolver->msktask, &nmosekvars) );
1262  MOSEK_CALL( MSK_getnumcone (sdpisolver->msktask, &nmosekcones) );
1263 
1264  MOSEK_CALL( MSK_printdata (sdpisolver->msktask, MSK_STREAM_LOG, 0, nmosekconss, 0, nmosekvars, 0, nmosekcones, 1, 1, 1, 1, 1, 1, 1, 1) );
1265 #ifdef SCIP_PRINT_PARAMETERS
1266  MOSEK_CALL( MSK_printparam (sdpisolver->msktask) );
1267 #endif
1268 #endif
1269 
1270  /* set the time limit */
1271  startseconds = (SCIP_Real) starttime.tv_sec + (SCIP_Real) starttime.tv_usec / 1e6;
1272 
1273  TIMEOFDAY_CALL( gettimeofday(&currenttime, NULL) );/*lint !e438, !e550, !e641 */
1274  currentseconds = (SCIP_Real) currenttime.tv_sec + (SCIP_Real) currenttime.tv_usec / 1e6;
1275 
1276  elapsedtime = currentseconds - startseconds;
1277 
1278  if ( timelimit <= elapsedtime )
1279  {
1280  sdpisolver->timelimit = TRUE;
1281  sdpisolver->solved = FALSE;
1282  }
1283  else
1284  {
1285  SCIP_Real feastol;
1286 
1287  /* set epsilon and feasibility tolerance (note that the dual in MOSEK is the problem we are interested in, so this is where we use feastol,
1288  * since MOSEK works with relative tolerance, we adjust our absolute tolerance accordingly, so that any solution satisfying the relative
1289  * tolerance in MOSEK satisfies our absolute tolerance) */
1290  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_PFEAS, sdpisolver->gaptol) );/*lint !e641*/
1291 #if CONVERT_ABSOLUTE_TOLERANCES
1292  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_DFEAS, sdpisolver->sdpsolverfeastol / (1 + maxrhscoef)) );/*lint !e641*/
1293  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_INFEAS, sdpisolver->sdpsolverfeastol / (1 + maxrhscoef)) );/*lint !e641*/
1294  SCIPdebugMessage("Setting relative feasibility tolerance for MOSEK to %.10f / %f = %.12f\n", sdpisolver->sdpsolverfeastol,
1295  1+maxrhscoef, sdpisolver->sdpsolverfeastol / (1 + maxrhscoef));
1296 #else
1297  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_DFEAS, sdpisolver->sdpsolverfeastol) );/*lint !e641*/
1298  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_INFEAS, sdpisolver->sdpsolverfeastol) );/*lint !e641*/
1299 #endif
1300  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_MU_RED, sdpisolver->gaptol) );/*lint !e641*/
1301  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_REL_GAP, sdpisolver->gaptol) );/*lint !e641*/
1302 
1303  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, timelimit - elapsedtime) )
1304  {
1305  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_OPTIMIZER_MAX_TIME, timelimit - elapsedtime) );/*lint !e641*/
1306  }
1307 
1308  /* set objective cutoff */
1309  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, sdpisolver->objlimit) )
1310  {
1311  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_UPPER_OBJ_CUT, sdpisolver->objlimit) );/*lint !e641*/
1312  }
1313 
1314  /* solve the problem */
1315  MOSEK_CALL( MSK_optimizetrm(sdpisolver->msktask, &(sdpisolver->terminationcode)) );/*lint !e641*/
1316 
1317  if ( sdpisolver->sdpinfo )
1318  {
1319  MOSEK_CALL( MSK_optimizersummary(sdpisolver->msktask, MSK_STREAM_LOG) );/*lint !e641*/
1320  MOSEK_CALL( MSK_analyzesolution(sdpisolver->msktask, MSK_STREAM_LOG, MSK_SOL_ITR) );/*lint !e641*/
1321  }
1322 
1323  SCIPdebugMessage("Solving problem using MOSEK, return code %d\n", sdpisolver->terminationcode);
1324 
1325  sdpisolver->solved = TRUE;
1326 
1327  sdpisolver->nsdpcalls = 1;
1328  MOSEK_CALL( MSK_getnaintinf(sdpisolver->msktask, "MSK_IINF_INTPNT_ITER", &(sdpisolver->niterations)) );/*lint !e641*/
1329 
1330  /* if the problem has been stably solved but did not reach the required feasibility tolerance, even though the solver
1331  * reports feasibility, resolve it with adjusted tolerance */
1332 #if CONVERT_ABSOLUTE_TOLERANCES
1333  feastol = sdpisolver->sdpsolverfeastol / (1 + maxrhscoef);
1334 #else
1335  feastol = sdpisolver->sdpsolverfeastol;
1336 #endif
1337 
1338  while ( SCIPsdpiSolverIsAcceptable(sdpisolver) && SCIPsdpiSolverIsDualFeasible(sdpisolver) && penaltyparam < sdpisolver->epsilon && feastol >= INFEASMINFEASTOL )
1339  {
1340  SCIP_Real* solvector;
1341  int nvarspointer;
1342  SCIP_Bool infeasible;
1343  int newiterations;
1344 
1345  /* get current solution */
1346  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &solvector, nvars) );
1347  nvarspointer = nvars;
1348  SCIP_CALL( SCIPsdpiSolverGetSol(sdpisolver, NULL, solvector, &nvarspointer) );
1349  assert( nvarspointer == nvars );
1350 
1351  /* check the solution for feasibility with regards to our tolerance */
1352  SCIP_CALL( SCIPsdpSolcheckerCheck(sdpisolver->bufmem, nvars, lb, ub, nsdpblocks, sdpblocksizes, sdpnblockvars, sdpconstnnonz,
1353  sdpconstnblocknonz, sdpconstrow, sdpconstcol, sdpconstval, sdpnnonz, sdpnblockvarnonz, sdpvar, sdprow, sdpcol, sdpval,
1354  indchanges, nremovedinds, blockindchanges, nlpcons, noldlpcons, lplhs, lprhs, rownactivevars, lpnnonz, lprow, lpcol, lpval,
1355  solvector, sdpisolver->feastol, sdpisolver->epsilon, &infeasible) );
1356 
1357  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &solvector);
1358 
1359  if ( infeasible )
1360  {
1361  SCIPdebugMessage("Solution feasible for MOSEK but outside feasibility tolerance, changing MOSEK feasibility tolerance from %f to %f\n",
1362  feastol, feastol * INFEASFEASTOLCHANGE);
1363  feastol *= INFEASFEASTOLCHANGE;
1364 
1365  if ( feastol >= INFEASMINFEASTOL )
1366  {
1367  /* update settings */
1368  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_DFEAS, feastol) );/*lint !e641*/
1369  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_INFEAS, feastol) );/*lint !e641*/
1370 
1371  /* set the time limit */
1372  startseconds = (SCIP_Real) starttime.tv_sec + (SCIP_Real) starttime.tv_usec / 1e6;
1373 
1374  TIMEOFDAY_CALL( gettimeofday(&currenttime, NULL) );/*lint !e438, !e550, !e641 */
1375  currentseconds = (SCIP_Real) currenttime.tv_sec + (SCIP_Real) currenttime.tv_usec / 1e6;
1376 
1377  elapsedtime = currentseconds - startseconds;
1378 
1379  if ( timelimit <= elapsedtime )
1380  {
1381  sdpisolver->timelimit = TRUE;
1382  sdpisolver->solved = FALSE;
1383  }
1384 
1385  /* solve the problem */
1386  MOSEK_CALL( MSK_optimizetrm(sdpisolver->msktask, &(sdpisolver->terminationcode)) );/*lint !e641*/
1387 
1388  if ( sdpisolver->sdpinfo )
1389  {
1390  MOSEK_CALL( MSK_optimizersummary(sdpisolver->msktask, MSK_STREAM_LOG) );/*lint !e641*/
1391  MOSEK_CALL( MSK_analyzesolution(sdpisolver->msktask, MSK_STREAM_LOG, MSK_SOL_ITR) );/*lint !e641*/
1392  }
1393 
1394  /* update number of SDP-iterations and -calls */
1395  sdpisolver->nsdpcalls++;
1396  MOSEK_CALL( MSK_getnaintinf(sdpisolver->msktask, "MSK_IINF_INTPNT_ITER", &newiterations) );/*lint !e641*/
1397  sdpisolver->niterations += newiterations;
1398  }
1399  else
1400  {
1401  sdpisolver->solved = FALSE;
1402  SCIPmessagePrintInfo(sdpisolver->messagehdlr, "MOSEK failed to reach required feasibility tolerance! \n");
1403  }
1404  }
1405  else
1406  break;
1407  }
1408  }
1409 
1410 
1411  /* if using a penalty formulation, check if the solution is feasible for the original problem */
1412  if ( penaltyparam >= sdpisolver->epsilon && ( ! sdpisolver->timelimit ) && ( sdpisolver->terminationcode != MSK_RES_TRM_MAX_TIME ) )
1413  {
1414  SCIP_Real* moseksol;
1415  SCIP_Real trace = 0.0;
1416  SCIP_Real* x;
1417 
1418  assert( feasorig != NULL );
1419 
1420  /* get the r variable in the dual problem */
1421  BMSallocBufferMemoryArray(sdpisolver->bufmem, &moseksol, sdpisolver->nactivevars + 1);/*lint !e776*/
1422 
1423  MOSEK_CALL( MSK_gety(sdpisolver->msktask, MSK_SOL_ITR, moseksol) );/*lint !e641*/
1424 
1425  *feasorig = (moseksol[sdpisolver->nactivevars] < sdpisolver->feastol); /*lint !e413*/
1426 
1427  /* only set sdpisolver->feasorig to true if we solved with objective, because only in this case we want to compute
1428  * the objective value by hand since it is numerically more stable then the result returned by MOSEK */
1429  if ( withobj )
1430  sdpisolver->feasorig = *feasorig;
1431 
1432  /* if r > 0 also check the primal bound */
1433  if ( ! *feasorig && penaltybound != NULL )
1434  {
1435 
1436  SCIPdebugMessage("Solution not feasible in original problem, r = %f\n", moseksol[sdpisolver->nactivevars]);
1437 
1438  /* compute Tr(X) */
1439 
1440  /* start with the diagonal entries of the primal semidefinite variables */
1441  for (b = 0; b < nsdpblocks; b++)
1442  {
1443  if ( blockindchanges[b] > -1 )
1444  {
1445  SCIP_Real* X; /* the upper triangular entries of matrix X */
1446  int size;
1447 
1448  size = sdpblocksizes[b] - nremovedinds[b];
1449 
1450  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &X, 0.5 * size * (size + 1)) );
1451  MOSEK_CALL( MSK_getbarxj(sdpisolver->msktask, MSK_SOL_ITR, b - blockindchanges[b], X) );/*lint !e641*/
1452 
1453  /* iterate over all diagonal entries */
1454  for (i = 0; i < size; i++)
1455  {
1456  /* get index in the lower triangular part */
1457  ind = 0.5 * i * (i + 3);/*lint !e776*/ /* i*(i+1)/2 + i */
1458  assert( ind < 0.5 * size * (size + 1) );
1459  trace += X[ind];
1460  }
1461 
1462  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &X);
1463  }
1464  }
1465 
1466  /* add primal lp-variables */
1467  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &x, nlpvars + sdpisolver->nvarbounds) );
1468 
1469  MOSEK_CALL( MSK_getxx(sdpisolver->msktask, MSK_SOL_ITR, x) );/*lint !e641*/
1470 
1471  for (i = 0; i < nlpvars; i++)
1472  trace += x[i];
1473 
1474  BMSfreeBufferMemoryArrayNull(sdpisolver->bufmem, &x);
1475 
1476  /* if the relative gap is smaller than the tolerance, we return equality */
1477  if ( (penaltyparam - trace) / penaltyparam < PENALTYBOUNDTOL )/*lint !e414*/
1478  {
1479  if ( penaltybound != NULL )
1480  *penaltybound = TRUE;
1481  SCIPdebugMessage("Tr(X) = %f == %f = Gamma, penalty formulation not exact, Gamma should be increased or problem is infeasible\n",
1482  trace, penaltyparam);
1483  }
1484  else if ( penaltybound != NULL )
1485  *penaltybound = FALSE;
1486  }
1487  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &moseksol);
1488  }
1489 
1490  /* free memory */
1491  BMSfreeBufferMemoryArrayNull(sdpisolver->bufmem, &mosekblocksizes);
1492  if ( nlpcons > 0 )
1493  {
1494  BMSfreeBufferMemoryArrayNull(sdpisolver->bufmem, &vartolhsrhsmapper);
1495  BMSfreeBufferMemoryArrayNull(sdpisolver->bufmem, &vartorowmapper);
1496  }
1497 
1498  return SCIP_OKAY;
1499 }
1505 /*
1506  * Solution Information Methods
1507  */
1508 
1513 SCIP_Bool SCIPsdpiSolverWasSolved(
1514  SCIP_SDPISOLVER* sdpisolver
1515  )
1516 {/*lint --e{818}*/
1517  assert( sdpisolver != NULL );
1518 
1519  return sdpisolver->solved;
1520 }
1521 
1529  SCIP_SDPISOLVER* sdpisolver
1530  )
1531 {/*lint --e{818}*/
1532  MSKsolstae solstat;
1533 
1534  assert( sdpisolver != NULL );
1535  CHECK_IF_SOLVED_BOOL( sdpisolver );
1536 
1537  MOSEK_CALL_BOOL( MSK_getsolsta(sdpisolver->msktask, MSK_SOL_ITR, &solstat) );/*lint !e641*/
1538 
1539  switch ( solstat )
1540  {
1541  case MSK_SOL_STA_UNKNOWN:
1542  case MSK_SOL_STA_PRIM_FEAS:
1543  case MSK_SOL_STA_DUAL_FEAS:
1544  case MSK_SOL_STA_NEAR_PRIM_FEAS:
1545  case MSK_SOL_STA_NEAR_DUAL_FEAS:
1546  return FALSE;
1547  case MSK_SOL_STA_OPTIMAL:
1548  case MSK_SOL_STA_NEAR_OPTIMAL:
1549  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
1550  case MSK_SOL_STA_NEAR_PRIM_AND_DUAL_FEAS:
1551  case MSK_SOL_STA_PRIM_INFEAS_CER:
1552  case MSK_SOL_STA_NEAR_PRIM_INFEAS_CER:
1553  case MSK_SOL_STA_DUAL_INFEAS_CER:
1554  case MSK_SOL_STA_NEAR_DUAL_INFEAS_CER:
1555  return TRUE;
1556  default:
1557  SCIPdebugMessage("Unknown return code in SCIPsdpiSolverFeasibilityKnown\n"); /* TODO: add illposed_cer */
1558  return FALSE;
1559  }/*lint !e788*/
1560 }
1561 
1563 SCIP_RETCODE SCIPsdpiSolverGetSolFeasibility(
1564  SCIP_SDPISOLVER* sdpisolver,
1565  SCIP_Bool* primalfeasible,
1566  SCIP_Bool* dualfeasible
1567  )
1568 {/*lint --e{818}*/
1569  MSKsolstae solstat;
1570 
1571  assert( sdpisolver != NULL );
1572  assert( primalfeasible != NULL );
1573  assert( dualfeasible != NULL );
1574  CHECK_IF_SOLVED( sdpisolver );
1575 
1576  MOSEK_CALL( MSK_getsolsta(sdpisolver->msktask, MSK_SOL_ITR, &solstat) );/*lint !e641*/
1577 
1578  switch ( solstat )
1579  {
1580  case MSK_SOL_STA_OPTIMAL:
1581  case MSK_SOL_STA_NEAR_OPTIMAL:
1582  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
1583  case MSK_SOL_STA_NEAR_PRIM_AND_DUAL_FEAS:
1584  *primalfeasible = TRUE;
1585  *dualfeasible = TRUE;
1586  break;
1587  case MSK_SOL_STA_PRIM_INFEAS_CER:
1588  case MSK_SOL_STA_NEAR_PRIM_INFEAS_CER:
1589  *primalfeasible = FALSE;
1590  *dualfeasible = TRUE;
1591  break;
1592  case MSK_SOL_STA_DUAL_INFEAS_CER:
1593  case MSK_SOL_STA_NEAR_DUAL_INFEAS_CER:
1594  *primalfeasible = TRUE;
1595  *dualfeasible = FALSE;
1596  break;
1597  default:
1598  SCIPdebugMessage("MOSEK does not know about feasibility of solutions\n");
1599  return SCIP_LPERROR;
1600  }/*lint !e788*/
1601 
1602  return SCIP_OKAY;
1603 }
1604 
1608  SCIP_SDPISOLVER* sdpisolver
1609  )
1610 {/*lint --e{818}*/
1611  MSKsolstae solstat;
1612 
1613  assert( sdpisolver != NULL );
1614  CHECK_IF_SOLVED_BOOL( sdpisolver );
1615 
1616  MOSEK_CALL_BOOL( MSK_getsolsta(sdpisolver->msktask, MSK_SOL_ITR, &solstat) );/*lint !e641*/
1617 
1618  switch ( solstat )
1619  {
1620  case MSK_SOL_STA_DUAL_INFEAS_CER:
1621  case MSK_SOL_STA_NEAR_DUAL_INFEAS_CER:
1622  return TRUE;
1623  case MSK_SOL_STA_OPTIMAL:
1624  case MSK_SOL_STA_NEAR_OPTIMAL:
1625  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
1626  case MSK_SOL_STA_NEAR_PRIM_AND_DUAL_FEAS:
1627  case MSK_SOL_STA_PRIM_INFEAS_CER:
1628  case MSK_SOL_STA_NEAR_PRIM_INFEAS_CER:
1629  break;
1630  default:
1631  SCIPdebugMessage("MOSEK does not know about feasibility of solutions\n");
1632  break;
1633  }/*lint !e788*/
1634  return FALSE;
1635 }
1636 
1640  SCIP_SDPISOLVER* sdpisolver
1641  )
1642 {/*lint --e{818}*/
1643  MSKsolstae solstat;
1644 
1645  assert( sdpisolver != NULL );
1646  CHECK_IF_SOLVED_BOOL( sdpisolver );
1647 
1648  MOSEK_CALL_BOOL( MSK_getsolsta(sdpisolver->msktask, MSK_SOL_ITR, &solstat) );/*lint !e641*/
1649 
1650  switch ( solstat )
1651  {
1652  case MSK_SOL_STA_PRIM_INFEAS_CER:
1653  case MSK_SOL_STA_NEAR_PRIM_INFEAS_CER:
1654  return TRUE;
1655  case MSK_SOL_STA_OPTIMAL:
1656  case MSK_SOL_STA_NEAR_OPTIMAL:
1657  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
1658  case MSK_SOL_STA_NEAR_PRIM_AND_DUAL_FEAS:
1659  case MSK_SOL_STA_DUAL_INFEAS_CER:
1660  case MSK_SOL_STA_NEAR_DUAL_INFEAS_CER:
1661  break;
1662  default:
1663  SCIPdebugMessage("MOSEK does not know about feasibility of solutions\n");
1664  break;
1665  }/*lint !e788*/
1666  return FALSE;
1667 }
1668 
1672  SCIP_SDPISOLVER* sdpisolver
1673  )
1674 {/*lint --e{818}*/
1675  MSKsolstae solstat;
1676 
1677  assert( sdpisolver != NULL );
1678  CHECK_IF_SOLVED_BOOL( sdpisolver );
1679 
1680  MOSEK_CALL_BOOL( MSK_getsolsta(sdpisolver->msktask, MSK_SOL_ITR, &solstat) );/*lint !e641*/
1681 
1682  switch ( solstat )
1683  {
1684  case MSK_SOL_STA_OPTIMAL:
1685  case MSK_SOL_STA_NEAR_OPTIMAL:
1686  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
1687  case MSK_SOL_STA_NEAR_PRIM_AND_DUAL_FEAS:
1688  case MSK_SOL_STA_DUAL_INFEAS_CER:
1689  case MSK_SOL_STA_NEAR_DUAL_INFEAS_CER:
1690  return TRUE;
1691  case MSK_SOL_STA_PRIM_INFEAS_CER:
1692  case MSK_SOL_STA_NEAR_PRIM_INFEAS_CER:
1693  break;
1694  default:
1695  SCIPdebugMessage("MOSEK does not know about feasibility of solutions\n");
1696  break;
1697  }/*lint !e788*/
1698  return FALSE;
1699 }
1700 
1704  SCIP_SDPISOLVER* sdpisolver
1705  )
1706 {/*lint --e{818}*/
1707  MSKsolstae solstat;
1708 
1709  assert( sdpisolver != NULL );
1710  CHECK_IF_SOLVED_BOOL( sdpisolver );
1711 
1712  MOSEK_CALL_BOOL( MSK_getsolsta(sdpisolver->msktask, MSK_SOL_ITR, &solstat) );/*lint !e641*/
1713 
1714  switch ( solstat )
1715  {
1716  case MSK_SOL_STA_PRIM_INFEAS_CER:
1717  case MSK_SOL_STA_NEAR_PRIM_INFEAS_CER:
1718  return TRUE;
1719  case MSK_SOL_STA_OPTIMAL:
1720  case MSK_SOL_STA_NEAR_OPTIMAL:
1721  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
1722  case MSK_SOL_STA_NEAR_PRIM_AND_DUAL_FEAS:
1723  case MSK_SOL_STA_DUAL_INFEAS_CER:
1724  case MSK_SOL_STA_NEAR_DUAL_INFEAS_CER:
1725  break;
1726  default:
1727  SCIPdebugMessage("MOSEK does not know about feasibility of solutions\n");
1728  break;
1729  }/*lint !e788*/
1730  return FALSE;
1731 }
1732 
1736  SCIP_SDPISOLVER* sdpisolver
1737  )
1738 {/*lint --e{818}*/
1739  MSKsolstae solstat;
1740 
1741  assert( sdpisolver != NULL );
1742  CHECK_IF_SOLVED_BOOL( sdpisolver );
1743 
1744  MOSEK_CALL_BOOL( MSK_getsolsta(sdpisolver->msktask, MSK_SOL_ITR, &solstat) );/*lint !e641*/
1745 
1746  switch ( solstat )
1747  {
1748  case MSK_SOL_STA_DUAL_INFEAS_CER:
1749  case MSK_SOL_STA_NEAR_DUAL_INFEAS_CER:
1750  return TRUE;
1751  case MSK_SOL_STA_OPTIMAL:
1752  case MSK_SOL_STA_NEAR_OPTIMAL:
1753  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
1754  case MSK_SOL_STA_NEAR_PRIM_AND_DUAL_FEAS:
1755  case MSK_SOL_STA_PRIM_INFEAS_CER:
1756  case MSK_SOL_STA_NEAR_PRIM_INFEAS_CER:
1757  break;
1758  default:
1759  SCIPdebugMessage("MOSEK does not know about feasibility of solutions\n");
1760  break;
1761  }/*lint !e788*/
1762  return FALSE;
1763 }
1764 
1768  SCIP_SDPISOLVER* sdpisolver
1769  )
1770 {/*lint --e{818}*/
1771  MSKsolstae solstat;
1772 
1773  assert( sdpisolver != NULL );
1774  CHECK_IF_SOLVED_BOOL( sdpisolver );
1775 
1776  MOSEK_CALL_BOOL( MSK_getsolsta(sdpisolver->msktask, MSK_SOL_ITR, &solstat) );/*lint !e641*/
1777 
1778  switch ( solstat )
1779  {
1780  case MSK_SOL_STA_OPTIMAL:
1781  case MSK_SOL_STA_NEAR_OPTIMAL:
1782  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
1783  case MSK_SOL_STA_NEAR_PRIM_AND_DUAL_FEAS:
1784  case MSK_SOL_STA_PRIM_INFEAS_CER:
1785  case MSK_SOL_STA_NEAR_PRIM_INFEAS_CER:
1786  return TRUE;
1787  case MSK_SOL_STA_DUAL_INFEAS_CER:
1788  case MSK_SOL_STA_NEAR_DUAL_INFEAS_CER:
1789  break;
1790  default:
1791  SCIPdebugMessage("MOSEK does not know about feasibility of solutions\n");
1792  break;
1793  }/*lint !e788*/
1794  return FALSE;
1795 }
1796 
1798 SCIP_Bool SCIPsdpiSolverIsConverged(
1799  SCIP_SDPISOLVER* sdpisolver
1800  )
1801 {/*lint --e{818}*/
1802  assert( sdpisolver != NULL );
1803 
1804  if ( sdpisolver->timelimit )
1805  return FALSE;
1806 
1807  CHECK_IF_SOLVED_BOOL( sdpisolver );
1808 
1809  /* check if Mosek stalled when it was already acceptable */
1810  if ( sdpisolver->terminationcode == MSK_RES_TRM_STALL )
1811  {
1812  MSKsolstae solstat;
1813  SCIP_Real pobj;
1814  SCIP_Real dobj;
1815  SCIP_Real gapnormalization;
1816 
1817  MOSEK_CALL_BOOL( MSK_getsolsta(sdpisolver->msktask, MSK_SOL_ITR, &solstat) );
1818 
1819  /* check the solution status */
1820  switch ( solstat )
1821  {
1822  case MSK_SOL_STA_UNKNOWN:
1823  case MSK_SOL_STA_PRIM_FEAS:
1824  case MSK_SOL_STA_DUAL_FEAS:
1825  case MSK_SOL_STA_NEAR_PRIM_FEAS:
1826  case MSK_SOL_STA_NEAR_DUAL_FEAS:
1827  return FALSE;
1828  case MSK_SOL_STA_OPTIMAL:
1829  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
1830  case MSK_SOL_STA_PRIM_INFEAS_CER:
1831  case MSK_SOL_STA_DUAL_INFEAS_CER:
1832  case MSK_SOL_STA_NEAR_OPTIMAL:
1833  case MSK_SOL_STA_NEAR_PRIM_AND_DUAL_FEAS:
1834  case MSK_SOL_STA_NEAR_PRIM_INFEAS_CER:
1835  case MSK_SOL_STA_NEAR_DUAL_INFEAS_CER:
1836  /* check duality gap */
1837  MOSEK_CALL( MSK_getdualobj(sdpisolver->msktask, MSK_SOL_ITR, &dobj) );
1838  MOSEK_CALL( MSK_getprimalobj(sdpisolver->msktask, MSK_SOL_ITR, &pobj) );
1839  /* for the relative gap we divide by max(1.0, min(pobj, dobj)), as this is also done in Mosek */
1840  gapnormalization = dobj > pobj ? (pobj > 1.0 ? pobj : 1.0) : (dobj > 1.0 ? dobj : 1.0);
1841  if ( REALABS((pobj-dobj) / gapnormalization) < sdpisolver->gaptol )
1842  return TRUE;
1843  else
1844  return FALSE;
1845  default:
1846  return FALSE;
1847  }
1848  }
1849 
1850  return sdpisolver->terminationcode == MSK_RES_OK;
1851 }
1852 
1854 SCIP_Bool SCIPsdpiSolverIsObjlimExc(
1855  SCIP_SDPISOLVER* sdpisolver
1856  )
1857 {/*lint --e{818}*/
1858  assert( sdpisolver != NULL );
1859  CHECK_IF_SOLVED_BOOL( sdpisolver );
1860 
1861  return sdpisolver->terminationcode == MSK_RES_TRM_OBJECTIVE_RANGE;
1862 }
1863 
1865 SCIP_Bool SCIPsdpiSolverIsIterlimExc(
1866  SCIP_SDPISOLVER* sdpisolver
1867  )
1868 {/*lint --e{818}*/
1869  assert( sdpisolver != NULL );
1870  CHECK_IF_SOLVED_BOOL( sdpisolver );
1871 
1872  return sdpisolver->terminationcode == MSK_RES_TRM_MAX_ITERATIONS;
1873 }
1874 
1876 SCIP_Bool SCIPsdpiSolverIsTimelimExc(
1877  SCIP_SDPISOLVER* sdpisolver
1878  )
1879 {/*lint --e{818}*/
1880  assert( sdpisolver != NULL );
1881 
1882  if ( sdpisolver->timelimit )
1883  return TRUE;
1884 
1885  if ( ! sdpisolver->solved )
1886  return FALSE;
1887 
1888  return sdpisolver->terminationcode == MSK_RES_TRM_MAX_TIME;
1889 }
1890 
1902  SCIP_SDPISOLVER* sdpisolver
1903  )
1904 {/*lint --e{818}*/
1905  assert( sdpisolver != NULL );
1906 
1907  if ( ! sdpisolver->solved )
1908  return -1;
1909 
1910  if ( sdpisolver->timelimit )
1911  return 5;
1912 
1913  switch ( sdpisolver->terminationcode )
1914  {
1915  case MSK_RES_OK:
1916  return 0;
1917  case MSK_RES_TRM_MAX_NUM_SETBACKS:
1918  case MSK_RES_TRM_NUMERICAL_PROBLEM:
1919  case MSK_RES_TRM_STALL:
1920  return 2;
1921  case MSK_RES_TRM_OBJECTIVE_RANGE:
1922  return 3;
1923  case MSK_RES_TRM_MAX_ITERATIONS:
1924  return 4;
1925  case MSK_RES_TRM_MAX_TIME:
1926  return 5;
1927  default:
1928  return 7;
1929  }/*lint !e788*/
1930 }
1931 
1933 SCIP_Bool SCIPsdpiSolverIsOptimal(
1934  SCIP_SDPISOLVER* sdpisolver
1935  )
1936 {/*lint --e{818}*/
1937  MSKsolstae solstat;
1938 
1939  assert( sdpisolver != NULL );
1940 
1941  if ( sdpisolver->timelimit )
1942  return FALSE;
1943 
1944  CHECK_IF_SOLVED_BOOL( sdpisolver );
1945 
1946  if ( sdpisolver->terminationcode != MSK_RES_OK )
1947  return FALSE;
1948 
1949  MOSEK_CALL_BOOL( MSK_getsolsta(sdpisolver->msktask, MSK_SOL_ITR, &solstat) );/*lint !e641*/
1950 
1951  if ( solstat != MSK_SOL_STA_OPTIMAL )
1952  return FALSE;
1953 
1954  return TRUE;
1955 }
1956 
1959 SCIP_Bool SCIPsdpiSolverIsAcceptable(
1960  SCIP_SDPISOLVER* sdpisolver
1961  )
1962 {/*lint --e{818}*/
1963  assert( sdpisolver != NULL );
1964 
1965  if ( sdpisolver->timelimit )
1966  return FALSE;
1967 
1968  if ( ! sdpisolver->solved )
1969  return FALSE;
1970 
1971  return SCIPsdpiSolverIsConverged(sdpisolver) && SCIPsdpiSolverFeasibilityKnown(sdpisolver);
1972 }
1973 
1975 SCIP_RETCODE SCIPsdpiSolverIgnoreInstability(
1976  SCIP_SDPISOLVER* sdpisolver,
1977  SCIP_Bool* success
1978  )
1979 {/*lint --e{715,818}*/
1980  SCIPdebugMessage("Not implemented yet\n");
1981  return SCIP_LPERROR;
1982 }
1983 
1985 SCIP_RETCODE SCIPsdpiSolverGetObjval(
1986  SCIP_SDPISOLVER* sdpisolver,
1987  SCIP_Real* objval
1988  )
1989 {/*lint --e{818}*/
1990  SCIP_Real* moseksol;
1991 
1992  assert( sdpisolver != NULL );
1993  CHECK_IF_SOLVED( sdpisolver );
1994  assert( objval != NULL );
1995 
1996  if ( sdpisolver->penalty && ( ! sdpisolver->feasorig ) )
1997  {
1998  /* in this case we cannot really trust the solution given by MOSEK, since changes in the value of r much less than epsilon can
1999  * cause huge changes in the objective, so using the objective value given by MOSEK is numerically more stable */
2000  MOSEK_CALL( MSK_getdualobj(sdpisolver->msktask, MSK_SOL_ITR, objval) );
2001  }
2002  else
2003  {
2004  int v;
2005 
2006  /* since the objective value given by MOSEK sometimes differs slightly from the correct value for the given solution,
2007  * we get the solution from MOSEK and compute the correct objective value */
2008  BMSallocBufferMemoryArray(sdpisolver->bufmem, &moseksol, sdpisolver->penalty ? sdpisolver->nactivevars + 1 : sdpisolver->nactivevars);
2009  MOSEK_CALL( MSK_gety(sdpisolver->msktask, MSK_SOL_ITR, moseksol) );/*lint !e641*/
2010 
2011  *objval = 0.0;
2012  for (v = 0; v < sdpisolver->nactivevars; v++)
2013  *objval += moseksol[v] * sdpisolver->objcoefs[v];
2014  }
2015 
2016  /* as we didn't add the fixed (lb = ub) variables to MOSEK, we have to add their contributions to the objective as well */
2017  *objval += sdpisolver->fixedvarsobjcontr;
2018 
2019  if ( ( ! sdpisolver->penalty ) || sdpisolver->feasorig)
2020  {
2021  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &moseksol);
2022  }
2023 
2024  return SCIP_OKAY;
2025 }
2026 
2031 SCIP_RETCODE SCIPsdpiSolverGetSol(
2032  SCIP_SDPISOLVER* sdpisolver,
2033  SCIP_Real* objval,
2034  SCIP_Real* dualsol,
2035  int* dualsollength
2037  )
2038 {/*lint --e{818}*/
2039  int v;
2040  SCIP_Real* moseksol;
2041 
2042  assert( sdpisolver != NULL );
2043  CHECK_IF_SOLVED( sdpisolver );
2044  assert( dualsollength != NULL );
2045 
2046  if ( *dualsollength > 0 )
2047  {
2048  assert( dualsol != NULL );
2049  if ( *dualsollength < sdpisolver->nvars )
2050  {
2051  SCIPdebugMessage("The given array in SCIPsdpiSolverGetSol only had length %d, but %d was needed", *dualsollength, sdpisolver->nvars);
2052  *dualsollength = sdpisolver->nvars;
2053 
2054  return SCIP_OKAY;
2055  }
2056 
2057  BMSallocBufferMemoryArray(sdpisolver->bufmem, &moseksol, sdpisolver->penalty ? sdpisolver->nactivevars + 1 : sdpisolver->nactivevars);
2058 
2059  MOSEK_CALL( MSK_gety(sdpisolver->msktask, MSK_SOL_ITR, moseksol) );/*lint !e641*/
2060 
2061  /* insert the entries into dualsol, for non-fixed vars we copy those from MOSEK, the rest are the saved entries from inserting (they equal lb=ub) */
2062  for (v = 0; v < sdpisolver->nvars; v++)
2063  {
2064  if ( sdpisolver->inputtomosekmapper[v] >= 0 )
2065  dualsol[v] = moseksol[sdpisolver->inputtomosekmapper[v]];
2066  else
2067  {
2068  /* this is the value that was saved when inserting, as this variable has lb=ub */
2069  assert( -sdpisolver->inputtomosekmapper[v] <= sdpisolver->nvars - sdpisolver->nactivevars );
2070  dualsol[v] = sdpisolver->fixedvarsval[(-1 * sdpisolver->inputtomosekmapper[v]) - 1]; /*lint !e679*/ /* -1 because we wanted strictly negative vals */
2071  }
2072  }
2073 
2074  /* if both solution and objective should be printed, we can use the solution to compute the objective */
2075  if ( objval != NULL )
2076  {
2077  if ( sdpisolver->penalty && ( ! sdpisolver->feasorig ))
2078  {
2079  /* in this case we cannot really trust the solution given by MOSEK, since changes in the value of r much less than epsilon can
2080  * cause huge changes in the objective, so using the objective value given by MOSEK is numerically more stable */
2081  MOSEK_CALL( MSK_getdualobj(sdpisolver->msktask, MSK_SOL_ITR, objval) );
2082  }
2083  else
2084  {
2085  /* since the objective value given by MOSEK sometimes differs slightly from the correct value for the given solution,
2086  * we get the solution from MOSEK and compute the correct objective value */
2087  *objval = 0.0;
2088  for (v = 0; v < sdpisolver->nactivevars; v++)
2089  *objval += moseksol[v] * sdpisolver->objcoefs[v];
2090  }
2091 
2092  /* as we didn't add the fixed (lb = ub) variables to MOSEK, we have to add their contributions to the objective as well */
2093  *objval += sdpisolver->fixedvarsobjcontr;
2094  }
2095 
2096  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &moseksol);
2097  }
2098  else if ( objval != NULL )
2099  {
2100  SCIP_CALL( SCIPsdpiSolverGetObjval(sdpisolver, objval) );
2101  }
2102 
2103  return SCIP_OKAY;
2104 }
2105 
2108  SCIP_SDPISOLVER* sdpisolver,
2109  int nblocks,
2110  int* startXnblocknonz
2112  )
2113 {
2114  SCIPdebugMessage("Not implemented yet\n");
2115 
2116  return SCIP_PLUGINNOTFOUND;
2117 }
2118 
2126 SCIP_RETCODE SCIPsdpiSolverGetPreoptimalSol(
2127  SCIP_SDPISOLVER* sdpisolver,
2128  SCIP_Bool* success,
2129  SCIP_Real* dualsol,
2130  int* dualsollength,
2132  int nblocks,
2133  int* startXnblocknonz,
2135  int** startXrow,
2136  int** startXcol,
2137  SCIP_Real** startXval
2138  )
2139 {/*lint !e1784*/
2140  SCIPdebugMessage("Not implemented yet\n");
2141  return SCIP_LPERROR;
2142 }/*lint !e715*/
2143 
2152  SCIP_SDPISOLVER* sdpisolver,
2153  SCIP_Real* lbvars,
2154  SCIP_Real* ubvars,
2155  int* arraylength
2157  )
2158 {/*lint --e{818}*/
2159  SCIP_Real* primalvars;
2160  int nprimalvars;
2161  int i;
2162 
2163  assert( sdpisolver != NULL );
2164  CHECK_IF_SOLVED( sdpisolver );
2165  assert( arraylength != NULL );
2166  assert( lbvars != NULL );
2167  assert( ubvars != NULL );
2168 
2169  /* check if the arrays are long enough */
2170  if ( *arraylength < sdpisolver->nvars )
2171  {
2172  *arraylength = sdpisolver->nvars;
2173  SCIPdebugMessage("Insufficient length of array in SCIPsdpiSolverGetPrimalBoundVars (gave %d, needed %d)\n", *arraylength, sdpisolver->nvars);
2174  return SCIP_OKAY;
2175  }
2176 
2177  /* initialize the return-arrays with zero */
2178  for (i = 0; i < sdpisolver->nvars; i++)
2179  {
2180  lbvars[i] = 0.0;
2181  ubvars[i] = 0.0;
2182  }
2183 
2184  /* get number of primal variables in MOSEK */
2185  MOSEK_CALL( MSK_getnumvar(sdpisolver->msktask, &nprimalvars) );/*lint !e641*/
2186 
2187  BMSallocBufferMemoryArray(sdpisolver->bufmem, &primalvars, nprimalvars);
2188 
2189  MOSEK_CALL( MSK_getxx(sdpisolver->msktask, MSK_SOL_ITR, primalvars) );/*lint !e641*/
2190 
2191  /* iterate over all variable bounds and insert the corresponding primal variables in the right positions of the return-arrays */
2192  assert( sdpisolver->nvarbounds <= 2 * sdpisolver->nvars );
2193 
2194  for (i = 0; i < sdpisolver->nvarbounds; i++)
2195  {
2196  if ( sdpisolver->varboundpos[i] < 0 )
2197  {
2198  /* this is a lower bound */
2199  /* the last nvarbounds entries correspond to the varbounds */
2200  lbvars[sdpisolver->mosektoinputmapper[-1 * sdpisolver->varboundpos[i] -1]] = primalvars[nprimalvars - sdpisolver->nvarbounds + i]; /*lint !e679, !e834 */
2201  }
2202  else
2203  {
2204  /* this is an upper bound */
2205 
2206  assert( sdpisolver->varboundpos[i] > 0 );
2207 
2208  /* the last nvarbounds entries correspond to the varbounds */
2209  ubvars[sdpisolver->mosektoinputmapper[sdpisolver->varboundpos[i] - 1]] = primalvars[nprimalvars - sdpisolver->nvarbounds + i]; /*lint !e679, !e834 */
2210  }
2211  }
2212 
2213  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &primalvars);
2214 
2215  return SCIP_OKAY;
2216 }
2217 
2219 SCIP_RETCODE SCIPsdpiSolverGetPrimalNonzeros(
2220  SCIP_SDPISOLVER* sdpisolver,
2221  int nblocks,
2222  int* startXnblocknonz
2223  )
2224 {/*lint --e{715,818}*/
2225  SCIPdebugMessage("Not implemented yet\n");
2226  return SCIP_LPERROR;
2227 }
2228 
2233 SCIP_RETCODE SCIPsdpiSolverGetPrimalMatrix(
2234  SCIP_SDPISOLVER* sdpisolver,
2235  int nblocks,
2236  int* startXnblocknonz,
2238  int** startXrow,
2239  int** startXcol,
2240  SCIP_Real** startXval
2241  )
2242 {/*lint --e{715,818}*/
2243  SCIPdebugMessage("Not implemented yet\n");
2244  return SCIP_LPERROR;
2245 }
2246 
2249  SCIP_SDPISOLVER* sdpisolver
2250  )
2251 {/*lint --e{715}*/
2252  SCIPdebugMessage("Not implemented yet\n");
2253  return SCIP_LPERROR;
2254 }
2255 
2257 SCIP_RETCODE SCIPsdpiSolverGetIterations(
2258  SCIP_SDPISOLVER* sdpisolver,
2259  int* iterations
2260  )
2261 {/*lint --e{818}*/
2262 
2263  if ( sdpisolver->timelimitinitial )
2264  *iterations = 0;
2265  else
2266  {
2267  *iterations = sdpisolver->niterations;
2268  }
2269 
2270  return SCIP_OKAY;
2271 }
2272 
2274 SCIP_RETCODE SCIPsdpiSolverGetSdpCalls(
2275  SCIP_SDPISOLVER* sdpisolver,
2276  int* calls
2277  )
2278 {/*lint --e{715,818,1784}*/
2279  assert( calls != NULL );
2280 
2281  *calls = sdpisolver->timelimitinitial ? 0 : sdpisolver->nsdpcalls;
2282 
2283  return SCIP_OKAY;
2284 }
2285 
2287 SCIP_RETCODE SCIPsdpiSolverSettingsUsed(
2288  SCIP_SDPISOLVER* sdpisolver,
2289  SCIP_SDPSOLVERSETTING* usedsetting
2290  )
2291 {/*lint --e{818}*/
2292  assert( sdpisolver != NULL );
2293  assert( usedsetting != NULL );
2294 
2295  if ( ! SCIPsdpiSolverIsAcceptable(sdpisolver) )
2296  *usedsetting = SCIP_SDPSOLVERSETTING_UNSOLVED;
2297  else if ( sdpisolver->penalty )
2298  *usedsetting = SCIP_SDPSOLVERSETTING_PENALTY;
2299  else
2300  *usedsetting = SCIP_SDPSOLVERSETTING_FAST;
2301 
2302  return SCIP_OKAY;
2303 }
2304 
2310 /*
2311  * Numerical Methods
2312  */
2313 
2318 SCIP_Real SCIPsdpiSolverInfinity(
2319  SCIP_SDPISOLVER* sdpisolver
2320  )
2321 {/*lint --e{715,818}*/
2322  return 1.0e16;
2323 }
2324 
2326 SCIP_Bool SCIPsdpiSolverIsInfinity(
2327  SCIP_SDPISOLVER* sdpisolver,
2328  SCIP_Real val
2329  )
2330 {/*lint --e{818}*/
2331  return ((val <= -SCIPsdpiSolverInfinity(sdpisolver)) || (val >= SCIPsdpiSolverInfinity(sdpisolver)));
2332 }
2333 
2335 SCIP_RETCODE SCIPsdpiSolverGetRealpar(
2336  SCIP_SDPISOLVER* sdpisolver,
2337  SCIP_SDPPARAM type,
2338  SCIP_Real* dval
2339  )
2340 {/*lint --e{818}*/
2341  assert( sdpisolver != NULL );
2342  assert( dval != NULL );
2343 
2344  switch( type )
2345  {
2346  case SCIP_SDPPAR_EPSILON:
2347  *dval = sdpisolver->epsilon;
2348  break;
2349  case SCIP_SDPPAR_GAPTOL:
2350  *dval = sdpisolver->gaptol;
2351  break;
2352  case SCIP_SDPPAR_FEASTOL:
2353  *dval = sdpisolver->feastol;
2354  break;
2356  *dval = sdpisolver->sdpsolverfeastol;
2357  break;
2358  case SCIP_SDPPAR_OBJLIMIT:
2359  *dval = sdpisolver->objlimit;
2360  break;
2361  default:
2362  return SCIP_PARAMETERUNKNOWN;
2363  }/*lint !e788*/
2364 
2365  return SCIP_OKAY;
2366 }
2367 
2369 SCIP_RETCODE SCIPsdpiSolverSetRealpar(
2370  SCIP_SDPISOLVER* sdpisolver,
2371  SCIP_SDPPARAM type,
2372  SCIP_Real dval
2373  )
2374 {
2375  assert( sdpisolver != NULL );
2376 
2377  switch( type )
2378  {
2379  case SCIP_SDPPAR_EPSILON:
2380  sdpisolver->epsilon = dval;
2381  SCIPdebugMessage("Setting sdpisolver epsilon to %f.\n", dval);
2382  break;
2383  case SCIP_SDPPAR_GAPTOL:
2384  sdpisolver->gaptol = dval;
2385  SCIPdebugMessage("Setting sdpisolver gaptol to %f.\n", dval);
2386  break;
2387  case SCIP_SDPPAR_FEASTOL:
2388  sdpisolver->feastol = dval;
2389  SCIPdebugMessage("Setting sdpisolver feastol to %f.\n", dval);
2390  break;
2392  sdpisolver->sdpsolverfeastol = dval;
2393  SCIPdebugMessage("Setting sdpisolver sdpsolverfeastol to %f.\n", dval);
2394  break;
2395  case SCIP_SDPPAR_OBJLIMIT:
2396  SCIPdebugMessage("Setting sdpisolver objlimit to %f.\n", dval);
2397  sdpisolver->objlimit = dval;
2398  break;
2399  default:
2400  return SCIP_PARAMETERUNKNOWN;
2401  }/*lint !e788*/
2402 
2403  return SCIP_OKAY;
2404 }
2405 
2407 SCIP_RETCODE SCIPsdpiSolverGetIntpar(
2408  SCIP_SDPISOLVER* sdpisolver,
2409  SCIP_SDPPARAM type,
2410  int* ival
2411  )
2412 {/*lint --e{818}*/
2413  assert( sdpisolver != NULL );
2414 
2415  switch( type )
2416  {
2417  case SCIP_SDPPAR_SDPINFO:
2418  *ival = (int) sdpisolver->sdpinfo;
2419  SCIPdebugMessage("Getting sdpisolver information output (%d).\n", *ival);
2420  break;
2421  case SCIP_SDPPAR_NTHREADS:
2422  *ival = sdpisolver->nthreads;
2423  SCIPdebugMessage("Getting sdpisolver number of threads: %d.\n", *ival);
2424  break;
2425  default:
2426  return SCIP_PARAMETERUNKNOWN;
2427  }/*lint !e788*/
2428 
2429  return SCIP_OKAY;
2430 }
2431 
2433 SCIP_RETCODE SCIPsdpiSolverSetIntpar(
2434  SCIP_SDPISOLVER* sdpisolver,
2435  SCIP_SDPPARAM type,
2436  int ival
2437  )
2438 {
2439  assert( sdpisolver != NULL );
2440 
2441  switch( type )
2442  {
2443  case SCIP_SDPPAR_NTHREADS:
2444  sdpisolver->nthreads = ival;
2445  SCIPdebugMessage("Setting sdpisolver number of threads to %d.\n", ival);
2446  break;
2447  case SCIP_SDPPAR_SDPINFO:
2448  assert( 0 <= ival && ival <= 1 );
2449  sdpisolver->sdpinfo = (SCIP_Bool) ival;
2450  SCIPdebugMessage("Setting sdpisolver information output (%d).\n", ival);
2451  break;
2452  default:
2453  return SCIP_PARAMETERUNKNOWN;
2454  }/*lint !e788*/
2455 
2456  return SCIP_OKAY;
2457 }
2458 
2460 SCIP_RETCODE SCIPsdpiSolverComputeLambdastar(
2461  SCIP_SDPISOLVER* sdpisolver,
2462  SCIP_Real maxguess
2463  )
2464 {/*lint --e{715,818}*/
2465  SCIPdebugMessage("Lambdastar parameter not used by MOSEK"); /* this parameter is only used by SDPA */
2466 
2467  return SCIP_OKAY;
2468 }
2469 
2472  SCIP_SDPISOLVER* sdpisolver,
2473  SCIP_Real maxcoeff,
2474  SCIP_Real* penaltyparam
2475  )
2476 {/*lint --e{818,1784}*/
2477  SCIP_Real compval;
2478 
2479  assert( sdpisolver != NULL );
2480  assert( penaltyparam != NULL );
2481 
2482  compval = PENALTYPARAM_FACTOR * maxcoeff;
2483 
2484  if ( compval < MIN_PENALTYPARAM )
2485  {
2486  SCIPdebugMessage("Setting penaltyparameter to %f.\n", MIN_PENALTYPARAM);
2487  *penaltyparam = MIN_PENALTYPARAM;
2488  }
2489  else if ( compval > MAX_PENALTYPARAM )
2490  {
2491  SCIPdebugMessage("Setting penaltyparameter to %f.\n", MAX_PENALTYPARAM);
2492  *penaltyparam = MAX_PENALTYPARAM;
2493  }
2494  else
2495  {
2496  SCIPdebugMessage("Setting penaltyparameter to %f.\n", compval);
2497  *penaltyparam = compval;
2498  }
2499  return SCIP_OKAY;
2500 }
2501 
2504  SCIP_SDPISOLVER* sdpisolver,
2505  SCIP_Real penaltyparam,
2506  SCIP_Real* maxpenaltyparam
2507  )
2508 {/*lint --e{818,1784}*/
2509  SCIP_Real compval;
2510 
2511  assert( sdpisolver != NULL );
2512  assert( maxpenaltyparam != NULL );
2513 
2514  compval = penaltyparam * MAXPENALTYPARAM_FACTOR;
2515 
2516  if ( compval < MAX_MAXPENALTYPARAM )
2517  {
2518  *maxpenaltyparam = compval;
2519  SCIPdebugMessage("Setting maximum penaltyparameter to %f.\n", compval);
2520  }
2521  else
2522  {
2523  *maxpenaltyparam = MAX_MAXPENALTYPARAM;
2524  SCIPdebugMessage("Setting penaltyparameter to %f.\n", MAX_MAXPENALTYPARAM);
2525  }
2526 
2527  return SCIP_OKAY;
2528 }
2529 
2535 /*
2536  * File Interface Methods
2537  */
2538 
2543 SCIP_RETCODE SCIPsdpiSolverReadSDP(
2544  SCIP_SDPISOLVER* sdpisolver,
2545  const char* fname
2546  )
2547 {/*lint --e{715,818}*/
2548  SCIPdebugMessage("Not implemented yet\n");
2549  return SCIP_LPERROR;
2550 }
2551 
2553 SCIP_RETCODE SCIPsdpiSolverWriteSDP(
2554  SCIP_SDPISOLVER* sdpisolver,
2555  const char* fname
2556  )
2557 {/*lint --e{818}*/
2558  assert( sdpisolver != NULL );
2559  assert( fname != NULL );
2560 
2561  MOSEK_CALL( MSK_writedata(sdpisolver->msktask, fname) );/*lint !e641*/
2562 
2563  return SCIP_OKAY;
2564 }
2565 
SCIP_RETCODE SCIPsdpiSolverCreate(SCIP_SDPISOLVER **sdpisolver, SCIP_MESSAGEHDLR *messagehdlr, BMS_BLKMEM *blkmem, BMS_BUFMEM *bufmem)
SCIP_Real SCIPsdpiSolverInfinity(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverIncreaseCounter(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverComputeLambdastar(SCIP_SDPISOLVER *sdpisolver, SCIP_Real maxguess)
SCIP_Bool SCIPsdpiSolverWasSolved(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverReadSDP(SCIP_SDPISOLVER *sdpisolver, const char *fname)
#define PENALTYPARAM_FACTOR
#define INFEASMINFEASTOL
SCIP_Bool SCIPsdpiSolverIsConverged(SCIP_SDPISOLVER *sdpisolver)
#define CHECK_IF_SOLVED(sdpisolver)
enum SCIP_SDPSolverSetting SCIP_SDPSOLVERSETTING
Definition: type_sdpi.h:79
SCIP_RETCODE SCIPsdpiSolverResetCounter(SCIP_SDPISOLVER *sdpisolver)
SCIP_Bool SCIPsdpiSolverIsDualFeasible(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverIgnoreInstability(SCIP_SDPISOLVER *sdpisolver, SCIP_Bool *success)
int SCIPsdpiSolverGetInternalStatus(SCIP_SDPISOLVER *sdpisolver)
void * SCIPsdpiSolverGetSolverPointer(SCIP_SDPISOLVER *sdpisolver)
#define MIN_PENALTYPARAM
SCIP_RETCODE SCIPsdpiSolverWriteSDP(SCIP_SDPISOLVER *sdpisolver, const char *fname)
interface methods for specific SDP-solvers
SCIP_RETCODE SCIPsdpiSolverComputeMaxPenaltyparam(SCIP_SDPISOLVER *sdpisolver, SCIP_Real penaltyparam, SCIP_Real *maxpenaltyparam)
SCIP_Bool SCIPsdpiSolverIsInfinity(SCIP_SDPISOLVER *sdpisolver, SCIP_Real val)
SCIP_Bool SCIPsdpiSolverIsPrimalFeasible(SCIP_SDPISOLVER *sdpisolver)
#define MAX_MAXPENALTYPARAM
SCIP_RETCODE SCIPsdpiSolverSettingsUsed(SCIP_SDPISOLVER *sdpisolver, SCIP_SDPSOLVERSETTING *usedsetting)
SCIP_RETCODE SCIPsdpiSolverFree(SCIP_SDPISOLVER **sdpisolver)
#define MAXPENALTYPARAM_FACTOR
#define MOSEK_CALL_BOOL(x)
SCIP_Bool SCIPsdpiSolverIsPrimalUnbounded(SCIP_SDPISOLVER *sdpisolver)
#define TIMEOFDAY_CALL(x)
SCIP_RETCODE SCIPsdpiSolverGetIterations(SCIP_SDPISOLVER *sdpisolver, int *iterations)
SCIP_RETCODE SCIPsdpiSolverGetPrimalMatrix(SCIP_SDPISOLVER *sdpisolver, int nblocks, int *startXnblocknonz, int **startXrow, int **startXcol, SCIP_Real **startXval)
#define PENALTYBOUNDTOL
SCIP_RETCODE SCIPsdpiSolverLoadAndSolve(SCIP_SDPISOLVER *sdpisolver, int nvars, SCIP_Real *obj, SCIP_Real *lb, SCIP_Real *ub, int nsdpblocks, int *sdpblocksizes, int *sdpnblockvars, int sdpconstnnonz, int *sdpconstnblocknonz, int **sdpconstrow, int **sdpconstcol, SCIP_Real **sdpconstval, int sdpnnonz, int **sdpnblockvarnonz, int **sdpvar, int ***sdprow, int ***sdpcol, SCIP_Real ***sdpval, int **indchanges, int *nremovedinds, int *blockindchanges, int nremovedblocks, int nlpcons, int noldlpcons, SCIP_Real *lplhs, SCIP_Real *lprhs, int *rownactivevars, int lpnnonz, int *lprow, int *lpcol, SCIP_Real *lpval, SCIP_Real *starty, int *startZnblocknonz, int **startZrow, int **startZcol, SCIP_Real **startZval, int *startXnblocknonz, int **startXrow, int **startXcol, SCIP_Real **startXval, SCIP_SDPSOLVERSETTING startsettings, SCIP_Real timelimit)
SCIP_RETCODE SCIPsdpiSolverComputePenaltyparam(SCIP_SDPISOLVER *sdpisolver, SCIP_Real maxcoeff, SCIP_Real *penaltyparam)
SCIP_RETCODE SCIPsdpiSolverSetIntpar(SCIP_SDPISOLVER *sdpisolver, SCIP_SDPPARAM type, int ival)
SCIP_Bool SCIPsdpiSolverIsPrimalInfeasible(SCIP_SDPISOLVER *sdpisolver)
int SCIPsdpiSolverGetDefaultSdpiSolverNpenaltyIncreases(void)
SCIP_Bool SCIPsdpiSolverIsOptimal(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpSolcheckerCheck(BMS_BUFMEM *bufmem, int nvars, SCIP_Real *lb, SCIP_Real *ub, int nsdpblocks, int *sdpblocksizes, int *sdpnblockvars, int sdpconstnnonz, int *sdpconstnblocknonz, int **sdpconstrow, int **sdpconstcol, SCIP_Real **sdpconstval, int sdpnnonz, int **sdpnblockvarnonz, int **sdpvar, int ***sdprow, int ***sdpcol, SCIP_Real ***sdpval, int **indchanges, int *nremovedinds, int *blockindchanges, int nlpcons, int noldlpcons, SCIP_Real *lplhs, SCIP_Real *lprhs, int *rownactivevars, int lpnnonz, int *lprow, int *lpcol, SCIP_Real *lpval, SCIP_Real *solvector, SCIP_Real feastol, SCIP_Real epsilon, SCIP_Bool *infeasible)
Definition: sdpsolchecker.c:57
#define INFEASFEASTOLCHANGE
SCIP_Real SCIPsdpiSolverGetDefaultSdpiSolverGaptol(void)
SCIP_RETCODE SCIPsdpiSolverGetSol(SCIP_SDPISOLVER *sdpisolver, SCIP_Real *objval, SCIP_Real *dualsol, int *dualsollength)
SCIP_RETCODE SCIPsdpiSolverGetObjval(SCIP_SDPISOLVER *sdpisolver, SCIP_Real *objval)
#define BMS_CALL(x)
checks a given SDP solution for feasibility
static void MSKAPI printstr(void *handle, MSKCONST char str[])
const char * SCIPsdpiSolverGetSolverDesc(void)
SCIP_RETCODE SCIPsdpiSolverGetPreoptimalPrimalNonzeros(SCIP_SDPISOLVER *sdpisolver, int nblocks, int *startXnblocknonz)
SCIP_Real SCIPsdpiSolverGetDefaultSdpiSolverFeastol(void)
SCIP_Bool SCIPsdpiSolverIsObjlimExc(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverGetPrimalNonzeros(SCIP_SDPISOLVER *sdpisolver, int nblocks, int *startXnblocknonz)
static SCIP_Bool isFixed(SCIP_SDPISOLVER *sdpisolver, SCIP_Real lb, SCIP_Real ub)
SCIP_RETCODE SCIPsdpiSolverGetRealpar(SCIP_SDPISOLVER *sdpisolver, SCIP_SDPPARAM type, SCIP_Real *dval)
SCIP_Bool SCIPsdpiSolverIsDualInfeasible(SCIP_SDPISOLVER *sdpisolver)
#define CHECK_IF_SOLVED_BOOL(sdpisolver)
SCIP_Bool SCIPsdpiSolverIsIterlimExc(SCIP_SDPISOLVER *sdpisolver)
#define MOSEK_CALLM(x)
SCIP_Real SCIPsdpiSolverGetMaxPrimalEntry(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverGetPrimalBoundVars(SCIP_SDPISOLVER *sdpisolver, SCIP_Real *lbvars, SCIP_Real *ubvars, int *arraylength)
const char * SCIPsdpiSolverGetSolverName(void)
SCIP_RETCODE SCIPsdpiSolverGetSdpCalls(SCIP_SDPISOLVER *sdpisolver, int *calls)
SCIP_RETCODE SCIPsdpiSolverGetSolFeasibility(SCIP_SDPISOLVER *sdpisolver, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
SCIP_Bool SCIPsdpiSolverIsAcceptable(SCIP_SDPISOLVER *sdpisolver)
struct SCIP_SDPiSolver SCIP_SDPISOLVER
Definition: sdpisolver.h:70
SCIP_RETCODE SCIPsdpiSolverSetRealpar(SCIP_SDPISOLVER *sdpisolver, SCIP_SDPPARAM type, SCIP_Real dval)
SCIP_RETCODE SCIPsdpiSolverGetIntpar(SCIP_SDPISOLVER *sdpisolver, SCIP_SDPPARAM type, int *ival)
#define MOSEK_CALL(x)
SCIP_RETCODE SCIPsdpiSolverGetPreoptimalSol(SCIP_SDPISOLVER *sdpisolver, SCIP_Bool *success, SCIP_Real *dualsol, int *dualsollength, int nblocks, int *startXnblocknonz, int **startXrow, int **startXcol, SCIP_Real **startXval)
enum SCIP_SDPParam SCIP_SDPPARAM
Definition: type_sdpi.h:68
SCIP_Bool SCIPsdpiSolverIsDualUnbounded(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverLoadAndSolveWithPenalty(SCIP_SDPISOLVER *sdpisolver, SCIP_Real penaltyparam, SCIP_Bool withobj, SCIP_Bool rbound, int nvars, SCIP_Real *obj, SCIP_Real *lb, SCIP_Real *ub, int nsdpblocks, int *sdpblocksizes, int *sdpnblockvars, int sdpconstnnonz, int *sdpconstnblocknonz, int **sdpconstrow, int **sdpconstcol, SCIP_Real **sdpconstval, int sdpnnonz, int **sdpnblockvarnonz, int **sdpvar, int ***sdprow, int ***sdpcol, SCIP_Real ***sdpval, int **indchanges, int *nremovedinds, int *blockindchanges, int nremovedblocks, int nlpcons, int noldlpcons, SCIP_Real *lplhs, SCIP_Real *lprhs, int *rownactivevars, int lpnnonz, int *lprow, int *lpcol, SCIP_Real *lpval, SCIP_Real *starty, int *startZnblocknonz, int **startZrow, int **startZcol, SCIP_Real **startZval, int *startXnblocknonz, int **startXrow, int **startXcol, SCIP_Real **startXval, SCIP_SDPSOLVERSETTING startsettings, SCIP_Real timelimit, SCIP_Bool *feasorig, SCIP_Bool *penaltybound)
SCIP_Bool SCIPsdpiSolverIsTimelimExc(SCIP_SDPISOLVER *sdpisolver)
char name[SCIP_MAXSTRLEN]
SCIP_Bool SCIPsdpiSolverDoesWarmstartNeedPrimal(void)
SCIP_Bool SCIPsdpiSolverFeasibilityKnown(SCIP_SDPISOLVER *sdpisolver)
#define MAX_PENALTYPARAM