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