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