SCIP-SDP  3.0.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 8;
323 }
324 
328 /*
329  * SDPI Creation and Destruction Methods
330  */
331 
336 SCIP_RETCODE SCIPsdpiSolverCreate(
337  SCIP_SDPISOLVER** sdpisolver,
338  SCIP_MESSAGEHDLR* messagehdlr,
339  BMS_BLKMEM* blkmem,
340  BMS_BUFMEM* bufmem
341  )
342 {
343  assert( sdpisolver != NULL );
344  assert( blkmem != NULL );
345  assert( bufmem != NULL );
346 
347  SCIPdebugMessage("Calling SCIPsdpiCreate \n");
348 
349  BMS_CALL( BMSallocBlockMemory(blkmem, sdpisolver) );
350 
351  (*sdpisolver)->messagehdlr = messagehdlr;
352  (*sdpisolver)->blkmem = blkmem;
353  (*sdpisolver)->bufmem = bufmem;
354 
355  MOSEK_CALLM( MSK_makeenv(&((*sdpisolver)->mskenv), NULL) );/*lint !e641*/ /* the NULL-argument is a debug file, but setting this will spam the whole folder */
356 
357  /* this will be properly initialized then calling solve */
358  (*sdpisolver)->msktask = NULL;
359 
360  (*sdpisolver)->nvars = 0;
361  (*sdpisolver)->nactivevars = 0;
362  (*sdpisolver)->inputtomosekmapper = NULL;
363  (*sdpisolver)->mosektoinputmapper = NULL;
364  (*sdpisolver)->fixedvarsval = NULL;
365  (*sdpisolver)->fixedvarsobjcontr = 0.0;
366  (*sdpisolver)->objcoefs = NULL;
367  (*sdpisolver)->nvarbounds = 0;
368  (*sdpisolver)->varboundpos = NULL;
369  (*sdpisolver)->solved = FALSE;
370  (*sdpisolver)->sdpcounter = 0;
371 
372  (*sdpisolver)->epsilon = 1e-9;
373  (*sdpisolver)->gaptol = 1e-4;
374  (*sdpisolver)->feastol = 1e-6;
375  (*sdpisolver)->sdpsolverfeastol = 1e-6;
376  (*sdpisolver)->objlimit = SCIPsdpiSolverInfinity(*sdpisolver);
377  (*sdpisolver)->sdpinfo = FALSE;
378  (*sdpisolver)->nthreads = -1;
379  (*sdpisolver)->timelimit = FALSE;
380  (*sdpisolver)->timelimitinitial = FALSE;
381 
382  return SCIP_OKAY;
383 }
384 
386 SCIP_RETCODE SCIPsdpiSolverFree(
387  SCIP_SDPISOLVER** sdpisolver
388  )
389 {
390  assert( sdpisolver != NULL );
391  assert( *sdpisolver != NULL );
392 
393  SCIPdebugMessage("Freeing SDPISolver\n");
394 
395  if ( ((*sdpisolver)->msktask) != NULL )
396  {
397  MOSEK_CALL( MSK_deletetask(&((*sdpisolver)->msktask)) );/*lint !e641*/
398  }
399 
400  if ( ((*sdpisolver)->mskenv) != NULL )
401  {
402  MOSEK_CALL( MSK_deleteenv(&((*sdpisolver)->mskenv)) );/*lint !e641*/
403  }
404 
405  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->varboundpos, 2 * (*sdpisolver)->nactivevars); /*lint !e647*/
406  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->inputtomosekmapper, (*sdpisolver)->nvars);/*lint !e737*/
407  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->mosektoinputmapper, (*sdpisolver)->nactivevars);/*lint !e737*/
408  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->fixedvarsval, (*sdpisolver)->nvars - (*sdpisolver)->nactivevars); /*lint !e776*/
409  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->objcoefs, (*sdpisolver)->nactivevars); /*lint !e776*/
410 
411  BMSfreeBlockMemory((*sdpisolver)->blkmem, sdpisolver);
412 
413  return SCIP_OKAY;
414 }
415 
417 SCIP_RETCODE SCIPsdpiSolverIncreaseCounter(
418  SCIP_SDPISOLVER* sdpisolver
419  )
420 {
421  assert( sdpisolver != NULL );
422 
423  sdpisolver->sdpcounter++;
424 
425  return SCIP_OKAY;
426 }
427 
429 SCIP_RETCODE SCIPsdpiSolverResetCounter(
430  SCIP_SDPISOLVER* sdpisolver
431  )
432 {
433  assert( sdpisolver != NULL );
434 
435  SCIPdebugMessage("Resetting counter of SDP-Interface from %d to 0.\n", sdpisolver->sdpcounter);
436  sdpisolver->sdpcounter = 0;
437 
438  return SCIP_OKAY;
439 }
440 
444 /*
445  * Solving Methods
446  */
447 
463 SCIP_RETCODE SCIPsdpiSolverLoadAndSolve(
464  SCIP_SDPISOLVER* sdpisolver,
465  int nvars,
466  SCIP_Real* obj,
467  SCIP_Real* lb,
468  SCIP_Real* ub,
469  int nsdpblocks,
470  int* sdpblocksizes,
471  int* sdpnblockvars,
472  int sdpconstnnonz,
473  int* sdpconstnblocknonz,
475  int** sdpconstrow,
476  int** sdpconstcol,
477  SCIP_Real** sdpconstval,
478  int sdpnnonz,
479  int** sdpnblockvarnonz,
481  int** sdpvar,
483  int*** sdprow,
484  int*** sdpcol,
485  SCIP_Real*** sdpval,
486  int** indchanges,
488  int* nremovedinds,
489  int* blockindchanges,
490  int nremovedblocks,
491  int nlpcons,
492  int noldlpcons,
493  SCIP_Real* lplhs,
494  SCIP_Real* lprhs,
495  int* rownactivevars,
496  int lpnnonz,
497  int* lprow,
498  int* lpcol,
499  SCIP_Real* lpval,
500  SCIP_Real* start,
501  SCIP_SDPSOLVERSETTING startsettings,
503  SCIP_Real timelimit
504  )
505 {
506  return SCIPsdpiSolverLoadAndSolveWithPenalty(sdpisolver, 0.0, TRUE, FALSE, nvars, obj, lb, ub, nsdpblocks, sdpblocksizes, sdpnblockvars, sdpconstnnonz,
507  sdpconstnblocknonz, sdpconstrow, sdpconstcol, sdpconstval, sdpnnonz, sdpnblockvarnonz, sdpvar, sdprow, sdpcol, sdpval, indchanges,
508  nremovedinds, blockindchanges, nremovedblocks, nlpcons, noldlpcons, lplhs, lprhs, rownactivevars, lpnnonz, lprow, lpcol, lpval, start,
509  startsettings, timelimit, NULL, NULL);
510 }
511 
532  SCIP_SDPISOLVER* sdpisolver,
533  SCIP_Real penaltyparam,
534  SCIP_Bool withobj,
535  SCIP_Bool rbound,
536  int nvars,
537  SCIP_Real* obj,
538  SCIP_Real* lb,
539  SCIP_Real* ub,
540  int nsdpblocks,
541  int* sdpblocksizes,
542  int* sdpnblockvars,
543  int sdpconstnnonz,
544  int* sdpconstnblocknonz,
546  int** sdpconstrow,
547  int** sdpconstcol,
548  SCIP_Real** sdpconstval,
549  int sdpnnonz,
550  int** sdpnblockvarnonz,
552  int** sdpvar,
554  int*** sdprow,
555  int*** sdpcol,
556  SCIP_Real*** sdpval,
557  int** indchanges,
559  int* nremovedinds,
560  int* blockindchanges,
561  int nremovedblocks,
562  int nlpcons,
563  int noldlpcons,
564  SCIP_Real* lplhs,
565  SCIP_Real* lprhs,
566  int* rownactivevars,
567  int lpnnonz,
568  int* lprow,
569  int* lpcol,
570  SCIP_Real* lpval,
571  SCIP_Real* start,
572  SCIP_SDPSOLVERSETTING startsettings,
574  SCIP_Real timelimit,
575  SCIP_Bool* feasorig,
577  SCIP_Bool* penaltybound
579 )
580 {/*lint --e{715,818}*/
581  int b;
582  int i;
583  int j;
584  int blockvar;
585  int v;
586  int k;
587  long long ind;
588  int mosekind = 0;
589  SCIP_Real* mosekvarbounds;
590  int nfixedvars;
591  int oldnactivevars;
592  int* vartorowmapper; /* maps the lpvars to the corresponding left- and right-hand-sides of the LP constraints */
593  int* vartolhsrhsmapper; /* maps the lpvars to the corresponding entries in lplhs and lprhs */
594  int nlpvars;
595  int pos;
596  int newpos;
597  int* mosekblocksizes;
598  SCIP_Real one; /* MOSEK always wants a pointer to factors for a sum of matrices, we always use a single matrix with factor one */
599  int* mosekrow;
600  int* mosekcol;
601  SCIP_Real* mosekval;
602  int row;
603  SCIP_Real val;
604  struct timeval starttime;
605  struct timeval currenttime;
606  SCIP_Real startseconds;
607  SCIP_Real currentseconds;
608  SCIP_Real elapsedtime;
609 #ifdef SCIP_MORE_DEBUG
610  int nmosekconss;
611  int nmosekvars;
612  int nmosekcones;
613  char varname[SCIP_MAXSTRLEN];
614 #endif
615 #if CONVERT_ABSOLUTE_TOLERANCES
616  SCIP_Real maxrhscoef; /* MOSEK uses a relative feasibility tolerance, the largest rhs-coefficient is needed for converting the absolute tolerance */
617 #endif
618 
619  assert( sdpisolver != NULL );
620  assert( sdpisolver->mskenv != NULL );
621  assert( penaltyparam > -1 * sdpisolver->epsilon );
622  assert( penaltyparam < sdpisolver->epsilon || ( feasorig != NULL ) );
623  assert( nvars > 0 );
624  assert( obj != NULL );
625  assert( lb != NULL );
626  assert( ub != NULL );
627  assert( nsdpblocks >= 0 );
628  assert( nsdpblocks == 0 || sdpblocksizes != NULL );
629  assert( nsdpblocks == 0 || sdpnblockvars != NULL );
630  assert( sdpconstnnonz >= 0 );
631  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstnblocknonz != NULL );
632  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstrow != NULL );
633  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstcol != NULL );
634  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstval != NULL );
635  assert( sdpnnonz >= 0 );
636  assert( nsdpblocks == 0 || sdpnblockvarnonz != NULL );
637  assert( nsdpblocks == 0 || sdpvar != NULL );
638  assert( nsdpblocks == 0 || sdprow != NULL );
639  assert( nsdpblocks == 0 || sdpcol != NULL );
640  assert( nsdpblocks == 0 || sdpval != NULL );
641  assert( nsdpblocks == 0 || indchanges != NULL );
642  assert( nsdpblocks == 0 || nremovedinds != NULL );
643  assert( nsdpblocks == 0 || blockindchanges != NULL );
644  assert( 0 <= nremovedblocks && nremovedblocks <= nsdpblocks );
645  assert( nlpcons >= 0 );
646  assert( noldlpcons >= nlpcons );
647  assert( nlpcons == 0 || lplhs != NULL );
648  assert( nlpcons == 0 || lprhs != NULL );
649  assert( nlpcons == 0 || rownactivevars != NULL );
650  assert( lpnnonz >= 0 );
651  assert( nlpcons == 0 || lprow != NULL );
652  assert( nlpcons == 0 || lpcol != NULL );
653  assert( nlpcons == 0 || lpval != NULL );
654 
655  /* check the timelimit */
656  if ( timelimit <= 0.0 )
657  {
658  sdpisolver->timelimit = TRUE;
659  sdpisolver->timelimitinitial = TRUE;
660  sdpisolver->solved = FALSE;
661  return SCIP_OKAY;
662  }
663  sdpisolver->timelimit = FALSE;
664  sdpisolver->timelimitinitial = FALSE;
665  sdpisolver->feasorig = FALSE;
666 
667  /* start the timing */
668  TIMEOFDAY_CALL( gettimeofday(&starttime, NULL) );/*lint !e438, !e550, !e641 */
669 
670  one = 1.0;
671 #if CONVERT_ABSOLUTE_TOLERANCES
672  maxrhscoef = 0.0;
673 #endif
674 
675  /* create an empty task (second and third argument are guesses for maximum number of constraints and variables), if there already is one, delete it */
676  if ((sdpisolver->msktask) != NULL)
677  {
678  MOSEK_CALL( MSK_deletetask(&(sdpisolver->msktask)) );/*lint !e641*/
679  }
680  if ( penaltyparam < sdpisolver->epsilon )
681  {
682  MOSEK_CALLM( MSK_maketask(sdpisolver->mskenv, nvars, nsdpblocks - nremovedblocks + nlpcons + 2 * nvars, &(sdpisolver->msktask)) );/*lint !e641*/
683  }
684  else
685  {
686  MOSEK_CALLM( MSK_maketask(sdpisolver->mskenv, nvars + 1, nsdpblocks - nremovedblocks + nlpcons + 2 * nvars, &(sdpisolver->msktask)) );/*lint !e641*/
687  }
688 
689 #ifdef SCIP_MORE_DEBUG
690  MOSEK_CALL( MSK_linkfunctotaskstream (sdpisolver->msktask, MSK_STREAM_LOG, NULL, printstr) ); /* output to console */
691 #else
692  /* if sdpinfo is true, redirect output to console */
693  if ( sdpisolver->sdpinfo )
694  {
695  MOSEK_CALL( MSK_linkfunctotaskstream (sdpisolver->msktask, MSK_STREAM_LOG, NULL, printstr) );/*lint !e641*/
696  }
697 #endif
698 
699  /* set number of threads */
700  if ( sdpisolver->nthreads > 0 )
701  {
702  MOSEK_CALL( MSK_putintparam(sdpisolver->msktask, MSK_IPAR_NUM_THREADS, sdpisolver->nthreads) );/*lint !e641*/
703  }
704 
705  /* 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
706  * same SDP) */
707  if ( penaltyparam < sdpisolver->epsilon )
708  SCIPdebugMessage("Inserting Data into MOSEK for SDP (%d) \n", ++sdpisolver->sdpcounter);
709  else
710  SCIPdebugMessage("Inserting Data again into MOSEK for SDP (%d) \n", sdpisolver->sdpcounter);
711 
712  /* set the penalty and rbound flags accordingly */
713  sdpisolver->penalty = (penaltyparam < sdpisolver->epsilon) ? FALSE : TRUE;
714  sdpisolver->rbound = rbound;
715 
716  /* allocate memory for inputtomosekmapper, mosektoinputmapper and the fixed and active variable information, for the latter this will
717  * later be shrinked if the needed size is known */
718  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->inputtomosekmapper), sdpisolver->nvars, nvars) );
719  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->mosektoinputmapper), sdpisolver->nactivevars, nvars) );
720  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->fixedvarsval), sdpisolver->nvars - sdpisolver->nactivevars, nvars) ); /*lint !e776*/
721  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->objcoefs), sdpisolver->nactivevars, nvars) ); /*lint !e776*/
722 
723  oldnactivevars = sdpisolver->nactivevars; /* we need to save this to realloc the varboundpos-array if needed */
724  sdpisolver->nvars = nvars;
725  sdpisolver->nactivevars = 0;
726  nfixedvars = 0;
727 
728  /* find the fixed variables */
729  sdpisolver->fixedvarsobjcontr = 0.0;
730  for (i = 0; i < nvars; i++)
731  {
732  if ( isFixed(sdpisolver, lb[i], ub[i]) )
733  {
734  sdpisolver->fixedvarsobjcontr += obj[i] * lb[i]; /* this is the value this fixed variable contributes to the objective */
735  sdpisolver->fixedvarsval[nfixedvars] = lb[i]; /* if lb=ub, then this is the value the variable will have in every solution */
736  nfixedvars++;
737  sdpisolver->inputtomosekmapper[i] = -nfixedvars;
738  SCIPdebugMessage("Fixing variable %d locally to %f for SDP %d in MOSEK\n", i, lb[i], sdpisolver->sdpcounter);
739  }
740  else
741  {
742  sdpisolver->mosektoinputmapper[sdpisolver->nactivevars] = i;
743  sdpisolver->inputtomosekmapper[i] = sdpisolver->nactivevars;
744  sdpisolver->objcoefs[sdpisolver->nactivevars] = obj[i];
745  sdpisolver->nactivevars++;
746 #ifdef SCIP_MORE_DEBUG
747  SCIPdebugMessage("Variable %d becomes variable %d for SDP %d in MOSEK\n", i, sdpisolver->inputtomosekmapper[i], sdpisolver->sdpcounter);
748 #endif
749  }
750  }
751  assert( sdpisolver->nactivevars + nfixedvars == sdpisolver->nvars );
752 
753  /* if we want to solve without objective, we reset fixedvarsobjcontr */
754  if ( ! withobj )
755  sdpisolver->fixedvarsobjcontr = 0.0;
756 
757  /* shrink the fixedvars, objcoefs and mosektoinputmapper arrays to the right size */
758  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->objcoefs), nvars, sdpisolver->nactivevars) );
759  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->fixedvarsval), nvars, nfixedvars) );
760  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->mosektoinputmapper), nvars, sdpisolver->nactivevars) );
761 
762  /* compute number of variable bounds and save them in mosekvarbounds */
763  sdpisolver->nvarbounds = 0;
764  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &mosekvarbounds, 2 * sdpisolver->nactivevars) ); /*lint !e647*/
765 
766  if ( sdpisolver->nactivevars != oldnactivevars )
767  {
768  if ( sdpisolver->varboundpos == NULL )
769  {
770  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->varboundpos), 2 * sdpisolver->nactivevars) ); /*lint !e647*/
771  }
772  else
773  {
774  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->varboundpos), 2 * oldnactivevars, 2 * sdpisolver->nactivevars) ); /*lint !e647*/
775  }
776  }
777  assert( sdpisolver->varboundpos != NULL );
778 
779  for (i = 0; i < sdpisolver->nactivevars; i++)
780  {
781  assert( 0 <= sdpisolver->mosektoinputmapper[i] && sdpisolver->mosektoinputmapper[i] < nvars );
782  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, lb[sdpisolver->mosektoinputmapper[i]]) )
783  {
784  mosekvarbounds[sdpisolver->nvarbounds] = lb[sdpisolver->mosektoinputmapper[i]];
785  sdpisolver->varboundpos[sdpisolver->nvarbounds] = -(i + 1); /* negative sign means lower bound */
786  (sdpisolver->nvarbounds)++;
787  }
788  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, ub[sdpisolver->mosektoinputmapper[i]]) )
789  {
790  mosekvarbounds[sdpisolver->nvarbounds] = -1 * ub[sdpisolver->mosektoinputmapper[i]]; /* we give the upper bounds a negative sign for the objective */
791  sdpisolver->varboundpos[sdpisolver->nvarbounds] = +(i + 1); /* positive sign means upper bound */
792  (sdpisolver->nvarbounds)++;
793  }
794  }
795 
796  if ( nlpcons > 0 )
797  {
798  /* allocate memory to save which lpvariable corresponds to which lp constraint, negative signs correspond to left-hand-sides of lp constraints,
799  * 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 */
800  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &vartorowmapper, 2*noldlpcons) ); /*lint !e647*/ /*lint !e530*/
801  /* allocate memory to save at which indices the corresponding lhss and rhss of the lpvars are saved */
802  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &vartolhsrhsmapper, 2*noldlpcons) ); /*lint !e647*/ /*lint !e530*/
803 
804  /* compute the number of LP constraints after splitting the ranged rows and compute the rowtovarmapper */
805  pos = 0;
806  newpos = 0; /* the position in the lhs and rhs arrays */
807  for (i = 0; i < noldlpcons; i++)
808  {
809  assert( newpos <= nlpcons );
810  if ( rownactivevars[i] >= 2 )
811  {
812  if ( lplhs[newpos] > - SCIPsdpiSolverInfinity(sdpisolver) )
813  {
814  vartorowmapper[pos] = -(i+1);
815  vartolhsrhsmapper[pos] = newpos;
816  pos++;
817 
818 #if CONVERT_ABSOLUTE_TOLERANCES
819  /* update largest rhs-entry */
820  if ( REALABS(lplhs[newpos]) > maxrhscoef )
821  maxrhscoef = REALABS(lplhs[newpos]);
822 #endif
823 
824  }
825  if ( lprhs[newpos] < SCIPsdpiSolverInfinity(sdpisolver) )
826  {
827  vartorowmapper[pos] = i+1;
828  vartolhsrhsmapper[pos] = newpos;
829  pos++;
830 
831 #if CONVERT_ABSOLUTE_TOLERANCES
832  /* update largest rhs-entry */
833  if ( REALABS(lprhs[newpos]) > maxrhscoef )
834  maxrhscoef = REALABS(lprhs[newpos]);
835 #endif
836  }
837  newpos++;
838  }
839  }
840  nlpvars = pos;
841  assert( nlpvars <= 2*nlpcons ); /* *2 comes from left- and right-hand-sides */
842  }
843  else
844  nlpvars = 0;
845 
846  /* create matrix variables */
847  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &mosekblocksizes, nsdpblocks - nremovedblocks) ); /*lint !e679 !e776*/
848 
849  for (b = 0; b < nsdpblocks; b++)
850  {
851  if ( blockindchanges[b] > -1 )
852  {
853  assert( 0 <= blockindchanges[b] && blockindchanges[b] <= b && (b - blockindchanges[b]) <= (nsdpblocks - nremovedblocks) );
854  mosekblocksizes[b - blockindchanges[b]] = sdpblocksizes[b] - nremovedinds[b];/*lint !e679*/
855  }
856  }
857  MOSEK_CALLM( MSK_appendbarvars(sdpisolver->msktask, nsdpblocks - nremovedblocks, mosekblocksizes) );/*lint !e641*/
858 
859  /* create scalar variables (since we solve the primal problem, these are not the active variables but the dual variables for the
860  * lp constraints and variable bounds) */
861  MOSEK_CALLM( MSK_appendvars(sdpisolver->msktask, nlpvars + sdpisolver->nvarbounds) );/*lint !e641*/
862 
863  /* all of these are non-negative */
864  for (v = 0; v < nlpvars + sdpisolver->nvarbounds; v++)
865  {
866  MOSEK_CALL( MSK_putvarbound(sdpisolver->msktask, v, MSK_BK_LO, 0.0, (double) MSK_DPAR_DATA_TOL_BOUND_INF) );/*lint !e641*/
867  }
868 
869  /* append empty constraints (since we solve the primal problem, we get one constraint for each active variable) */
870  MOSEK_CALLM( MSK_appendcons(sdpisolver->msktask, (penaltyparam < sdpisolver->epsilon) ? sdpisolver->nactivevars : sdpisolver->nactivevars + 1) );/*lint !e641*/
871 
872  /* set objective values for the matrix variables */
873  i = 0;
874 
875  if ( sdpconstnnonz > 0 )
876  {
877  for (b = 0; b < nsdpblocks; b++)
878  {
879  if ( blockindchanges[b] > -1 )
880  {
881  /* if some indices in the block were removed, we need to change indices accordingly */
882  if ( nremovedinds[b] > 0 )
883  {
884  int* moseksdpconstrow;
885  int* moseksdpconstcol;
886 
887  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &moseksdpconstrow, sdpconstnblocknonz[b]) );
888  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &moseksdpconstcol, sdpconstnblocknonz[b]) );
889 
890  for (k = 0; k < sdpconstnblocknonz[b]; k++)
891  {
892  /* rows and cols with active nonzeros should not be removed */
893  assert( -1 < indchanges[b][sdpconstrow[b][k]] && indchanges[b][sdpconstrow[b][k]] <= sdpconstrow[b][k] );
894  assert( -1 < indchanges[b][sdpconstcol[b][k]] && indchanges[b][sdpconstcol[b][k]] <= sdpconstcol[b][k] );
895 
896  assert( 0 <= sdpconstrow[b][k] && sdpconstrow[b][k] <= sdpblocksizes[b] );
897  assert( 0 <= sdpconstcol[b][k] && sdpconstcol[b][k] <= sdpblocksizes[b] );
898 
899  moseksdpconstrow[k] = sdpconstrow[b][k] - indchanges[b][sdpconstrow[b][k]];
900  moseksdpconstcol[k] = sdpconstcol[b][k] - indchanges[b][sdpconstcol[b][k]];
901 
902 #if CONVERT_ABSOLUTE_TOLERANCES
903  /* update largest rhs-entry */
904  if ( REALABS(sdpconstval[b][k]) > maxrhscoef )
905  maxrhscoef = REALABS(sdpconstval[b][k]);
906 #endif
907  }
908 
909  MOSEK_CALL( MSK_appendsparsesymmat(sdpisolver->msktask, mosekblocksizes[b - blockindchanges[b]], sdpconstnblocknonz[b],
910  moseksdpconstrow, moseksdpconstcol, sdpconstval[b], &ind) );/*lint !e641, !e679, !e747*/
911 
912  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &moseksdpconstcol);
913  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &moseksdpconstrow);
914  }
915  else
916  {
917  MOSEK_CALL( MSK_appendsparsesymmat(sdpisolver->msktask, mosekblocksizes[b - blockindchanges[b]], sdpconstnblocknonz[b],
918  sdpconstrow[b], sdpconstcol[b], sdpconstval[b], &ind) );/*lint !e641, !e679, !e747*/
919  }
920  MOSEK_CALL( MSK_putbarcj(sdpisolver->msktask, i, 1, &ind, &one) );/*lint !e641, !e747*/
921  i++;
922  }
923  }
924  }
925 
926  /* set objective values for the scalar variables */
927  /* first for those corresponding to LP constraints in the dual */
928  for (i = 0; i < nlpvars; i++)
929  {
930  if ( vartorowmapper[i] > 0 )/*lint !e644*/ /* right-hand side */
931  {
932  MOSEK_CALL( MSK_putcj(sdpisolver->msktask, i, -1 * lprhs[vartolhsrhsmapper[i]]) );/*lint !e641, !e644*/
933 #ifdef SCIP_MORE_DEBUG
934  /* give the variable a meaningful name for debug output */
935  (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "rhs-%d", vartorowmapper[i] - 1);
936  MOSEK_CALL( MSK_putvarname ( sdpisolver->msktask, i, varname) );
937 #endif
938  }
939  else /* left-hand side */
940  {
941  assert( vartorowmapper[i] < 0 ); /* we should not have value 0 so that we can clearly differentiate between positive and negative */
942  MOSEK_CALL( MSK_putcj(sdpisolver->msktask, i, lplhs[vartolhsrhsmapper[i]]) );/*lint !e641*/
943 #ifdef SCIP_MORE_DEBUG
944  /* give the variable a meaningful name for debug output */
945  (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "lhs-%d", -1 * vartorowmapper[i] - 1);
946  MOSEK_CALL( MSK_putvarname ( sdpisolver->msktask, i, varname) );
947 #endif
948  }
949  }
950 
951  /* finally for those corresponding to variable bounds in the dual */
952  for (i = 0; i < sdpisolver->nvarbounds; i++)
953  {
954  MOSEK_CALL( MSK_putcj(sdpisolver->msktask, nlpvars + i, mosekvarbounds[i]) );/*lint !e641*/ /* for the ub's we already added a negative sign in mosekvarbounds*/
955 #ifdef SCIP_MORE_DEBUG
956  if ( sdpisolver->varboundpos[i] < 0 ) /* lower bound */
957  {
958  /* give the variable a meaningful name for debug output */
959  (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "lb-%d", sdpisolver->mosektoinputmapper[-1 * sdpisolver->varboundpos[i] - 1]);
960  MOSEK_CALL( MSK_putvarname ( sdpisolver->msktask, nlpvars + i, varname) );
961  }
962  else /* upper bound */
963  {
964  assert( sdpisolver->varboundpos[i] > 0 ); /* we should not have value 0 so that we can clearly differentiate between positive and negative */
965  /* give the variable a meaningful name for debug output */
966  (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "ub-%d", sdpisolver->mosektoinputmapper[sdpisolver->varboundpos[i] - 1]);
967  MOSEK_CALL( MSK_putvarname ( sdpisolver->msktask, nlpvars + i, varname) );
968  }
969 #endif
970  }
971 
972  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &mosekvarbounds);
973 
974  /* set objective sense (since we want to minimize in the dual, we maximize in the primal) */
975  MOSEK_CALL( MSK_putobjsense(sdpisolver->msktask, MSK_OBJECTIVE_SENSE_MAXIMIZE) );/*lint !e641*/
976 
977  /* start inserting the constraints */
978 
979  /* first add the matrices A_i */
980  for (b = 0; b < nsdpblocks; b++)
981  {
982  if ( blockindchanges[b] > -1 )
983  {
984  for (blockvar = 0; blockvar < sdpnblockvars[b]; blockvar++)
985  {
986  v = sdpisolver->inputtomosekmapper[sdpvar[b][blockvar]];
987 
988  /* check if the variable is active */
989  if ( v > -1 )
990  {
991  assert( v < sdpisolver->nactivevars );
992  /* if there are removed indices, we have to adjust the column and row indices accordingly */
993  if ( nremovedinds[b] > 0 )
994  {
995  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &mosekrow, sdpnblockvarnonz[b][blockvar]) );
996  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &mosekcol, sdpnblockvarnonz[b][blockvar]) );
997 
998  for (k = 0; k < sdpnblockvarnonz[b][blockvar]; k++)
999  {
1000  /* rows and cols with active nonzeros should not be removed */
1001  assert( -1 < indchanges[b][sdprow[b][blockvar][k]] && indchanges[b][sdprow[b][blockvar][k]] <= sdprow[b][blockvar][k] );
1002  assert( -1 < indchanges[b][sdpcol[b][blockvar][k]] && indchanges[b][sdpcol[b][blockvar][k]] <= sdpcol[b][blockvar][k] );
1003 
1004  assert( 0 <= sdprow[b][blockvar][k] && sdprow[b][blockvar][k] < sdpblocksizes[b] );
1005  assert( 0 <= sdpcol[b][blockvar][k] && sdpcol[b][blockvar][k] < sdpblocksizes[b] );
1006 
1007  mosekrow[k] = sdprow[b][blockvar][k] - indchanges[b][sdprow[b][blockvar][k]];
1008  mosekcol[k] = sdpcol[b][blockvar][k] - indchanges[b][sdpcol[b][blockvar][k]];
1009  }
1010 
1011  MOSEK_CALL( MSK_appendsparsesymmat(sdpisolver->msktask, mosekblocksizes[b - blockindchanges[b]], (long long) sdpnblockvarnonz[b][blockvar],
1012  mosekrow, mosekcol, sdpval[b][blockvar], &ind) );/*lint !e641, !e679*/
1013 
1014  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &mosekcol);
1015  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &mosekrow);
1016  }
1017  else
1018  {
1019  MOSEK_CALL( MSK_appendsparsesymmat(sdpisolver->msktask, mosekblocksizes[b - blockindchanges[b]], (long long) sdpnblockvarnonz[b][blockvar],
1020  sdprow[b][blockvar], sdpcol[b][blockvar], sdpval[b][blockvar], &ind) );/*lint !e641, !e679*/
1021  }
1022 
1023  MOSEK_CALL( MSK_putbaraij(sdpisolver->msktask, v, b - blockindchanges[b], (long long) 1, &ind, &one) );/*lint !e641*/
1024  }
1025  }
1026  }
1027  }
1028 
1029  /* add the identity matrix corresponding to the penalty variable */
1030  if ( penaltyparam >= sdpisolver->epsilon )
1031  {
1032  int* identityindices;
1033  SCIP_Real* identityvalues;
1034 
1035  for (b = 0; b < nsdpblocks; b++)
1036  {
1037  if ( blockindchanges[b] > -1 )
1038  {
1039  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &identityindices, mosekblocksizes[b - blockindchanges[b]]) );
1040  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &identityvalues, mosekblocksizes[b - blockindchanges[b]]) );
1041 
1042  for (i = 0; i < mosekblocksizes[b - blockindchanges[b]]; i++)
1043  {
1044  identityindices[i] = i;
1045  identityvalues[i] = 1.0;
1046  }
1047  MOSEK_CALL( MSK_appendsparsesymmat(sdpisolver->msktask, mosekblocksizes[b - blockindchanges[b]], (long long) mosekblocksizes[b - blockindchanges[b]],
1048  identityindices, identityindices, identityvalues, &ind) );/*lint !e641, !e679*/
1049  MOSEK_CALL( MSK_putbaraij(sdpisolver->msktask, sdpisolver->nactivevars, b - blockindchanges[b], (long long) 1, &ind, &one) );/*lint !e641, !e679*/
1050 
1051  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &identityvalues);
1052  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &identityindices);
1053  }
1054  }
1055  }
1056 
1057  /* now add the entries corresponding to the lp-constraints in the dual problem */
1058  if ( penaltyparam < sdpisolver->epsilon )
1059  {
1060  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &mosekrow, lpnnonz) );
1061  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &mosekval, lpnnonz) );
1062  }
1063  else
1064  {
1065  /* one extra entry for the penalty-constraint Trace = Gamma */
1066  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &mosekrow, lpnnonz + 1) );/*lint !e776*/
1067  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &mosekval, lpnnonz + 1) );/*lint !e776*/
1068  }
1069 
1070  ind = 0;
1071  for (i = 0; i < nlpvars; i++)
1072  {
1073  if ( vartorowmapper[i] < 0 ) /* left-hand side */
1074  {
1075  mosekind = 0;
1076  /* find the first lp-entry belonging to this variable (those in between have to belong to constraints with less than two active variables and
1077  * will therefore not be used) */
1078  while (ind < lpnnonz && lprow[ind] < -1 * vartorowmapper[i] - 1)
1079  ind++;
1080  /* iterate over all nonzeros to input them to the array given to MOSEK */
1081  while (ind < lpnnonz && lprow[ind] == -1 * vartorowmapper[i] - 1) /* they should already be sorted by rows in the sdpi */
1082  {
1083  v = sdpisolver->inputtomosekmapper[lpcol[ind]];
1084  if ( v > -1 )
1085  {
1086  mosekrow[mosekind] = v;
1087  mosekval[mosekind] = lpval[ind];
1088  mosekind++;
1089  }
1090  ind++;
1091  }
1092  assert( mosekind <= lpnnonz );
1093  }
1094  else /* right-hand side */
1095  {
1096  assert( vartorowmapper[i] > 0 ); /* we should not have value 0 so that we can clearly differentiate between positive and negative */
1097 
1098  if ( i > 0 && vartorowmapper[i] == -1 * vartorowmapper[i - 1] )
1099  {
1100  /* we already iterated over this constraint in the lp-arrays, so we keep the current ind position and as we currenlty have
1101  * the corresponding entries in the mosek-arrays, we iterate over them again just changing the signs (except for the penalty-entry) */
1102  for (j = 0; j < (penaltyparam < sdpisolver->epsilon ? mosekind : mosekind - 1); j++)/*lint !e644*/
1103  mosekval[j] *= -1;
1104  }
1105  else
1106  {
1107  /* no left hand side for this constraint exists, so we didnot yet iterate over this constraint in the lp arrays */
1108  mosekind = 0;
1109  /* find the first lp-entry belonging to this variable (those in between have to belong to constraints with less than two active variables and
1110  * will therefore not be used) */
1111  while (lprow[ind] < vartorowmapper[i] - 1)
1112  ind++;
1113  while (ind < lpnnonz && lprow[ind] == vartorowmapper[i] - 1)
1114  {
1115  v = sdpisolver->inputtomosekmapper[lpcol[ind]];
1116  if ( v > -1 )
1117  {
1118  mosekrow[mosekind] = v;
1119  mosekval[mosekind] = -1 * lpval[ind]; /* because we need to change the <= to a >= constraint */
1120  mosekind++;
1121  }
1122  ind++;
1123  }
1124  assert( mosekind <= lpnnonz );
1125  }
1126  }
1127 
1128  /* add the additional entry for the penalty constraint Trace = Gamma */
1129  if ( penaltyparam >= sdpisolver->epsilon )
1130  {
1131  /* 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,
1132  * since it is already there */
1133  if ( ! (i > 0 && vartorowmapper[i] == -1 * vartorowmapper[i - 1] ))
1134  {
1135  mosekrow[mosekind] = sdpisolver->nactivevars;
1136  mosekval[mosekind] = 1.0;
1137  mosekind++;
1138  }
1139  assert( mosekind <= lpnnonz + 1 );
1140  }
1141 
1142  MOSEK_CALL( MSK_putacol(sdpisolver->msktask, i, mosekind, mosekrow, mosekval) );/*lint !e641*/
1143  }
1144 
1145  BMSfreeBufferMemoryArrayNull(sdpisolver->bufmem, &mosekval);
1146  BMSfreeBufferMemoryArrayNull(sdpisolver->bufmem, &mosekrow);
1147 
1148  /* finally add the entries corresponding to varbounds in the dual problem, we get exactly one entry per variable */
1149  for (i = 0; i < sdpisolver->nvarbounds; i++)
1150  {
1151  if ( sdpisolver->varboundpos[i] < 0 )
1152  {
1153  /* lower bound */
1154  row =-1 * sdpisolver->varboundpos[i] - 1; /* minus one because we added one to get strictly positive/negative values */
1155  val = 1.0;
1156  }
1157  else
1158  {
1159  /* upper bound */
1160  assert( sdpisolver->varboundpos[i] > 0 ); /* we should not have a zero as we wanted a clear differentiation between positive and negative */
1161  row = sdpisolver->varboundpos[i] - 1; /* minus one because we added one to get strictly positive/negative values */
1162  val = -1.0;
1163  }
1164  MOSEK_CALL( MSK_putacol(sdpisolver->msktask, nlpvars + i, 1, &row, &val) );/*lint !e641*/
1165  }
1166 
1167  /* make all constraints equality constraints with right-hand side b_i (or 0 if we solve without objective) */
1168  for (i = 0; i < sdpisolver->nactivevars; i++)
1169  {
1170  if ( withobj )
1171  {
1172  MOSEK_CALL( MSK_putconbound(sdpisolver->msktask, i, MSK_BK_FX, obj[sdpisolver->mosektoinputmapper[i]], obj[sdpisolver->mosektoinputmapper[i]]) );/*lint !e641*/
1173  }
1174  else
1175  {
1176  MOSEK_CALL( MSK_putconbound(sdpisolver->msktask, i, MSK_BK_FX, 0.0, 0.0) );/*lint !e641*/
1177  }
1178 #ifdef SCIP_MORE_DEBUG
1179  /* give the constraint a meaningful name for debug output */
1180  (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "var-%d", sdpisolver->mosektoinputmapper[i]);
1181  MOSEK_CALL( MSK_putconname ( sdpisolver->msktask, i, varname) );
1182 #endif
1183  }
1184 
1185  /* the penalty constraint has right-hand side Gamma, it is a <=-inequality if r was bounded and an equality constraint otherwise */
1186  if ( penaltyparam >= sdpisolver->epsilon )
1187  {
1188  if ( rbound )
1189  {
1190  MOSEK_CALL( MSK_putconbound(sdpisolver->msktask, sdpisolver->nactivevars, MSK_BK_UP, (double) -1 * MSK_DPAR_DATA_TOL_BOUND_INF, penaltyparam) );/*lint !e641*/
1191  }
1192  else
1193  {
1194  MOSEK_CALL( MSK_putconbound(sdpisolver->msktask, sdpisolver->nactivevars, MSK_BK_FX, penaltyparam, penaltyparam) );/*lint !e641*/
1195  }
1196  }
1197 
1198  /* write to file if asked to */
1199 #ifdef SCIP_DEBUG_PRINTTOFILE
1200  SCIP_CALL( SCIPsdpiSolverWriteSDP(sdpisolver, "mosek.task") );
1201 #endif
1202 
1203  /* print whole problem and parameters if asked to */
1204 #ifdef SCIP_MORE_DEBUG
1205  MOSEK_CALL( MSK_getnumcon (sdpisolver->msktask, &nmosekconss) );
1206  MOSEK_CALL( MSK_getnumvar (sdpisolver->msktask, &nmosekvars) );
1207  MOSEK_CALL( MSK_getnumcone (sdpisolver->msktask, &nmosekcones) );
1208 
1209  MOSEK_CALL( MSK_printdata (sdpisolver->msktask, MSK_STREAM_LOG, 0, nmosekconss, 0, nmosekvars, 0, nmosekcones, 1, 1, 1, 1, 1, 1, 1, 1) );
1210 #ifdef SCIP_PRINT_PARAMETERS
1211  MOSEK_CALL( MSK_printparam (sdpisolver->msktask) );
1212 #endif
1213 #endif
1214 
1215  /* set the time limit */
1216  startseconds = (SCIP_Real) starttime.tv_sec + (SCIP_Real) starttime.tv_usec / 1e6;
1217 
1218  TIMEOFDAY_CALL( gettimeofday(&currenttime, NULL) );/*lint !e438, !e550, !e641 */
1219  currentseconds = (SCIP_Real) currenttime.tv_sec + (SCIP_Real) currenttime.tv_usec / 1e6;
1220 
1221  elapsedtime = currentseconds - startseconds;
1222 
1223  if ( timelimit <= elapsedtime )
1224  {
1225  sdpisolver->timelimit = TRUE;
1226  sdpisolver->solved = FALSE;
1227  }
1228  else
1229  {
1230  SCIP_Real feastol;
1231 
1232  /* 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,
1233  * since MOSEK works with relative tolerance, we adjust our absolute tolerance accordingly, so that any solution satisfying the relative
1234  * tolerance in MOSEK satisfies our absolute tolerance) */
1235  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_PFEAS, sdpisolver->gaptol) );/*lint !e641*/
1236 #if CONVERT_ABSOLUTE_TOLERANCES
1237  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_DFEAS, sdpisolver->sdpsolverfeastol / (1 + maxrhscoef)) );/*lint !e641*/
1238  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_INFEAS, sdpisolver->sdpsolverfeastol / (1 + maxrhscoef)) );/*lint !e641*/
1239  SCIPdebugMessage("Setting relative feasibility tolerance for MOSEK to %.10f / %f = %.12f\n", sdpisolver->sdpsolverfeastol,
1240  1+maxrhscoef, sdpisolver->sdpsolverfeastol / (1 + maxrhscoef));
1241 #else
1242  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_DFEAS, sdpisolver->sdpsolverfeastol) );/*lint !e641*/
1243  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_INFEAS, sdpisolver->sdpsolverfeastol) );/*lint !e641*/
1244 #endif
1245  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_MU_RED, sdpisolver->gaptol) );/*lint !e641*/
1246  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_REL_GAP, sdpisolver->gaptol) );/*lint !e641*/
1247 
1248  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, timelimit - elapsedtime) )
1249  {
1250  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_OPTIMIZER_MAX_TIME, timelimit - elapsedtime) );/*lint !e641*/
1251  }
1252 
1253  /* set objective cutoff */
1254  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, sdpisolver->objlimit) )
1255  {
1256  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_UPPER_OBJ_CUT, sdpisolver->objlimit) );/*lint !e641*/
1257  }
1258 
1259  /* solve the problem */
1260  MOSEK_CALL( MSK_optimizetrm(sdpisolver->msktask, &(sdpisolver->terminationcode)) );/*lint !e641*/
1261 
1262  if ( sdpisolver->sdpinfo )
1263  {
1264  MOSEK_CALL( MSK_optimizersummary(sdpisolver->msktask, MSK_STREAM_LOG) );/*lint !e641*/
1265  MOSEK_CALL( MSK_analyzesolution(sdpisolver->msktask, MSK_STREAM_LOG, MSK_SOL_ITR) );/*lint !e641*/
1266  }
1267 
1268  SCIPdebugMessage("Solving problem using MOSEK, return code %d\n", sdpisolver->terminationcode);
1269 
1270  sdpisolver->solved = TRUE;
1271 
1272  sdpisolver->nsdpcalls = 1;
1273  MOSEK_CALL( MSK_getnaintinf(sdpisolver->msktask, "MSK_IINF_INTPNT_ITER", &(sdpisolver->niterations)) );/*lint !e641*/
1274 
1275  /* if the problem has been stably solved but did not reach the required feasibility tolerance, even though the solver
1276  * reports feasibility, resolve it with adjusted tolerance */
1277 #if CONVERT_ABSOLUTE_TOLERANCES
1278  feastol = sdpisolver->sdpsolverfeastol / (1 + maxrhscoef);
1279 #else
1280  feastol = sdpisolver->sdpsolverfeastol;
1281 #endif
1282 
1283  while ( SCIPsdpiSolverIsAcceptable(sdpisolver) && SCIPsdpiSolverIsDualFeasible(sdpisolver) && penaltyparam < sdpisolver->epsilon && feastol >= INFEASMINFEASTOL )
1284  {
1285  SCIP_Real* solvector;
1286  int nvarspointer;
1287  SCIP_Bool infeasible;
1288  int newiterations;
1289 
1290  /* get current solution */
1291  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &solvector, nvars) );
1292  nvarspointer = nvars;
1293  SCIP_CALL( SCIPsdpiSolverGetSol(sdpisolver, NULL, solvector, &nvarspointer) );
1294  assert( nvarspointer == nvars );
1295 
1296  /* check the solution for feasibility with regards to our tolerance */
1297  SCIP_CALL( SCIPsdpSolcheckerCheck(sdpisolver->bufmem, nvars, lb, ub, nsdpblocks, sdpblocksizes, sdpnblockvars, sdpconstnnonz,
1298  sdpconstnblocknonz, sdpconstrow, sdpconstcol, sdpconstval, sdpnnonz, sdpnblockvarnonz, sdpvar, sdprow, sdpcol, sdpval,
1299  indchanges, nremovedinds, blockindchanges, nlpcons, noldlpcons, lplhs, lprhs, rownactivevars, lpnnonz, lprow, lpcol, lpval,
1300  solvector, sdpisolver->feastol, sdpisolver->epsilon, &infeasible) );
1301 
1302  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &solvector);
1303 
1304  if ( infeasible )
1305  {
1306  SCIPdebugMessage("Solution feasible for MOSEK but outside feasibility tolerance, changing MOSEK feasibility tolerance from %f to %f\n",
1307  feastol, feastol * INFEASFEASTOLCHANGE);
1308  feastol *= INFEASFEASTOLCHANGE;
1309 
1310  if ( feastol >= INFEASMINFEASTOL )
1311  {
1312  /* update settings */
1313  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_DFEAS, feastol) );/*lint !e641*/
1314  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_INFEAS, feastol) );/*lint !e641*/
1315 
1316  /* set the time limit */
1317  startseconds = (SCIP_Real) starttime.tv_sec + (SCIP_Real) starttime.tv_usec / 1e6;
1318 
1319  TIMEOFDAY_CALL( gettimeofday(&currenttime, NULL) );/*lint !e438, !e550, !e641 */
1320  currentseconds = (SCIP_Real) currenttime.tv_sec + (SCIP_Real) currenttime.tv_usec / 1e6;
1321 
1322  elapsedtime = currentseconds - startseconds;
1323 
1324  if ( timelimit <= elapsedtime )
1325  {
1326  sdpisolver->timelimit = TRUE;
1327  sdpisolver->solved = FALSE;
1328  }
1329 
1330  /* solve the problem */
1331  MOSEK_CALL( MSK_optimizetrm(sdpisolver->msktask, &(sdpisolver->terminationcode)) );/*lint !e641*/
1332 
1333  if ( sdpisolver->sdpinfo )
1334  {
1335  MOSEK_CALL( MSK_optimizersummary(sdpisolver->msktask, MSK_STREAM_LOG) );/*lint !e641*/
1336  MOSEK_CALL( MSK_analyzesolution(sdpisolver->msktask, MSK_STREAM_LOG, MSK_SOL_ITR) );/*lint !e641*/
1337  }
1338 
1339  /* update number of SDP-iterations and -calls */
1340  sdpisolver->nsdpcalls++;
1341  MOSEK_CALL( MSK_getnaintinf(sdpisolver->msktask, "MSK_IINF_INTPNT_ITER", &newiterations) );/*lint !e641*/
1342  sdpisolver->niterations += newiterations;
1343  }
1344  else
1345  {
1346  sdpisolver->solved = FALSE;
1347  SCIPmessagePrintInfo(sdpisolver->messagehdlr, "MOSEK failed to reach required feasibility tolerance! \n");
1348  }
1349  }
1350  else
1351  break;
1352  }
1353  }
1354 
1355 
1356  /* if using a penalty formulation, check if the solution is feasible for the original problem */
1357  if ( penaltyparam >= sdpisolver->epsilon && ( ! sdpisolver->timelimit ) && ( sdpisolver->terminationcode != MSK_RES_TRM_MAX_TIME ) )
1358  {
1359  SCIP_Real* moseksol;
1360  SCIP_Real trace = 0.0;
1361  SCIP_Real* x;
1362 
1363  assert( feasorig != NULL );
1364 
1365  /* get the r variable in the dual problem */
1366  BMSallocBufferMemoryArray(sdpisolver->bufmem, &moseksol, sdpisolver->nactivevars + 1);/*lint !e776*/
1367 
1368  MOSEK_CALL( MSK_gety(sdpisolver->msktask, MSK_SOL_ITR, moseksol) );/*lint !e641*/
1369 
1370  *feasorig = (moseksol[sdpisolver->nactivevars] < sdpisolver->feastol); /*lint !e413*/
1371 
1372  /* only set sdpisolver->feasorig to true if we solved with objective, because only in this case we want to compute
1373  * the objective value by hand since it is numerically more stable then the result returned by DSDP */
1374  if ( withobj )
1375  sdpisolver->feasorig = *feasorig;
1376 
1377  /* if r > 0 also check the primal bound */
1378  if ( ! *feasorig && penaltybound != NULL )
1379  {
1380 
1381  SCIPdebugMessage("Solution not feasible in original problem, r = %f\n", moseksol[sdpisolver->nactivevars]);
1382 
1383  /* compute Tr(X) */
1384 
1385  /* start with the diagonal entries of the primal semidefinite variables */
1386  for (b = 0; b < nsdpblocks; b++)
1387  {
1388  if ( blockindchanges[b] > -1 )
1389  {
1390  SCIP_Real* X; /* the upper triangular entries of matrix X */
1391  int size;
1392 
1393  size = sdpblocksizes[b] - nremovedinds[b];
1394 
1395  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &X, 0.5 * size * (size + 1)) );
1396  MOSEK_CALL( MSK_getbarxj(sdpisolver->msktask, MSK_SOL_ITR, b - blockindchanges[b], X) );/*lint !e641*/
1397 
1398  /* iterate over all diagonal entries */
1399  for (i = 0; i < size; i++)
1400  {
1401  /* get index in the lower triangular part */
1402  ind = 0.5 * i * (i + 3);/*lint !e776*/ /* i*(i+1)/2 + i */
1403  assert( ind < 0.5 * size * (size + 1) );
1404  trace += X[ind];
1405  }
1406 
1407  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &X);
1408  }
1409  }
1410 
1411  /* add primal lp-variables */
1412  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &x, nlpvars + sdpisolver->nvarbounds) );
1413 
1414  MOSEK_CALL( MSK_getxx(sdpisolver->msktask, MSK_SOL_ITR, x) );/*lint !e641*/
1415 
1416  for (i = 0; i < nlpvars; i++)
1417  trace += x[i];
1418 
1419  BMSfreeBufferMemoryArrayNull(sdpisolver->bufmem, &x);
1420 
1421  /* if the relative gap is smaller than the tolerance, we return equality */
1422  if ( (penaltyparam - trace) / penaltyparam < PENALTYBOUNDTOL )/*lint !e414*/
1423  {
1424  if ( penaltybound != NULL )
1425  *penaltybound = TRUE;
1426  SCIPdebugMessage("Tr(X) = %f == %f = Gamma, penalty formulation not exact, Gamma should be increased or problem is infeasible\n",
1427  trace, penaltyparam);
1428  }
1429  else if ( penaltybound != NULL )
1430  *penaltybound = FALSE;
1431  }
1432  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &moseksol);
1433  }
1434 
1435  /* free memory */
1436  BMSfreeBufferMemoryArrayNull(sdpisolver->bufmem, &mosekblocksizes);
1437  if ( nlpcons > 0 )
1438  {
1439  BMSfreeBufferMemoryArrayNull(sdpisolver->bufmem, &vartolhsrhsmapper);
1440  BMSfreeBufferMemoryArrayNull(sdpisolver->bufmem, &vartorowmapper);
1441  }
1442 
1443  return SCIP_OKAY;
1444 }
1450 /*
1451  * Solution Information Methods
1452  */
1453 
1458 SCIP_Bool SCIPsdpiSolverWasSolved(
1459  SCIP_SDPISOLVER* sdpisolver
1460  )
1461 {/*lint --e{818}*/
1462  assert( sdpisolver != NULL );
1463 
1464  return sdpisolver->solved;
1465 }
1466 
1474  SCIP_SDPISOLVER* sdpisolver
1475  )
1476 {/*lint --e{818}*/
1477  MSKsolstae solstat;
1478 
1479  assert( sdpisolver != NULL );
1480  CHECK_IF_SOLVED_BOOL( sdpisolver );
1481 
1482  MOSEK_CALL_BOOL( MSK_getsolsta(sdpisolver->msktask, MSK_SOL_ITR, &solstat) );/*lint !e641*/
1483 
1484  switch ( solstat )
1485  {
1486  case MSK_SOL_STA_UNKNOWN:
1487  case MSK_SOL_STA_PRIM_FEAS:
1488  case MSK_SOL_STA_DUAL_FEAS:
1489  case MSK_SOL_STA_NEAR_OPTIMAL:
1490  case MSK_SOL_STA_NEAR_PRIM_FEAS:
1491  case MSK_SOL_STA_NEAR_DUAL_FEAS:
1492  case MSK_SOL_STA_NEAR_PRIM_AND_DUAL_FEAS:
1493  case MSK_SOL_STA_NEAR_PRIM_INFEAS_CER:
1494  case MSK_SOL_STA_NEAR_DUAL_INFEAS_CER:
1495  return FALSE;
1496  case MSK_SOL_STA_OPTIMAL:
1497  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
1498  case MSK_SOL_STA_PRIM_INFEAS_CER:
1499  case MSK_SOL_STA_DUAL_INFEAS_CER:
1500  return TRUE;
1501  default:
1502  SCIPdebugMessage("Unknown return code in SCIPsdpiSolverFeasibilityKnown\n");
1503  return FALSE;
1504  }/*lint !e788*/
1505 }
1506 
1508 SCIP_RETCODE SCIPsdpiSolverGetSolFeasibility(
1509  SCIP_SDPISOLVER* sdpisolver,
1510  SCIP_Bool* primalfeasible,
1511  SCIP_Bool* dualfeasible
1512  )
1513 {/*lint --e{818}*/
1514  MSKsolstae solstat;
1515 
1516  assert( sdpisolver != NULL );
1517  assert( primalfeasible != NULL );
1518  assert( dualfeasible != NULL );
1519  CHECK_IF_SOLVED( sdpisolver );
1520 
1521  MOSEK_CALL( MSK_getsolsta(sdpisolver->msktask, MSK_SOL_ITR, &solstat) );/*lint !e641*/
1522 
1523  switch ( solstat )
1524  {
1525  case MSK_SOL_STA_OPTIMAL:
1526  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
1527  *primalfeasible = TRUE;
1528  *dualfeasible = TRUE;
1529  break;
1530  case MSK_SOL_STA_PRIM_INFEAS_CER:
1531  *primalfeasible = FALSE;
1532  *dualfeasible = TRUE;
1533  break;
1534  case MSK_SOL_STA_DUAL_INFEAS_CER:
1535  *primalfeasible = TRUE;
1536  *dualfeasible = FALSE;
1537  break;
1538  default:
1539  SCIPdebugMessage("MOSEK does not know about feasibility of solutions\n");
1540  return SCIP_LPERROR;
1541  }/*lint !e788*/
1542 
1543  return SCIP_OKAY;
1544 }
1545 
1549  SCIP_SDPISOLVER* sdpisolver
1550  )
1551 {/*lint --e{818}*/
1552  MSKsolstae solstat;
1553 
1554  assert( sdpisolver != NULL );
1555  CHECK_IF_SOLVED_BOOL( sdpisolver );
1556 
1557  MOSEK_CALL_BOOL( MSK_getsolsta(sdpisolver->msktask, MSK_SOL_ITR, &solstat) );/*lint !e641*/
1558 
1559  switch ( solstat )
1560  {
1561  case MSK_SOL_STA_DUAL_INFEAS_CER:
1562  return TRUE;
1563  case MSK_SOL_STA_OPTIMAL:
1564  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
1565  case MSK_SOL_STA_PRIM_INFEAS_CER:
1566  break;
1567  default:
1568  SCIPdebugMessage("MOSEK does not know about feasibility of solutions\n");
1569  break;
1570  }/*lint !e788*/
1571  return FALSE;
1572 }
1573 
1577  SCIP_SDPISOLVER* sdpisolver
1578  )
1579 {/*lint --e{818}*/
1580  MSKsolstae solstat;
1581 
1582  assert( sdpisolver != NULL );
1583  CHECK_IF_SOLVED_BOOL( sdpisolver );
1584 
1585  MOSEK_CALL_BOOL( MSK_getsolsta(sdpisolver->msktask, MSK_SOL_ITR, &solstat) );/*lint !e641*/
1586 
1587  switch ( solstat )
1588  {
1589  case MSK_SOL_STA_PRIM_INFEAS_CER:
1590  return TRUE;
1591  case MSK_SOL_STA_OPTIMAL:
1592  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
1593  case MSK_SOL_STA_DUAL_INFEAS_CER:
1594  break;
1595  default:
1596  SCIPdebugMessage("MOSEK does not know about feasibility of solutions\n");
1597  break;
1598  }/*lint !e788*/
1599  return FALSE;
1600 }
1601 
1605  SCIP_SDPISOLVER* sdpisolver
1606  )
1607 {/*lint --e{818}*/
1608  MSKsolstae solstat;
1609 
1610  assert( sdpisolver != NULL );
1611  CHECK_IF_SOLVED_BOOL( sdpisolver );
1612 
1613  MOSEK_CALL_BOOL( MSK_getsolsta(sdpisolver->msktask, MSK_SOL_ITR, &solstat) );/*lint !e641*/
1614 
1615  switch ( solstat )
1616  {
1617  case MSK_SOL_STA_OPTIMAL:
1618  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
1619  case MSK_SOL_STA_DUAL_INFEAS_CER:
1620  return TRUE;
1621  case MSK_SOL_STA_PRIM_INFEAS_CER:
1622  break;
1623  default:
1624  SCIPdebugMessage("MOSEK does not know about feasibility of solutions\n");
1625  break;
1626  }/*lint !e788*/
1627  return FALSE;
1628 }
1629 
1633  SCIP_SDPISOLVER* sdpisolver
1634  )
1635 {/*lint --e{818}*/
1636  MSKsolstae solstat;
1637 
1638  assert( sdpisolver != NULL );
1639  CHECK_IF_SOLVED_BOOL( sdpisolver );
1640 
1641  MOSEK_CALL_BOOL( MSK_getsolsta(sdpisolver->msktask, MSK_SOL_ITR, &solstat) );/*lint !e641*/
1642 
1643  switch ( solstat )
1644  {
1645  case MSK_SOL_STA_PRIM_INFEAS_CER:
1646  return TRUE;
1647  case MSK_SOL_STA_OPTIMAL:
1648  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
1649  case MSK_SOL_STA_DUAL_INFEAS_CER:
1650  break;
1651  default:
1652  SCIPdebugMessage("MOSEK does not know about feasibility of solutions\n");
1653  break;
1654  }/*lint !e788*/
1655  return FALSE;
1656 }
1657 
1661  SCIP_SDPISOLVER* sdpisolver
1662  )
1663 {/*lint --e{818}*/
1664  MSKsolstae solstat;
1665 
1666  assert( sdpisolver != NULL );
1667  CHECK_IF_SOLVED_BOOL( sdpisolver );
1668 
1669  MOSEK_CALL_BOOL( MSK_getsolsta(sdpisolver->msktask, MSK_SOL_ITR, &solstat) );/*lint !e641*/
1670 
1671  switch ( solstat )
1672  {
1673  case MSK_SOL_STA_DUAL_INFEAS_CER:
1674  return TRUE;
1675  case MSK_SOL_STA_OPTIMAL:
1676  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
1677  case MSK_SOL_STA_PRIM_INFEAS_CER:
1678  break;
1679  default:
1680  SCIPdebugMessage("MOSEK does not know about feasibility of solutions\n");
1681  break;
1682  }/*lint !e788*/
1683  return FALSE;
1684 }
1685 
1689  SCIP_SDPISOLVER* sdpisolver
1690  )
1691 {/*lint --e{818}*/
1692  MSKsolstae solstat;
1693 
1694  assert( sdpisolver != NULL );
1695  CHECK_IF_SOLVED_BOOL( sdpisolver );
1696 
1697  MOSEK_CALL_BOOL( MSK_getsolsta(sdpisolver->msktask, MSK_SOL_ITR, &solstat) );/*lint !e641*/
1698 
1699  switch ( solstat )
1700  {
1701  case MSK_SOL_STA_OPTIMAL:
1702  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
1703  case MSK_SOL_STA_PRIM_INFEAS_CER:
1704  return TRUE;
1705  case MSK_SOL_STA_DUAL_INFEAS_CER:
1706  break;
1707  default:
1708  SCIPdebugMessage("MOSEK does not know about feasibility of solutions\n");
1709  break;
1710  }/*lint !e788*/
1711  return FALSE;
1712 }
1713 
1715 SCIP_Bool SCIPsdpiSolverIsConverged(
1716  SCIP_SDPISOLVER* sdpisolver
1717  )
1718 {/*lint --e{818}*/
1719  assert( sdpisolver != NULL );
1720 
1721  if ( sdpisolver->timelimit )
1722  return FALSE;
1723 
1724  CHECK_IF_SOLVED_BOOL( sdpisolver );
1725 
1726  return sdpisolver->terminationcode == MSK_RES_OK;
1727 }
1728 
1730 SCIP_Bool SCIPsdpiSolverIsObjlimExc(
1731  SCIP_SDPISOLVER* sdpisolver
1732  )
1733 {/*lint --e{818}*/
1734  assert( sdpisolver != NULL );
1735  CHECK_IF_SOLVED_BOOL( sdpisolver );
1736 
1737  return sdpisolver->terminationcode == MSK_RES_TRM_OBJECTIVE_RANGE;
1738 }
1739 
1741 SCIP_Bool SCIPsdpiSolverIsIterlimExc(
1742  SCIP_SDPISOLVER* sdpisolver
1743  )
1744 {/*lint --e{818}*/
1745  assert( sdpisolver != NULL );
1746  CHECK_IF_SOLVED_BOOL( sdpisolver );
1747 
1748  return sdpisolver->terminationcode == MSK_RES_TRM_MAX_ITERATIONS;
1749 }
1750 
1752 SCIP_Bool SCIPsdpiSolverIsTimelimExc(
1753  SCIP_SDPISOLVER* sdpisolver
1754  )
1755 {/*lint --e{818}*/
1756  assert( sdpisolver != NULL );
1757 
1758  if ( sdpisolver->timelimit )
1759  return TRUE;
1760 
1761  if ( ! sdpisolver->solved )
1762  return FALSE;
1763 
1764  return sdpisolver->terminationcode == MSK_RES_TRM_MAX_TIME;
1765 }
1766 
1778  SCIP_SDPISOLVER* sdpisolver
1779  )
1780 {/*lint --e{818}*/
1781  assert( sdpisolver != NULL );
1782 
1783  if ( ! sdpisolver->solved )
1784  return -1;
1785 
1786  if ( sdpisolver->timelimit )
1787  return 5;
1788 
1789  switch ( sdpisolver->terminationcode )
1790  {
1791  case MSK_RES_OK:
1792  return 0;
1793  case MSK_RES_TRM_MAX_NUM_SETBACKS:
1794  case MSK_RES_TRM_NUMERICAL_PROBLEM:
1795  case MSK_RES_TRM_STALL:
1796  return 2;
1797  case MSK_RES_TRM_OBJECTIVE_RANGE:
1798  return 3;
1799  case MSK_RES_TRM_MAX_ITERATIONS:
1800  return 4;
1801  case MSK_RES_TRM_MAX_TIME:
1802  return 5;
1803  default:
1804  return 7;
1805  }/*lint !e788*/
1806 }
1807 
1809 SCIP_Bool SCIPsdpiSolverIsOptimal(
1810  SCIP_SDPISOLVER* sdpisolver
1811  )
1812 {/*lint --e{818}*/
1813  MSKsolstae solstat;
1814 
1815  assert( sdpisolver != NULL );
1816 
1817  if ( sdpisolver->timelimit )
1818  return FALSE;
1819 
1820  CHECK_IF_SOLVED_BOOL( sdpisolver );
1821 
1822  if ( sdpisolver->terminationcode != MSK_RES_OK )
1823  return FALSE;
1824 
1825  MOSEK_CALL_BOOL( MSK_getsolsta(sdpisolver->msktask, MSK_SOL_ITR, &solstat) );/*lint !e641*/
1826 
1827  if ( solstat != MSK_SOL_STA_OPTIMAL )
1828  return FALSE;
1829 
1830  return TRUE;
1831 }
1832 
1835 SCIP_Bool SCIPsdpiSolverIsAcceptable(
1836  SCIP_SDPISOLVER* sdpisolver
1837  )
1838 {/*lint --e{818}*/
1839  assert( sdpisolver != NULL );
1840 
1841  if ( sdpisolver->timelimit )
1842  return FALSE;
1843 
1844  if ( ! sdpisolver->solved )
1845  return FALSE;
1846 
1847  return SCIPsdpiSolverIsConverged(sdpisolver) && SCIPsdpiSolverFeasibilityKnown(sdpisolver);
1848 }
1849 
1851 SCIP_RETCODE SCIPsdpiSolverIgnoreInstability(
1852  SCIP_SDPISOLVER* sdpisolver,
1853  SCIP_Bool* success
1854  )
1855 {/*lint --e{715,818}*/
1856  SCIPdebugMessage("Not implemented yet\n");
1857  return SCIP_LPERROR;
1858 }
1859 
1861 SCIP_RETCODE SCIPsdpiSolverGetObjval(
1862  SCIP_SDPISOLVER* sdpisolver,
1863  SCIP_Real* objval
1864  )
1865 {/*lint --e{818}*/
1866  SCIP_Real* moseksol;
1867 
1868  assert( sdpisolver != NULL );
1869  CHECK_IF_SOLVED( sdpisolver );
1870  assert( objval != NULL );
1871 
1872  if ( sdpisolver->penalty && ( ! sdpisolver->feasorig ) )
1873  {
1874  /* in this case we cannot really trust the solution given by MOSEK, since changes in the value of r much less than epsilon can
1875  * cause huge changes in the objective, so using the objective value given by MOSEK is numerically more stable */
1876  MOSEK_CALL( MSK_getdualobj(sdpisolver->msktask, MSK_SOL_ITR, objval) );
1877  }
1878  else
1879  {
1880  int v;
1881 
1882  /* since the objective value given by MOSEK sometimes differs slightly from the correct value for the given solution,
1883  * we get the solution from MOSEK and compute the correct objective value */
1884  BMSallocBufferMemoryArray(sdpisolver->bufmem, &moseksol, sdpisolver->penalty ? sdpisolver->nactivevars + 1 : sdpisolver->nactivevars);
1885  MOSEK_CALL( MSK_gety(sdpisolver->msktask, MSK_SOL_ITR, moseksol) );/*lint !e641*/
1886 
1887  *objval = 0.0;
1888  for (v = 0; v < sdpisolver->nactivevars; v++)
1889  {
1890  if ( moseksol[v] > sdpisolver->epsilon )
1891  *objval += moseksol[v] * sdpisolver->objcoefs[v];
1892  }
1893  }
1894 
1895  /* as we didn't add the fixed (lb = ub) variables to MOSEK, we have to add their contributions to the objective as well */
1896  *objval += sdpisolver->fixedvarsobjcontr;
1897 
1898  if ( ( ! sdpisolver->penalty ) || sdpisolver->feasorig)
1899  {
1900  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &moseksol);
1901  }
1902 
1903  return SCIP_OKAY;
1904 }
1905 
1910 SCIP_RETCODE SCIPsdpiSolverGetSol(
1911  SCIP_SDPISOLVER* sdpisolver,
1912  SCIP_Real* objval,
1913  SCIP_Real* dualsol,
1914  int* dualsollength
1916  )
1917 {/*lint --e{818}*/
1918  int v;
1919  SCIP_Real* moseksol;
1920 
1921  assert( sdpisolver != NULL );
1922  CHECK_IF_SOLVED( sdpisolver );
1923  assert( dualsollength != NULL );
1924 
1925  if ( *dualsollength > 0 )
1926  {
1927  assert( dualsol != NULL );
1928  if ( *dualsollength < sdpisolver->nvars )
1929  {
1930  SCIPdebugMessage("The given array in SCIPsdpiSolverGetSol only had length %d, but %d was needed", *dualsollength, sdpisolver->nvars);
1931  *dualsollength = sdpisolver->nvars;
1932 
1933  return SCIP_OKAY;
1934  }
1935 
1936  BMSallocBufferMemoryArray(sdpisolver->bufmem, &moseksol, sdpisolver->penalty ? sdpisolver->nactivevars + 1 : sdpisolver->nactivevars);
1937 
1938  MOSEK_CALL( MSK_gety(sdpisolver->msktask, MSK_SOL_ITR, moseksol) );/*lint !e641*/
1939 
1940  /* 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) */
1941  for (v = 0; v < sdpisolver->nvars; v++)
1942  {
1943  if ( sdpisolver->inputtomosekmapper[v] >= 0 )
1944  dualsol[v] = moseksol[sdpisolver->inputtomosekmapper[v]];
1945  else
1946  {
1947  /* this is the value that was saved when inserting, as this variable has lb=ub */
1948  assert( -sdpisolver->inputtomosekmapper[v] <= sdpisolver->nvars - sdpisolver->nactivevars );
1949  dualsol[v] = sdpisolver->fixedvarsval[(-1 * sdpisolver->inputtomosekmapper[v]) - 1]; /*lint !e679*/ /* -1 because we wanted strictly negative vals */
1950  }
1951  }
1952 
1953  /* if both solution and objective should be printed, we can use the solution to compute the objective */
1954  if ( objval != NULL )
1955  {
1956  if ( sdpisolver->penalty && ( ! sdpisolver->feasorig ))
1957  {
1958  /* in this case we cannot really trust the solution given by MOSEK, since changes in the value of r much less than epsilon can
1959  * cause huge changes in the objective, so using the objective value given by MOSEK is numerically more stable */
1960  MOSEK_CALL( MSK_getdualobj(sdpisolver->msktask, MSK_SOL_ITR, objval) );
1961  }
1962  else
1963  {
1964  /* since the objective value given by MOSEK sometimes differs slightly from the correct value for the given solution,
1965  * we get the solution from MOSEK and compute the correct objective value */
1966  *objval = 0.0;
1967  for (v = 0; v < sdpisolver->nactivevars; v++)
1968  {
1969  if ( REALABS(moseksol[v]) > sdpisolver->epsilon )
1970  *objval += moseksol[v] * sdpisolver->objcoefs[v];
1971  }
1972  }
1973 
1974  /* as we didn't add the fixed (lb = ub) variables to MOSEK, we have to add their contributions to the objective as well */
1975  *objval += sdpisolver->fixedvarsobjcontr;
1976  }
1977 
1978  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &moseksol);
1979  }
1980  else if ( objval != NULL )
1981  {
1982  SCIP_CALL( SCIPsdpiSolverGetObjval(sdpisolver, objval) );
1983  }
1984 
1985  return SCIP_OKAY;
1986 }
1987 
1996  SCIP_SDPISOLVER* sdpisolver,
1997  SCIP_Real* lbvars,
1998  SCIP_Real* ubvars,
1999  int* arraylength
2001  )
2002 {/*lint --e{818}*/
2003  SCIP_Real* primalvars;
2004  int nprimalvars;
2005  int i;
2006 
2007  assert( sdpisolver != NULL );
2008  CHECK_IF_SOLVED( sdpisolver );
2009  assert( arraylength != NULL );
2010  assert( lbvars != NULL );
2011  assert( ubvars != NULL );
2012 
2013  /* check if the arrays are long enough */
2014  if ( *arraylength < sdpisolver->nvars )
2015  {
2016  *arraylength = sdpisolver->nvars;
2017  SCIPdebugMessage("Insufficient length of array in SCIPsdpiSolverGetPrimalBoundVars (gave %d, needed %d)\n", *arraylength, sdpisolver->nvars);
2018  return SCIP_OKAY;
2019  }
2020 
2021  /* initialize the return-arrays with zero */
2022  for (i = 0; i < sdpisolver->nvars; i++)
2023  {
2024  lbvars[i] = 0.0;
2025  ubvars[i] = 0.0;
2026  }
2027 
2028  /* get number of primal variables in MOSEK */
2029  MOSEK_CALL( MSK_getnumvar(sdpisolver->msktask, &nprimalvars) );/*lint !e641*/
2030 
2031  BMSallocBufferMemoryArray(sdpisolver->bufmem, &primalvars, nprimalvars);
2032 
2033  MOSEK_CALL( MSK_getxx(sdpisolver->msktask, MSK_SOL_ITR, primalvars) );/*lint !e641*/
2034 
2035  /* iterate over all variable bounds and insert the corresponding primal variables in the right positions of the return-arrays */
2036  assert( sdpisolver->nvarbounds <= 2 * sdpisolver->nvars );
2037 
2038  for (i = 0; i < sdpisolver->nvarbounds; i++)
2039  {
2040  if ( sdpisolver->varboundpos[i] < 0 )
2041  {
2042  /* this is a lower bound */
2043  /* the last nvarbounds entries correspond to the varbounds */
2044  lbvars[sdpisolver->mosektoinputmapper[-1 * sdpisolver->varboundpos[i] -1]] = primalvars[nprimalvars - sdpisolver->nvarbounds + i]; /*lint !e679, !e834 */
2045  }
2046  else
2047  {
2048  /* this is an upper bound */
2049 
2050  assert( sdpisolver->varboundpos[i] > 0 );
2051 
2052  /* the last nvarbounds entries correspond to the varbounds */
2053  ubvars[sdpisolver->mosektoinputmapper[sdpisolver->varboundpos[i] - 1]] = primalvars[nprimalvars - sdpisolver->nvarbounds + i]; /*lint !e679, !e834 */
2054  }
2055  }
2056 
2057  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &primalvars);
2058 
2059  return SCIP_OKAY;
2060 }
2061 
2063 SCIP_RETCODE SCIPsdpiSolverGetIterations(
2064  SCIP_SDPISOLVER* sdpisolver,
2065  int* iterations
2066  )
2067 {/*lint --e{818}*/
2068 
2069  if ( sdpisolver->timelimitinitial )
2070  *iterations = 0;
2071  else
2072  {
2073  *iterations = sdpisolver->niterations;
2074  }
2075 
2076  return SCIP_OKAY;
2077 }
2078 
2080 SCIP_RETCODE SCIPsdpiSolverGetSdpCalls(
2081  SCIP_SDPISOLVER* sdpisolver,
2082  int* calls
2083  )
2084 {/*lint --e{715,818,1784}*/
2085  assert( calls != NULL );
2086 
2087  *calls = sdpisolver->timelimitinitial ? 0 : sdpisolver->nsdpcalls;
2088 
2089  return SCIP_OKAY;
2090 }
2091 
2093 SCIP_RETCODE SCIPsdpiSolverSettingsUsed(
2094  SCIP_SDPISOLVER* sdpisolver,
2095  SCIP_SDPSOLVERSETTING* usedsetting
2096  )
2097 {/*lint --e{818}*/
2098  assert( sdpisolver != NULL );
2099  assert( usedsetting != NULL );
2100 
2101  if ( ! SCIPsdpiSolverIsAcceptable(sdpisolver) )
2102  *usedsetting = SCIP_SDPSOLVERSETTING_UNSOLVED;
2103  else if ( sdpisolver->penalty )
2104  *usedsetting = SCIP_SDPSOLVERSETTING_PENALTY;
2105  else
2106  *usedsetting = SCIP_SDPSOLVERSETTING_FAST;
2107 
2108  return SCIP_OKAY;
2109 }
2110 
2116 /*
2117  * Numerical Methods
2118  */
2119 
2124 SCIP_Real SCIPsdpiSolverInfinity(
2125  SCIP_SDPISOLVER* sdpisolver
2126  )
2127 {/*lint --e{715,818}*/
2128  return 1.0e16;
2129 }
2130 
2132 SCIP_Bool SCIPsdpiSolverIsInfinity(
2133  SCIP_SDPISOLVER* sdpisolver,
2134  SCIP_Real val
2135  )
2136 {/*lint --e{818}*/
2137  return ((val <= -SCIPsdpiSolverInfinity(sdpisolver)) || (val >= SCIPsdpiSolverInfinity(sdpisolver)));
2138 }
2139 
2141 SCIP_RETCODE SCIPsdpiSolverGetRealpar(
2142  SCIP_SDPISOLVER* sdpisolver,
2143  SCIP_SDPPARAM type,
2144  SCIP_Real* dval
2145  )
2146 {/*lint --e{818}*/
2147  assert( sdpisolver != NULL );
2148  assert( dval != NULL );
2149 
2150  switch( type )
2151  {
2152  case SCIP_SDPPAR_EPSILON:
2153  *dval = sdpisolver->epsilon;
2154  break;
2155  case SCIP_SDPPAR_GAPTOL:
2156  *dval = sdpisolver->gaptol;
2157  break;
2158  case SCIP_SDPPAR_FEASTOL:
2159  *dval = sdpisolver->feastol;
2160  break;
2162  *dval = sdpisolver->sdpsolverfeastol;
2163  break;
2164  case SCIP_SDPPAR_OBJLIMIT:
2165  *dval = sdpisolver->objlimit;
2166  break;
2167  default:
2168  return SCIP_PARAMETERUNKNOWN;
2169  }/*lint !e788*/
2170 
2171  return SCIP_OKAY;
2172 }
2173 
2175 SCIP_RETCODE SCIPsdpiSolverSetRealpar(
2176  SCIP_SDPISOLVER* sdpisolver,
2177  SCIP_SDPPARAM type,
2178  SCIP_Real dval
2179  )
2180 {
2181  assert( sdpisolver != NULL );
2182 
2183  switch( type )
2184  {
2185  case SCIP_SDPPAR_EPSILON:
2186  sdpisolver->epsilon = dval;
2187  SCIPdebugMessage("Setting sdpisolver epsilon to %f.\n", dval);
2188  break;
2189  case SCIP_SDPPAR_GAPTOL:
2190  sdpisolver->gaptol = dval;
2191  SCIPdebugMessage("Setting sdpisolver gaptol to %f.\n", dval);
2192  break;
2193  case SCIP_SDPPAR_FEASTOL:
2194  sdpisolver->feastol = dval;
2195  SCIPdebugMessage("Setting sdpisolver feastol to %f.\n", dval);
2196  break;
2198  sdpisolver->sdpsolverfeastol = dval;
2199  SCIPdebugMessage("Setting sdpisolver sdpsolverfeastol to %f.\n", dval);
2200  break;
2201  case SCIP_SDPPAR_OBJLIMIT:
2202  SCIPdebugMessage("Setting sdpisolver objlimit to %f.\n", dval);
2203  sdpisolver->objlimit = dval;
2204  break;
2205  default:
2206  return SCIP_PARAMETERUNKNOWN;
2207  }/*lint !e788*/
2208 
2209  return SCIP_OKAY;
2210 }
2211 
2213 SCIP_RETCODE SCIPsdpiSolverGetIntpar(
2214  SCIP_SDPISOLVER* sdpisolver,
2215  SCIP_SDPPARAM type,
2216  int* ival
2217  )
2218 {/*lint --e{818}*/
2219  assert( sdpisolver != NULL );
2220 
2221  switch( type )
2222  {
2223  case SCIP_SDPPAR_SDPINFO:
2224  *ival = (int) sdpisolver->sdpinfo;
2225  SCIPdebugMessage("Getting sdpisolver information output (%d).\n", *ival);
2226  break;
2227  case SCIP_SDPPAR_NTHREADS:
2228  *ival = sdpisolver->nthreads;
2229  SCIPdebugMessage("Getting sdpisolver number of threads: %d.\n", *ival);
2230  break;
2231  default:
2232  return SCIP_PARAMETERUNKNOWN;
2233  }/*lint !e788*/
2234 
2235  return SCIP_OKAY;
2236 }
2237 
2239 SCIP_RETCODE SCIPsdpiSolverSetIntpar(
2240  SCIP_SDPISOLVER* sdpisolver,
2241  SCIP_SDPPARAM type,
2242  int ival
2243  )
2244 {
2245  assert( sdpisolver != NULL );
2246 
2247  switch( type )
2248  {
2249  case SCIP_SDPPAR_NTHREADS:
2250  sdpisolver->nthreads = ival;
2251  SCIPdebugMessage("Setting sdpisolver number of threads to %d.\n", ival);
2252  break;
2253  case SCIP_SDPPAR_SDPINFO:
2254  assert( 0 <= ival && ival <= 1 );
2255  sdpisolver->sdpinfo = (SCIP_Bool) ival;
2256  SCIPdebugMessage("Setting sdpisolver information output (%d).\n", ival);
2257  break;
2258  default:
2259  return SCIP_PARAMETERUNKNOWN;
2260  }/*lint !e788*/
2261 
2262  return SCIP_OKAY;
2263 }
2264 
2266 SCIP_RETCODE SCIPsdpiSolverComputeLambdastar(
2267  SCIP_SDPISOLVER* sdpisolver,
2268  SCIP_Real maxguess
2269  )
2270 {/*lint --e{715,818}*/
2271  SCIPdebugMessage("Lambdastar parameter not used by MOSEK"); /* this parameter is only used by SDPA */
2272 
2273  return SCIP_OKAY;
2274 }
2275 
2278  SCIP_SDPISOLVER* sdpisolver,
2279  SCIP_Real maxcoeff,
2280  SCIP_Real* penaltyparam
2281  )
2282 {/*lint --e{818,1784}*/
2283  SCIP_Real compval;
2284 
2285  assert( sdpisolver != NULL );
2286  assert( penaltyparam != NULL );
2287 
2288  compval = PENALTYPARAM_FACTOR * maxcoeff;
2289 
2290  if ( compval < MIN_PENALTYPARAM )
2291  {
2292  SCIPdebugMessage("Setting penaltyparameter to %f.\n", MIN_PENALTYPARAM);
2293  *penaltyparam = MIN_PENALTYPARAM;
2294  }
2295  else if ( compval > MAX_PENALTYPARAM )
2296  {
2297  SCIPdebugMessage("Setting penaltyparameter to %f.\n", MAX_PENALTYPARAM);
2298  *penaltyparam = MAX_PENALTYPARAM;
2299  }
2300  else
2301  {
2302  SCIPdebugMessage("Setting penaltyparameter to %f.\n", compval);
2303  *penaltyparam = compval;
2304  }
2305  return SCIP_OKAY;
2306 }
2307 
2310  SCIP_SDPISOLVER* sdpisolver,
2311  SCIP_Real penaltyparam,
2312  SCIP_Real* maxpenaltyparam
2313  )
2314 {/*lint --e{818,1784}*/
2315  SCIP_Real compval;
2316 
2317  assert( sdpisolver != NULL );
2318  assert( maxpenaltyparam != NULL );
2319 
2320  compval = penaltyparam * MAXPENALTYPARAM_FACTOR;
2321 
2322  if ( compval < MAX_MAXPENALTYPARAM )
2323  {
2324  *maxpenaltyparam = compval;
2325  SCIPdebugMessage("Setting maximum penaltyparameter to %f.\n", compval);
2326  }
2327  else
2328  {
2329  *maxpenaltyparam = MAX_MAXPENALTYPARAM;
2330  SCIPdebugMessage("Setting penaltyparameter to %f.\n", MAX_MAXPENALTYPARAM);
2331  }
2332 
2333  return SCIP_OKAY;
2334 }
2335 
2341 /*
2342  * File Interface Methods
2343  */
2344 
2349 SCIP_RETCODE SCIPsdpiSolverReadSDP(
2350  SCIP_SDPISOLVER* sdpisolver,
2351  const char* fname
2352  )
2353 {/*lint --e{715,818}*/
2354  SCIPdebugMessage("Not implemented yet\n");
2355  return SCIP_LPERROR;
2356 }
2357 
2359 SCIP_RETCODE SCIPsdpiSolverWriteSDP(
2360  SCIP_SDPISOLVER* sdpisolver,
2361  const char* fname
2362  )
2363 {/*lint --e{818}*/
2364  assert( sdpisolver != NULL );
2365  assert( fname != NULL );
2366 
2367  MOSEK_CALL( MSK_writedata(sdpisolver->msktask, fname) );/*lint !e641*/
2368 
2369  return SCIP_OKAY;
2370 }
2371 
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:78
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)
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 *start, SCIP_SDPSOLVERSETTING startsettings, SCIP_Real timelimit)
#define TIMEOFDAY_CALL(x)
SCIP_RETCODE SCIPsdpiSolverGetIterations(SCIP_SDPISOLVER *sdpisolver, int *iterations)
#define PENALTYBOUNDTOL
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_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_Real SCIPsdpiSolverGetDefaultSdpiSolverFeastol(void)
SCIP_Bool SCIPsdpiSolverIsObjlimExc(SCIP_SDPISOLVER *sdpisolver)
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_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 *start, SCIP_SDPSOLVERSETTING startsettings, SCIP_Real timelimit, SCIP_Bool *feasorig, SCIP_Bool *penaltybound)
SCIP_Bool SCIPsdpiSolverIsIterlimExc(SCIP_SDPISOLVER *sdpisolver)
#define MOSEK_CALLM(x)
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)
enum SCIP_SDPParam SCIP_SDPPARAM
Definition: type_sdpi.h:67
SCIP_Bool SCIPsdpiSolverIsDualUnbounded(SCIP_SDPISOLVER *sdpisolver)
SCIP_Bool SCIPsdpiSolverIsTimelimExc(SCIP_SDPISOLVER *sdpisolver)
char name[SCIP_MAXSTRLEN]
SCIP_Bool SCIPsdpiSolverFeasibilityKnown(SCIP_SDPISOLVER *sdpisolver)
#define MAX_PENALTYPARAM