SCIP-SDP  4.0.0
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-2021 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-2021 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 /* #define SCIP_PRINT_SOLU /\* prints each solution (primal and dual) reported from MOSEK to the screen *\/ */
37 
66 #include <assert.h>
67 
68 #include "sdpi/sdpisolver.h"
69 #include "sdpi/sdpiclock.h"
70 
71 #include "blockmemshell/memory.h" /* for memory allocation */
72 #include "scip/def.h" /* for SCIP_Real, _Bool, ... */
73 #include "scip/pub_misc.h" /* for SCIPsnprintf() */
74 #include "mosek.h" /* for MOSEK routines */
75 #include "sdpi/sdpsolchecker.h" /* to check solution with regards to feasibility tolerance */
76 #include "scip/pub_message.h" /* for debug and error message */
77 #include "tinycthread/tinycthread.h" /* for thread local environments */
78 
79 /* @todo Use MSK_putexitfunc to catch errors.
80  * @todo Think about what to do with near optimality etc. (If MOSEK cannot compute a solution that has the prescribed accuracy, then it will
81  * multiply the termination tolerances with MSK_DPAR_INTPNT_CO_TOL_NEAR_REL. If the solution then satisfies the termination criteria, then
82  * the solution is denoted near optimal, near feasible and so forth.)
83  */
84 
85 #define MIN_PENALTYPARAM 1e5
86 #define MAX_PENALTYPARAM 1e10
87 #define PENALTYPARAM_FACTOR 1e6
88 #define MAX_MAXPENALTYPARAM 1e15
89 #define MAXPENALTYPARAM_FACTOR 1e6
90 #define PENALTYBOUNDTOL 1E-3
92 #define INFEASFEASTOLCHANGE 0.1
93 #define INFEASMINFEASTOL 1E-9
95 #define CONVERT_ABSOLUTE_TOLERANCES TRUE
96 #define CHECKVIOLATIONS 0
97 #if MSK_VERSION_MAJOR >= 9
98 #define NEAR_REL_TOLERANCE 1.0
99 #endif
100 
101 /* Use thread local environment in order to not create a new environment for each new SDP. */
102 #if defined(_Thread_local)
103 _Thread_local MSKenv_t reusemskenv = NULL;
104 _Thread_local int numsdp = 0;
105 #define SCIP_REUSEENV
106 #endif
107 
108 
110 struct SCIP_SDPiSolver
111 {
112  SCIP_MESSAGEHDLR* messagehdlr;
113  BMS_BLKMEM* blkmem;
114  BMS_BUFMEM* bufmem;
115  MSKenv_t mskenv;
116  MSKtask_t msktask;
117  SCIP_Real opttime;
118  int nvars;
119  int nactivevars;
120  int maxnvars;
121  int* inputtomosekmapper;
124  int* mosektoinputmapper;
125  SCIP_Real* fixedvarsval;
126  SCIP_Real fixedvarsobjcontr;
127  SCIP_Real* objcoefs;
128  int nvarbounds;
129  int* varboundpos;
133  SCIP_Bool solved;
134  int sdpcounter;
135  SCIP_Real epsilon;
136  SCIP_Real gaptol;
137  SCIP_Real feastol;
138  SCIP_Real sdpsolverfeastol;
139  SCIP_Real objlimit;
140  SCIP_Bool sdpinfo;
141  SCIP_Bool usepresolving;
142  SCIP_Bool usescaling;
143  SCIP_Bool penalty;
144  SCIP_Bool feasorig;
146  SCIP_Bool rbound;
147  MSKrescodee terminationcode;
148  MSKsolstae solstat;
149  SCIP_Bool timelimit;
150  int nthreads;
151  int niterations;
152  int nsdpcalls;
153  SCIP_Bool scaleobj;
154  SCIP_Real objscalefactor;
155 };
156 
157 
158 /*
159  * Local Methods
160  */
161 
163 #define MOSEK_CALL(x) do \
164  { \
165  MSKrescodee _mosekerrorcode_; \
166  if ( (_mosekerrorcode_ = (x)) != MSK_RES_OK ) \
167  { \
168  SCIPerrorMessage("MOSEK-Error <%d> in function call.\n", (int)_mosekerrorcode_); \
169  return SCIP_LPERROR; \
170  } \
171  } \
172  while( FALSE )
173 
175 #define MOSEK_CALL_BOOL(x) do \
176  { \
177  MSKrescodee _mosekerrorcode_; \
178  if ( (_mosekerrorcode_ = (x)) != MSK_RES_OK ) \
179  { \
180  SCIPerrorMessage("MOSEK-Error <%d> in function call.\n", (int)_mosekerrorcode_); \
181  return FALSE; \
182  } \
183  } \
184  while( FALSE )
185 
187 #define MOSEK_CALLM(x) do \
188  { \
189  MSKrescodee _mosekerrorcode_; \
190  if ( (_mosekerrorcode_ = (x)) != MSK_RES_OK ) \
191  { \
192  SCIPerrorMessage("MOSEK-Error <%d> in function call.\n", (int)_mosekerrorcode_); \
193  return SCIP_NOMEMORY; \
194  } \
195  } \
196  while( FALSE )
197 
199 #define BMS_CALL(x) do \
200  { \
201  if( NULL == (x) ) \
202  { \
203  SCIPerrorMessage("No memory in function call.\n"); \
204  return SCIP_NOMEMORY; \
205  } \
206  } \
207  while( FALSE )
208 
210 #define CHECK_IF_SOLVED(sdpisolver) do \
211  { \
212  if (!(sdpisolver->solved)) \
213  { \
214  SCIPerrorMessage("Tried to access solution information for SDP %d ahead of solving!\n", sdpisolver->sdpcounter); \
215  return SCIP_LPERROR; \
216  } \
217  } \
218  while( FALSE )
219 
221 #define CHECK_IF_SOLVED_BOOL(sdpisolver) do \
222  { \
223  if (!(sdpisolver->solved)) \
224  { \
225  SCIPerrorMessage("Tried to access solution information for SDP %d ahead of solving!\n", sdpisolver->sdpcounter); \
226  SCIPABORT(); \
227  return FALSE; \
228  } \
229  } \
230  while( FALSE )
231 
233 static
234 void MSKAPI printstr(
235 #if MSK_VERSION_MAJOR >= 9
236  MSKuserhandle_t handler,
237  const char* str
238 #else
239  void* handler,
240  MSKCONST char str[]
241 #endif
242  )
243 { /*lint --e{715}*/
244 #if 0
245  char errstr[32];
246  snprintf(errstr, 32, "MOSEK Error %d", MSK_RES_ERR_DUP_NAME);
247  if ( strncmp(errstr, str, strlen(errstr)) == 0 )
248  return;
249 #endif
250 
251  SCIPmessagePrintInfo((SCIP_MESSAGEHDLR *) handler, "MOSEK: %s", str);
252 }
253 
254 
255 #ifndef NDEBUG
256 
257 static
258 SCIP_Bool isFixed(
259  SCIP_SDPISOLVER* sdpisolver,
260  SCIP_Real lb,
261  SCIP_Real ub
262  )
263 {
264  assert( sdpisolver != NULL );
265  assert( lb < ub + sdpisolver->feastol );
266 
267  return (ub-lb <= sdpisolver->epsilon);
268 }
269 #else
270 #define isFixed(sdpisolver,lb,ub) (ub-lb <= sdpisolver->epsilon)
271 #endif
272 
274 static
275 int calcGrowSize(
276  int initsize,
277  int num
278  )
279 {
280  int oldsize;
281  int size;
282 
283  assert( initsize >= 0 );
284  assert( num >= 0 );
285 
286  /* calculate the size with loop, such that the resulting numbers are always the same (-> block memory) */
287  initsize = MAX(initsize, SCIP_DEFAULT_MEM_ARRAYGROWINIT);
288  size = initsize;
289  oldsize = size - 1;
290 
291  /* second condition checks against overflow */
292  while ( size < num && size > oldsize )
293  {
294  oldsize = size;
295  size = (int)(SCIP_DEFAULT_MEM_ARRAYGROWFAC * size + initsize);
296  }
297 
298  /* if an overflow happened, set the correct value */
299  if ( size <= oldsize )
300  size = num;
301 
302  assert( size >= initsize );
303  assert( size >= num );
304 
305  return size;
306 }
307 
309 static
310 SCIP_RETCODE ensureMappingDataMemory(
311  SCIP_SDPISOLVER* sdpisolver,
312  int nvars
313  )
314 {
315  int newsize;
316 
317  assert( sdpisolver != NULL );
318 
319  if ( nvars > sdpisolver->maxnvars )
320  {
321  newsize = calcGrowSize(sdpisolver->maxnvars, nvars);
322 
323  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->varboundpos), 2 * sdpisolver->maxnvars, 2 * newsize) );
324  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->inputtomosekmapper), sdpisolver->maxnvars, newsize) );
325  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->mosektoinputmapper), sdpisolver->maxnvars, newsize) );
326  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->fixedvarsval), sdpisolver->maxnvars, newsize) );
327  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->objcoefs), sdpisolver->maxnvars, newsize) );
328  sdpisolver->maxnvars = newsize;
329  }
330 
331  return SCIP_OKAY;
332 }
333 
334 
335 /*
336  * Miscellaneous Methods
337  */
338 
342 char solvername[SCIP_MAXSTRLEN];
343 
345 const char* SCIPsdpiSolverGetSolverName(
346  void
347  )
348 {
349  MSKrescodee rescodee;
350  int majorver = 0;
351  int minorver = 0;
352 #if MSK_VERSION_MAJOR < 9
353  int build = 0;
354 #endif
355  int revision = 0;
356 #ifndef NDEBUG
357  int snprintfreturn; /* used to check the return code of snprintf */
358 #endif
359 
360 #if MSK_VERSION_MAJOR < 9
361  rescodee = MSK_getversion(&majorver, &minorver, &build, &revision);/*lint !e123*/
362 #else
363  rescodee = MSK_getversion(&majorver, &minorver, &revision);/*lint !e123*/
364 #endif
365 
366  if ( rescodee != MSK_RES_OK )
367  return "MOSEK";
368 
369 #ifndef NDEBUG
370 #if MSK_VERSION_MAJOR < 9
371  snprintfreturn = SCIPsnprintf(solvername, SCIP_MAXSTRLEN, "MOSEK %d.%d.%d.%d", majorver, minorver, build, revision);/*lint !e123*/
372 #else
373  snprintfreturn = SCIPsnprintf(solvername, SCIP_MAXSTRLEN, "MOSEK %d.%d.%d", majorver, minorver, revision);/*lint !e123*/
374 #endif
375  assert( snprintfreturn < SCIP_MAXSTRLEN ); /* check whether the name fits into the string */
376 #else
377 #if MSK_VERSION_MAJOR < 9
378  (void) SCIPsnprintf(solvername, SCIP_MAXSTRLEN, "MOSEK %d.%d.%d.%d", majorver, minorver, build, revision);
379 #else
380  (void) SCIPsnprintf(solvername, SCIP_MAXSTRLEN, "MOSEK %d.%d.%d", majorver, minorver, revision);
381 #endif
382 #endif
383 
384  return solvername;
385 }
386 
388 const char* SCIPsdpiSolverGetSolverDesc(
389  void
390  )
391 {
392  return "Homogeneous and self-dual interior-point solver for semidefinite programming developed by MOSEK ApS"
393  "(http://www.mosek.com)";
394 }
395 
403  SCIP_SDPISOLVER* sdpisolver
404  )
405 {
406  assert( sdpisolver != NULL );
407  return (void*) NULL;
408 }
409 
412  void
413  )
414 {
415  return 8;
416 }
417 
420  void
421  )
422 {
423  return FALSE;
424 }
425 
429 /*
430  * SDPI Creation and Destruction Methods
431  */
432 
437 SCIP_RETCODE SCIPsdpiSolverCreate(
438  SCIP_SDPISOLVER** sdpisolver,
439  SCIP_MESSAGEHDLR* messagehdlr,
440  BMS_BLKMEM* blkmem,
441  BMS_BUFMEM* bufmem
442  )
443 {
444  assert( sdpisolver != NULL );
445  assert( blkmem != NULL );
446  assert( bufmem != NULL );
447 
448  SCIPdebugMessage("Calling SCIPsdpiCreate \n");
449 
450  BMS_CALL( BMSallocBlockMemory(blkmem, sdpisolver) );
451 
452  (*sdpisolver)->messagehdlr = messagehdlr;
453  (*sdpisolver)->blkmem = blkmem;
454  (*sdpisolver)->bufmem = bufmem;
455 
456 #ifdef SCIP_REUSEENV
457  if ( reusemskenv == NULL )
458  {
459  assert(numsdp == 0);
460  MOSEK_CALL( MSK_makeenv(&reusemskenv, NULL) );
461  }
462  (*sdpisolver)->mskenv = reusemskenv;
463  ++numsdp;
464 #else
465  MOSEK_CALL( MSK_makeenv(&((*sdpisolver)->mskenv), NULL) );/*lint !e641*/ /* the NULL-argument is a debug file, but setting this will spam the whole folder */
466 #endif
467 
468  /* this will be properly initialized then calling solve */
469  (*sdpisolver)->msktask = NULL;
470  (*sdpisolver)->opttime = 0.0;
471 
472  (*sdpisolver)->nvars = 0;
473  (*sdpisolver)->nactivevars = 0;
474  (*sdpisolver)->inputtomosekmapper = NULL;
475  (*sdpisolver)->mosektoinputmapper = NULL;
476  (*sdpisolver)->fixedvarsval = NULL;
477  (*sdpisolver)->fixedvarsobjcontr = 0.0;
478  (*sdpisolver)->objcoefs = NULL;
479  (*sdpisolver)->maxnvars = 0;
480  (*sdpisolver)->nvarbounds = 0;
481  (*sdpisolver)->varboundpos = NULL;
482  (*sdpisolver)->solved = FALSE;
483  (*sdpisolver)->sdpcounter = 0;
484 
485  (*sdpisolver)->epsilon = 1e-9;
486  (*sdpisolver)->gaptol = 1e-4;
487  (*sdpisolver)->feastol = 1e-6;
488  (*sdpisolver)->sdpsolverfeastol = 1e-6;
489  (*sdpisolver)->objlimit = SCIPsdpiSolverInfinity(*sdpisolver);
490  (*sdpisolver)->sdpinfo = FALSE;
491  (*sdpisolver)->usepresolving = TRUE;
492  (*sdpisolver)->usescaling = TRUE;
493  (*sdpisolver)->nthreads = -1;
494  (*sdpisolver)->terminationcode = MSK_RES_OK;
495  (*sdpisolver)->solstat = MSK_SOL_STA_UNKNOWN;
496  (*sdpisolver)->timelimit = FALSE;
497  (*sdpisolver)->niterations = 0;
498  (*sdpisolver)->scaleobj = FALSE;
499  (*sdpisolver)->objscalefactor = 1.0;
500 
501  return SCIP_OKAY;
502 }
503 
505 SCIP_RETCODE SCIPsdpiSolverFree(
506  SCIP_SDPISOLVER** sdpisolver
507  )
508 {
509  assert( sdpisolver != NULL );
510  assert( *sdpisolver != NULL );
511 
512  SCIPdebugMessage("Freeing SDPISolver\n");
513 
514  if ( (*sdpisolver)->msktask != NULL )
515  {
516  MOSEK_CALL( MSK_deletetask(&((*sdpisolver)->msktask)) );/*lint !e641*/
517  }
518 
519  if ( (*sdpisolver)->mskenv != NULL )
520  {
521 #ifdef SCIP_REUSEENV
522  assert( numsdp > 0 );
523  --numsdp;
524  if ( numsdp == 0 )
525  {
526  MOSEK_CALL( MSK_deleteenv(&reusemskenv) );
527  reusemskenv = NULL;
528  }
529 #else
530  MOSEK_CALL( MSK_deleteenv(&((*sdpisolver)->mskenv)) );/*lint !e641*/
531 #endif
532  }
533 
534  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->varboundpos, 2 * (*sdpisolver)->maxnvars);
535  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->inputtomosekmapper, (*sdpisolver)->maxnvars);
536  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->mosektoinputmapper, (*sdpisolver)->maxnvars);
537  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->fixedvarsval, (*sdpisolver)->maxnvars);
538  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->objcoefs, (*sdpisolver)->maxnvars);
539 
540  BMSfreeBlockMemory((*sdpisolver)->blkmem, sdpisolver);
541 
542  return SCIP_OKAY;
543 }
544 
546 SCIP_RETCODE SCIPsdpiSolverIncreaseCounter(
547  SCIP_SDPISOLVER* sdpisolver
548  )
549 {
550  assert( sdpisolver != NULL );
551 
552  sdpisolver->sdpcounter++;
553 
554  return SCIP_OKAY;
555 }
556 
558 SCIP_RETCODE SCIPsdpiSolverResetCounter(
559  SCIP_SDPISOLVER* sdpisolver
560  )
561 {
562  assert( sdpisolver != NULL );
563 
564  SCIPdebugMessage("Resetting counter of SDP-Interface from %d to 0.\n", sdpisolver->sdpcounter);
565  sdpisolver->sdpcounter = 0;
566 
567  return SCIP_OKAY;
568 }
569 
573 /*
574  * Solving Methods
575  */
576 
595 SCIP_RETCODE SCIPsdpiSolverLoadAndSolve(
596  SCIP_SDPISOLVER* sdpisolver,
597  int nvars,
598  SCIP_Real* obj,
599  SCIP_Real* lb,
600  SCIP_Real* ub,
601  int nsdpblocks,
602  int* sdpblocksizes,
603  int* sdpnblockvars,
604  int sdpconstnnonz,
605  int* sdpconstnblocknonz,
607  int** sdpconstrow,
608  int** sdpconstcol,
609  SCIP_Real** sdpconstval,
610  int sdpnnonz,
611  int** sdpnblockvarnonz,
613  int** sdpvar,
615  int*** sdprow,
616  int*** sdpcol,
617  SCIP_Real*** sdpval,
618  int** indchanges,
620  int* nremovedinds,
621  int* blockindchanges,
622  int nremovedblocks,
623  int nlpcons,
624  SCIP_Real* lplhs,
625  SCIP_Real* lprhs,
626  int lpnnonz,
627  int* lprow,
628  int* lpcol,
629  SCIP_Real* lpval,
630  SCIP_Real* starty,
631  int* startZnblocknonz,
633  int** startZrow,
635  int** startZcol,
637  SCIP_Real** startZval,
639  int* startXnblocknonz,
641  int** startXrow,
643  int** startXcol,
645  SCIP_Real** startXval,
647  SCIP_SDPSOLVERSETTING startsettings,
649  SCIP_Real timelimit,
650  SDPI_CLOCK* usedsdpitime
651  )
652 {
653  return SCIPsdpiSolverLoadAndSolveWithPenalty(sdpisolver, 0.0, TRUE, FALSE, nvars, obj, lb, ub, nsdpblocks, sdpblocksizes, sdpnblockvars, sdpconstnnonz,
654  sdpconstnblocknonz, sdpconstrow, sdpconstcol, sdpconstval, sdpnnonz, sdpnblockvarnonz, sdpvar, sdprow, sdpcol, sdpval, indchanges,
655  nremovedinds, blockindchanges, nremovedblocks, nlpcons, lplhs, lprhs, lpnnonz, lprow, lpcol, lpval,
656  starty, startZnblocknonz, startZrow, startZcol, startZval, startXnblocknonz, startXrow, startXcol, startXval, startsettings,
657  timelimit, usedsdpitime, NULL, NULL);
658 }
659  /*lint --e{715}*/
683  SCIP_SDPISOLVER* sdpisolver,
684  SCIP_Real penaltyparam,
685  SCIP_Bool withobj,
686  SCIP_Bool rbound,
687  int nvars,
688  SCIP_Real* obj,
689  SCIP_Real* lb,
690  SCIP_Real* ub,
691  int nsdpblocks,
692  int* sdpblocksizes,
693  int* sdpnblockvars,
694  int sdpconstnnonz,
695  int* sdpconstnblocknonz,
697  int** sdpconstrow,
698  int** sdpconstcol,
699  SCIP_Real** sdpconstval,
700  int sdpnnonz,
701  int** sdpnblockvarnonz,
703  int** sdpvar,
705  int*** sdprow,
706  int*** sdpcol,
707  SCIP_Real*** sdpval,
708  int** indchanges,
710  int* nremovedinds,
711  int* blockindchanges,
712  int nremovedblocks,
713  int nlpcons,
714  SCIP_Real* lplhs,
715  SCIP_Real* lprhs,
716  int lpnnonz,
717  int* lprow,
718  int* lpcol,
719  SCIP_Real* lpval,
720  SCIP_Real* starty,
721  int* startZnblocknonz,
723  int** startZrow,
725  int** startZcol,
727  SCIP_Real** startZval,
729  int* startXnblocknonz,
731  int** startXrow,
733  int** startXcol,
735  SCIP_Real** startXval,
737  SCIP_SDPSOLVERSETTING startsettings,
739  SCIP_Real timelimit,
740  SDPI_CLOCK* usedsdpitime,
741  SCIP_Bool* feasorig,
743  SCIP_Bool* penaltybound
745 )
746 {/*lint --e{715}*/
747  int b;
748  int i;
749  int j;
750  int blockvar;
751  int v;
752  int k;
753  long long mosekindex;
754  int mosekind = 0;
755  int ind;
756  int nnonz;
757  SCIP_Real* mosekvarbounds;
758  int nfixedvars;
759  int nlpvars;
760  int* mosekblocksizes;
761  SCIP_Real one = 1.0; /* MOSEK always wants a pointer to factors for a sum of matrices, we always use a single matrix with factor one */
762  int* mosekrow;
763  int* mosekcol;
764  SCIP_Real* mosekval;
765  int row;
766  SCIP_Real val;
767  SCIP_Real solvertimelimit;
768 #ifdef SCIP_MORE_DEBUG
769  char name[SCIP_MAXSTRLEN];
770 #endif
771 #if CONVERT_ABSOLUTE_TOLERANCES
772  SCIP_Real maxrhscoef = 0.0; /* MOSEK uses a relative feasibility tolerance, the largest rhs-coefficient is needed for converting the absolute tolerance */
773 #endif
774  SCIP_Real maxabsobjcoef = 0.0;
775 
776  assert( sdpisolver != NULL );
777  assert( sdpisolver->mskenv != NULL );
778  assert( penaltyparam > -1 * sdpisolver->epsilon );
779  assert( penaltyparam < sdpisolver->epsilon || ( feasorig != NULL ) );
780  assert( nvars > 0 );
781  assert( obj != NULL );
782  assert( lb != NULL );
783  assert( ub != NULL );
784  assert( nsdpblocks >= 0 );
785  assert( nsdpblocks == 0 || sdpblocksizes != NULL );
786  assert( nsdpblocks == 0 || sdpnblockvars != NULL );
787  assert( sdpconstnnonz >= 0 );
788  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstnblocknonz != NULL );
789  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstrow != NULL );
790  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstcol != NULL );
791  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstval != NULL );
792  assert( sdpnnonz >= 0 );
793  assert( nsdpblocks == 0 || sdpnblockvarnonz != NULL );
794  assert( nsdpblocks == 0 || sdpvar != NULL );
795  assert( nsdpblocks == 0 || sdprow != NULL );
796  assert( nsdpblocks == 0 || sdpcol != NULL );
797  assert( nsdpblocks == 0 || sdpval != NULL );
798  assert( nsdpblocks == 0 || indchanges != NULL );
799  assert( nsdpblocks == 0 || nremovedinds != NULL );
800  assert( nsdpblocks == 0 || blockindchanges != NULL );
801  assert( 0 <= nremovedblocks && nremovedblocks <= nsdpblocks );
802  assert( nlpcons >= 0 );
803  assert( nlpcons == 0 || lplhs != NULL );
804  assert( nlpcons == 0 || lprhs != NULL );
805  assert( lpnnonz >= 0 );
806  assert( nlpcons == 0 || lprow != NULL );
807  assert( nlpcons == 0 || lpcol != NULL );
808  assert( nlpcons == 0 || lpval != NULL );
809 
810  /* compute the time limit to set for the solver */
811  solvertimelimit = timelimit;
812  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, solvertimelimit) )
813  solvertimelimit -= SDPIclockGetTime(usedsdpitime);
814 
815  sdpisolver->niterations = 0;
816  sdpisolver->nsdpcalls = 0;
817  sdpisolver->objscalefactor = 1.0;
818 
819  /* check the timelimit */
820  if ( solvertimelimit <= 0.0 )
821  {
822  sdpisolver->timelimit = TRUE;
823  sdpisolver->solved = FALSE;
824  return SCIP_OKAY;
825  }
826  sdpisolver->timelimit = FALSE;
827  sdpisolver->feasorig = FALSE;
828 
829  /* create an empty task (second and third argument are guesses for maximum number of constraints and variables), if there already is one, delete it */
830  if ( sdpisolver->msktask != NULL )
831  {
832  MOSEK_CALL( MSK_deletetask(&sdpisolver->msktask) );/*lint !e641*/
833  }
834  if ( penaltyparam < sdpisolver->epsilon )
835  {
836  MOSEK_CALLM( MSK_maketask(sdpisolver->mskenv, nvars, nsdpblocks - nremovedblocks + nlpcons + 2 * nvars, &sdpisolver->msktask) );/*lint !e641*/
837  }
838  else
839  {
840  MOSEK_CALLM( MSK_maketask(sdpisolver->mskenv, nvars + 1, nsdpblocks - nremovedblocks + nlpcons + 2 * nvars, &sdpisolver->msktask) );/*lint !e641*/
841  }
842 
843 #if MSK_VERSION_MAJOR >= 9
844  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_NEAR_REL, NEAR_REL_TOLERANCE) );
845 #endif
846 
847  /* redirect output to SCIP message handler */
848 #ifdef SCIP_MORE_DEBUG
849  sdpisolver->sdpinfo = TRUE;
850 #endif
851 
852  if ( sdpisolver->sdpinfo )
853  {
854  MOSEK_CALL( MSK_linkfunctotaskstream(sdpisolver->msktask, MSK_STREAM_LOG, (MSKuserhandle_t) sdpisolver->messagehdlr, printstr) );/*lint !e641*/
855  }
856 
857  /* set number of threads */
858  if ( sdpisolver->nthreads > 0 )
859  {
860  MOSEK_CALL( MSK_putintparam(sdpisolver->msktask, MSK_IPAR_NUM_THREADS, sdpisolver->nthreads) );/*lint !e641*/
861  }
862 
863  /* 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
864  * same SDP) */
865  if ( penaltyparam < sdpisolver->epsilon )
866  {
867  SCIPdebugMessage("Inserting data into MOSEK for SDP (%d) \n", ++sdpisolver->sdpcounter);
868  }
869  else
870  {
871  SCIPdebugMessage("Inserting Data again into MOSEK for penalty formulation of SDP (%d) \n", sdpisolver->sdpcounter);
872  }
873 
874  /* set the penalty and rbound flags accordingly */
875  sdpisolver->penalty = (penaltyparam < sdpisolver->epsilon) ? FALSE : TRUE;
876  sdpisolver->rbound = rbound;
877 
878  /* ensure memory for varboundpos, inputtomosekmapper, mosektoinputmapper and the fixed and active variable information */
879  SCIP_CALL( ensureMappingDataMemory(sdpisolver, nvars) );
880  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &mosekvarbounds, 2 * nvars) ); /*lint !e647*/
881 
882  sdpisolver->nvars = nvars;
883  sdpisolver->nactivevars = 0;
884  sdpisolver->nvarbounds = 0;
885  nfixedvars = 0;
886 
887  for (i = 0; i < sdpisolver->nactivevars; i++)
888  {
889  assert( 0 <= sdpisolver->mosektoinputmapper[i] && sdpisolver->mosektoinputmapper[i] < nvars );
890  }
891 
892  /* find fixed variables */
893  sdpisolver->fixedvarsobjcontr = 0.0;
894  for (i = 0; i < nvars; i++)
895  {
896  if ( isFixed(sdpisolver, lb[i], ub[i]) )
897  {
898  sdpisolver->fixedvarsobjcontr += obj[i] * lb[i]; /* this is the value this fixed variable contributes to the objective */
899  sdpisolver->fixedvarsval[nfixedvars] = lb[i]; /* if lb=ub, then this is the value the variable will have in every solution */
900  nfixedvars++;
901  sdpisolver->inputtomosekmapper[i] = -nfixedvars;
902  SCIPdebugMessage("Fixing variable %d locally to %g for SDP %d in MOSEK.\n", i, lb[i], sdpisolver->sdpcounter);
903  }
904  else
905  {
906 #ifdef SCIP_MORE_DEBUG
907  SCIPdebugMessage("Variable %d becomes variable %d for SDP %d in MOSEK.\n", i, sdpisolver->nactivevars, sdpisolver->sdpcounter);
908 #endif
909 
910  sdpisolver->mosektoinputmapper[sdpisolver->nactivevars] = i;
911  sdpisolver->inputtomosekmapper[i] = sdpisolver->nactivevars;
912  sdpisolver->objcoefs[sdpisolver->nactivevars] = obj[i];
913 
914  if ( withobj )
915  {
916  /* the objective moves to the rhs */
917  if ( REALABS(obj[i]) > maxabsobjcoef )
918  maxabsobjcoef = REALABS(obj[i]);
919  }
920 
921  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, lb[i]) )
922  {
923  mosekvarbounds[sdpisolver->nvarbounds] = lb[i];
924  sdpisolver->varboundpos[sdpisolver->nvarbounds++] = -(sdpisolver->nactivevars + 1); /* negative sign means lower bound */
925  }
926 
927  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, ub[i]) )
928  {
929  mosekvarbounds[sdpisolver->nvarbounds] = - ub[i]; /* we give the upper bounds a negative sign for the objective */
930  sdpisolver->varboundpos[sdpisolver->nvarbounds++] = +(sdpisolver->nactivevars + 1); /* positive sign means upper bound */
931  }
932 
933  sdpisolver->nactivevars++;
934  }
935  }
936  assert( sdpisolver->nactivevars + nfixedvars == sdpisolver->nvars );
937 
938  /* adjust maxabsrhscoef in penalty formulation */
939  if ( penaltyparam >= sdpisolver->epsilon )
940  {
941  if ( penaltyparam > maxabsobjcoef )
942  maxabsobjcoef = penaltyparam;
943  }
944 
945  /* if we want to solve without objective, we reset fixedvarsobjcontr */
946  if ( ! withobj )
947  sdpisolver->fixedvarsobjcontr = 0.0;
948 
949  /* determine total number of sides in LP-constraints */
950  nlpvars = 0;
951  if ( nlpcons > 0 )
952  {
953  for (i = 0; i < nlpcons; i++)
954  {
955  if ( lplhs[i] > - SCIPsdpiSolverInfinity(sdpisolver) )
956  {
957 #if CONVERT_ABSOLUTE_TOLERANCES
958  /* update largest rhs-entry */
959  if ( REALABS(lplhs[i]) > maxrhscoef )
960  maxrhscoef = REALABS(lplhs[i]);
961 #endif
962  ++nlpvars;
963  }
964 
965  if ( lprhs[i] < SCIPsdpiSolverInfinity(sdpisolver) )
966  {
967 #if CONVERT_ABSOLUTE_TOLERANCES
968  /* update largest rhs-entry */
969  if ( REALABS(lprhs[i]) > maxrhscoef )
970  maxrhscoef = REALABS(lprhs[i]);
971 #endif
972  ++nlpvars;
973  }
974  }
975  assert( nlpvars <= 2 * nlpcons ); /* factor 2 comes from left- and right-hand-sides */
976  }
977 
978  /* create matrix variables */
979  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &mosekblocksizes, nsdpblocks - nremovedblocks) ); /*lint !e679 !e776*/
980 
981  for (b = 0; b < nsdpblocks; b++)
982  {
983  if ( blockindchanges[b] > -1 )
984  {
985  assert( 0 <= blockindchanges[b] && blockindchanges[b] <= b && (b - blockindchanges[b]) <= (nsdpblocks - nremovedblocks) );
986  mosekblocksizes[b - blockindchanges[b]] = sdpblocksizes[b] - nremovedinds[b];/*lint !e679*/
987  }
988  }
989  MOSEK_CALLM( MSK_appendbarvars(sdpisolver->msktask, nsdpblocks - nremovedblocks, mosekblocksizes) );/*lint !e641*/
990 
991  /* create scalar variables (since we solve the primal problem, these are not the active variables but the dual variables for the
992  * lp constraints and variable bounds) */
993  MOSEK_CALLM( MSK_appendvars(sdpisolver->msktask, nlpvars + sdpisolver->nvarbounds) );/*lint !e641*/
994 
995  /* all of these are non-negative */
996  for (v = 0; v < nlpvars + sdpisolver->nvarbounds; v++)
997  {
998  MOSEK_CALL( MSK_putvarbound(sdpisolver->msktask, v, MSK_BK_LO, 0.0, (double) MSK_DPAR_DATA_TOL_BOUND_INF) );/*lint !e641*/
999  }
1000 
1001  /* append empty constraints (since we solve the primal problem, we get one constraint for each active variable) */
1002  MOSEK_CALLM( MSK_appendcons(sdpisolver->msktask, (penaltyparam < sdpisolver->epsilon) ? sdpisolver->nactivevars : sdpisolver->nactivevars + 1) );/*lint !e641*/
1003 
1004  /* set objective values for the matrix variables */
1005  i = 0;
1006 
1007  if ( sdpconstnnonz > 0 )
1008  {
1009  for (b = 0; b < nsdpblocks; b++)
1010  {
1011  if ( blockindchanges[b] > -1 )
1012  {
1013  /* if some indices in the block were removed, we need to change indices accordingly */
1014  if ( nremovedinds[b] > 0 )
1015  {
1016  int* moseksdpconstrow;
1017  int* moseksdpconstcol;
1018 
1019  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &moseksdpconstrow, sdpconstnblocknonz[b]) );
1020  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &moseksdpconstcol, sdpconstnblocknonz[b]) );
1021 
1022  for (k = 0; k < sdpconstnblocknonz[b]; k++)
1023  {
1024  /* rows and cols with active nonzeros should not be removed */
1025  assert( -1 < indchanges[b][sdpconstrow[b][k]] && indchanges[b][sdpconstrow[b][k]] <= sdpconstrow[b][k] );
1026  assert( -1 < indchanges[b][sdpconstcol[b][k]] && indchanges[b][sdpconstcol[b][k]] <= sdpconstcol[b][k] );
1027 
1028  assert( 0 <= sdpconstrow[b][k] && sdpconstrow[b][k] <= sdpblocksizes[b] );
1029  assert( 0 <= sdpconstcol[b][k] && sdpconstcol[b][k] <= sdpblocksizes[b] );
1030 
1031  moseksdpconstrow[k] = sdpconstrow[b][k] - indchanges[b][sdpconstrow[b][k]];
1032  moseksdpconstcol[k] = sdpconstcol[b][k] - indchanges[b][sdpconstcol[b][k]];
1033 
1034 #if CONVERT_ABSOLUTE_TOLERANCES
1035  /* update largest rhs-entry */
1036  if ( REALABS(sdpconstval[b][k]) > maxrhscoef )
1037  maxrhscoef = REALABS(sdpconstval[b][k]);
1038 #endif
1039  }
1040 
1041  MOSEK_CALL( MSK_appendsparsesymmat(sdpisolver->msktask, mosekblocksizes[b - blockindchanges[b]], sdpconstnblocknonz[b],
1042  moseksdpconstrow, moseksdpconstcol, sdpconstval[b], &mosekindex) );/*lint !e641, !e679, !e747*/
1043 
1044  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &moseksdpconstcol);
1045  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &moseksdpconstrow);
1046  }
1047  else
1048  {
1049  MOSEK_CALL( MSK_appendsparsesymmat(sdpisolver->msktask, mosekblocksizes[b - blockindchanges[b]], sdpconstnblocknonz[b],
1050  sdpconstrow[b], sdpconstcol[b], sdpconstval[b], &mosekindex) );/*lint !e641, !e679, !e747*/
1051  }
1052  MOSEK_CALL( MSK_putbarcj(sdpisolver->msktask, i, 1, &mosekindex, &one) );/*lint !e641, !e747*/
1053  i++;
1054  }
1055  }
1056  }
1057 
1058  /* set objective values for the scalar variables */
1059  /* TODO: check for equality constraints */
1060  /* first for those corresponding to LP constraints in the dual */
1061  ind = 0;
1062  for (i = 0; i < nlpcons; i++)
1063  {
1064  /* left hand side */
1065  if ( lplhs[i] > - SCIPsdpiSolverInfinity(sdpisolver) )
1066  {
1067  MOSEK_CALL( MSK_putcj(sdpisolver->msktask, ind, lplhs[i]) );/*lint !e641*/
1068 #ifdef SCIP_MORE_DEBUG
1069  /* give the variable a meaningful name for debug output */
1070  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "lhs#%d", i);
1071  MOSEK_CALL( MSK_putvarname(sdpisolver->msktask, ind, name) );
1072 #endif
1073  ++ind;
1074  }
1075 
1076  /* right hand side */
1077  if ( lprhs[i] < SCIPsdpiSolverInfinity(sdpisolver) )
1078  {
1079  MOSEK_CALL( MSK_putcj(sdpisolver->msktask, ind, - lprhs[i]) );/*lint !e641, !e644*/
1080 #ifdef SCIP_MORE_DEBUG
1081  /* give the variable a meaningful name for debug output */
1082  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "rhs#%d", i - 1);
1083  MOSEK_CALL( MSK_putvarname(sdpisolver->msktask, ind, name) );
1084 #endif
1085  ++ind;
1086  }
1087  }
1088  assert( ind == nlpvars );
1089 
1090  /* finally for those corresponding to variable bounds in the dual */
1091  for (i = 0; i < sdpisolver->nvarbounds; i++)
1092  {
1093  MOSEK_CALL( MSK_putcj(sdpisolver->msktask, nlpvars + i, mosekvarbounds[i]) );/*lint !e641*/ /* for the ub's we already added a negative sign in mosekvarbounds */
1094 
1095 #if 0
1096  /* We currently do not include variable bounds in maxrhscoef, because it does not seem to be beneficial
1097  * overall. The bounds are very relevant for cardinality least square instances in which all variables are binary,
1098  * except for one continuous variable representing the objective value. The objective value can be
1099  * large. Enlarging maxrhscoef will not particularly help in this context, since the objective values are measure
1100  * relatively and the bounds are filtered out later anyway. */
1101 #if CONVERT_ABSOLUTE_TOLERANCES
1102  if ( REALABS(mosekvarbounds[i]) > maxrhscoef )
1103  maxrhscoef = REALABS(mosekvarbounds[i]);
1104 #endif
1105 #endif
1106 
1107 #ifdef SCIP_MORE_DEBUG
1108  if ( sdpisolver->varboundpos[i] < 0 ) /* lower bound */
1109  {
1110  /* give the variable a meaningful name for debug output */
1111  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "lb#%d", sdpisolver->mosektoinputmapper[-1 * sdpisolver->varboundpos[i] - 1]);
1112  MOSEK_CALL( MSK_putvarname(sdpisolver->msktask, nlpvars + i, name) );
1113  }
1114  else /* upper bound */
1115  {
1116  assert( sdpisolver->varboundpos[i] > 0 ); /* we should not have value 0 so that we can clearly differentiate between positive and negative */
1117  /* give the variable a meaningful name for debug output */
1118  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "ub#%d", sdpisolver->mosektoinputmapper[sdpisolver->varboundpos[i] - 1]);
1119  MOSEK_CALL( MSK_putvarname(sdpisolver->msktask, nlpvars + i, name) );
1120  }
1121 #endif
1122  }
1123 
1124  /* set objective sense (since we want to minimize in the dual, we maximize in the primal) */
1125  MOSEK_CALL( MSK_putobjsense(sdpisolver->msktask, MSK_OBJECTIVE_SENSE_MAXIMIZE) );/*lint !e641*/
1126 
1127  /* start inserting the constraints */
1128 
1129  /* first add the matrices A_i */
1130  for (b = 0; b < nsdpblocks; b++)
1131  {
1132  if ( blockindchanges[b] > -1 )
1133  {
1134  /* prepare memory */
1135  if ( nremovedinds[b] > 0 )
1136  {
1137  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &mosekrow, sdpnnonz) );
1138  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &mosekcol, sdpnnonz) );
1139  }
1140  else
1141  {
1142  mosekrow = NULL;
1143  mosekcol = NULL;
1144  }
1145 
1146  for (blockvar = 0; blockvar < sdpnblockvars[b]; blockvar++)
1147  {
1148  v = sdpisolver->inputtomosekmapper[sdpvar[b][blockvar]];
1149 
1150  /* check if the variable is active */
1151  if ( v > -1 )
1152  {
1153  assert( v < sdpisolver->nactivevars );
1154 
1155  /* if there are removed indices, we have to adjust the column and row indices accordingly */
1156  if ( nremovedinds[b] > 0 )
1157  {
1158  assert( sdpnblockvarnonz[b][blockvar] <= sdpnnonz );
1159  for (k = 0; k < sdpnblockvarnonz[b][blockvar]; k++)
1160  {
1161  /* rows and cols with active nonzeros should not be removed */
1162  assert( 0 <= indchanges[b][sdprow[b][blockvar][k]] && indchanges[b][sdprow[b][blockvar][k]] <= sdprow[b][blockvar][k] );
1163  assert( 0 <= indchanges[b][sdpcol[b][blockvar][k]] && indchanges[b][sdpcol[b][blockvar][k]] <= sdpcol[b][blockvar][k] );
1164 
1165  assert( 0 <= sdprow[b][blockvar][k] && sdprow[b][blockvar][k] < sdpblocksizes[b] );
1166  assert( 0 <= sdpcol[b][blockvar][k] && sdpcol[b][blockvar][k] < sdpblocksizes[b] );
1167 
1168  mosekrow[k] = sdprow[b][blockvar][k] - indchanges[b][sdprow[b][blockvar][k]];
1169  mosekcol[k] = sdpcol[b][blockvar][k] - indchanges[b][sdpcol[b][blockvar][k]];
1170  }
1171  assert( k == sdpnblockvarnonz[b][blockvar] );
1172 
1173  MOSEK_CALL( MSK_appendsparsesymmat(sdpisolver->msktask, mosekblocksizes[b - blockindchanges[b]], (long long) k,
1174  mosekrow, mosekcol, sdpval[b][blockvar], &mosekindex) );/*lint !e641, !e679*/
1175  }
1176  else
1177  {
1178  MOSEK_CALL( MSK_appendsparsesymmat(sdpisolver->msktask, mosekblocksizes[b - blockindchanges[b]], (long long) sdpnblockvarnonz[b][blockvar],
1179  sdprow[b][blockvar], sdpcol[b][blockvar], sdpval[b][blockvar], &mosekindex) );/*lint !e641, !e679*/
1180  }
1181 
1182  MOSEK_CALL( MSK_putbaraij(sdpisolver->msktask, v, b - blockindchanges[b], (long long) 1, &mosekindex, &one) );/*lint !e641*/
1183  }
1184  }
1185  BMSfreeBufferMemoryArrayNull(sdpisolver->bufmem, &mosekcol);
1186  BMSfreeBufferMemoryArrayNull(sdpisolver->bufmem, &mosekrow);
1187  }
1188  }
1189 
1190  /* add the identity matrix corresponding to the penalty variable */
1191  if ( penaltyparam >= sdpisolver->epsilon )
1192  {
1193  int* identityindices;
1194  SCIP_Real* identityvalues;
1195 
1196  for (b = 0; b < nsdpblocks; b++)
1197  {
1198  if ( blockindchanges[b] > -1 )
1199  {
1200  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &identityindices, mosekblocksizes[b - blockindchanges[b]]) );
1201  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &identityvalues, mosekblocksizes[b - blockindchanges[b]]) );
1202 
1203  for (i = 0; i < mosekblocksizes[b - blockindchanges[b]]; i++)
1204  {
1205  identityindices[i] = i;
1206  identityvalues[i] = 1.0;
1207  }
1208  MOSEK_CALL( MSK_appendsparsesymmat(sdpisolver->msktask, mosekblocksizes[b - blockindchanges[b]], (long long) mosekblocksizes[b - blockindchanges[b]],
1209  identityindices, identityindices, identityvalues, &mosekindex) );/*lint !e641, !e679*/
1210  MOSEK_CALL( MSK_putbaraij(sdpisolver->msktask, sdpisolver->nactivevars, b - blockindchanges[b], (long long) 1, &mosekindex, &one) );/*lint !e641, !e679*/
1211 
1212  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &identityvalues);
1213  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &identityindices);
1214  }
1215  }
1216  }
1217 
1218  /* add the entries corresponding to the lp-constraints in the dual problem */
1219  if ( lpnnonz > 0 )
1220  {
1221  int currentrow;
1222  int varcnt = 0;
1223 
1224  if ( penaltyparam < sdpisolver->epsilon )
1225  {
1226  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &mosekrow, lpnnonz) );
1227  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &mosekval, lpnnonz) );
1228  }
1229  else
1230  {
1231  /* one extra entry for the penalty-constraint Trace = Gamma */
1232  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &mosekrow, lpnnonz + 1) );/*lint !e776*/
1233  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &mosekval, lpnnonz + 1) );/*lint !e776*/
1234  }
1235 
1236  currentrow = lprow[0];
1237  mosekind = 0;
1238  for (nnonz = 0; nnonz < lpnnonz; ++nnonz)
1239  {
1240  assert( nnonz == 0 || lprow[nnonz-1] <= lprow[nnonz] ); /* rows should be sorted */
1241 
1242  v = sdpisolver->inputtomosekmapper[lpcol[nnonz]];
1243  if ( v >= 0 )
1244  {
1245  mosekrow[mosekind] = v;
1246  mosekval[mosekind++] = lpval[nnonz];
1247  }
1248 
1249  /* we finished a row */
1250  if ( nnonz == lpnnonz - 1 || lprow[nnonz + 1] > currentrow )
1251  {
1252  /* all rows with at most one nonzero should have been sorted out */
1253  assert( mosekind >= 2 );
1254 
1255  /* add the additional entry for the penalty constraint Trace = Gamma */
1256  if ( penaltyparam >= sdpisolver->epsilon )
1257  {
1258  mosekrow[mosekind] = sdpisolver->nactivevars;
1259  mosekval[mosekind++] = 1.0;
1260  }
1261  assert( mosekind <= lpnnonz + 1 );
1262 
1263  /* treat left hand side */
1264  if ( lplhs[currentrow] > - SCIPsdpiSolverInfinity(sdpisolver) )
1265  {
1266  MOSEK_CALL( MSK_putacol(sdpisolver->msktask, varcnt++, mosekind, mosekrow, mosekval) );/*lint !e641*/
1267  }
1268 
1269  /* treat right hand side */
1270  if ( lprhs[currentrow] < SCIPsdpiSolverInfinity(sdpisolver) )
1271  {
1272  /* multiply column by -1 */
1273  for (j = 0; j < (penaltyparam < sdpisolver->epsilon ? mosekind : mosekind - 1); j++)/*lint !e644*/
1274  mosekval[j] *= -1.0;
1275 
1276  MOSEK_CALL( MSK_putacol(sdpisolver->msktask, varcnt++, mosekind, mosekrow, mosekval) );/*lint !e641*/
1277  }
1278 
1279  /* reset counters */
1280  mosekind = 0;
1281  if ( nnonz < lpnnonz - 1 )
1282  currentrow = lprow[nnonz+1];
1283  }
1284  }
1285  assert( varcnt == nlpvars );
1286 
1287  BMSfreeBufferMemoryArrayNull(sdpisolver->bufmem, &mosekval);
1288  BMSfreeBufferMemoryArrayNull(sdpisolver->bufmem, &mosekrow);
1289  }
1290 
1291  /* finally add the entries corresponding to varbounds in the dual problem, we get exactly one entry per variable */
1292  for (i = 0; i < sdpisolver->nvarbounds; i++)
1293  {
1294  if ( sdpisolver->varboundpos[i] < 0 )
1295  {
1296  /* lower bound */
1297  row = - sdpisolver->varboundpos[i] - 1; /* minus one because we added one to get strictly positive/negative values */
1298  val = 1.0;
1299  }
1300  else
1301  {
1302  /* upper bound */
1303  assert( sdpisolver->varboundpos[i] > 0 ); /* we should not have a zero as we wanted a clear differentiation between positive and negative */
1304  row = sdpisolver->varboundpos[i] - 1; /* minus one because we added one to get strictly positive/negative values */
1305  val = -1.0;
1306  }
1307  MOSEK_CALL( MSK_putacol(sdpisolver->msktask, nlpvars + i, 1, &row, &val) );/*lint !e641*/
1308  }
1309 
1310  /* possibly scale objective */
1311  if ( sdpisolver->scaleobj )
1312  {
1313  if ( REALABS(maxabsobjcoef) > 1.0 )
1314  {
1315  assert( withobj );
1316  sdpisolver->objscalefactor = maxabsobjcoef;
1317  SCIPdebugMessage("Scaling objective by %g.\n", 1.0 / sdpisolver->objscalefactor);
1318  maxabsobjcoef = 1.0; /* this is now 1 because of scaling */
1319  }
1320  }
1321  else
1322  assert( sdpisolver->objscalefactor == 1.0 );
1323 
1324  /* make all constraints equality constraints with right-hand side b_i (or 0 if we solve without objective) */
1325  for (i = 0; i < sdpisolver->nactivevars; i++)
1326  {
1327  if ( withobj )
1328  {
1329  SCIP_Real objcoef;
1330 
1331  objcoef = sdpisolver->objcoefs[i];
1332  assert( objcoef == obj[sdpisolver->mosektoinputmapper[i]] );
1333  objcoef /= sdpisolver->objscalefactor;
1334  MOSEK_CALL( MSK_putconbound(sdpisolver->msktask, i, MSK_BK_FX, objcoef, objcoef) );/*lint !e641*/
1335  }
1336  else
1337  {
1338  MOSEK_CALL( MSK_putconbound(sdpisolver->msktask, i, MSK_BK_FX, 0.0, 0.0) );/*lint !e641*/
1339  }
1340 
1341 #ifdef SCIP_MORE_DEBUG
1342  /* give the constraint a meaningful name for debug output */
1343  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "var#%d", sdpisolver->mosektoinputmapper[i]);
1344  MOSEK_CALL( MSK_putconname(sdpisolver->msktask, i, name) );
1345 #endif
1346  }
1347 
1348  /* the penalty constraint has right-hand side Gamma, it is a <=-inequality if r was bounded and an equality constraint otherwise */
1349  if ( penaltyparam >= sdpisolver->epsilon )
1350  {
1351  SCIP_Real p;
1352 
1353  p = penaltyparam / sdpisolver->objscalefactor;
1354  if ( rbound )
1355  {
1356  MOSEK_CALL( MSK_putconbound(sdpisolver->msktask, sdpisolver->nactivevars, MSK_BK_UP, (double) - MSK_DPAR_DATA_TOL_BOUND_INF, p) );/*lint !e641*/
1357  }
1358  else
1359  {
1360  MOSEK_CALL( MSK_putconbound(sdpisolver->msktask, sdpisolver->nactivevars, MSK_BK_FX, p, p) );/*lint !e641*/
1361  }
1362 #ifdef SCIP_MORE_DEBUG
1363  /* give the constraint a meaningful name for debug output */
1364  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "penalty");
1365  MOSEK_CALL( MSK_putconname(sdpisolver->msktask, i, name) );
1366 #endif
1367  }
1368 
1369  solvertimelimit = timelimit;
1370  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, solvertimelimit) )
1371  solvertimelimit -= SDPIclockGetTime(usedsdpitime);
1372 
1373  if ( solvertimelimit <= 0.0 )
1374  {
1375  sdpisolver->timelimit = TRUE;
1376  sdpisolver->solved = FALSE;
1377  }
1378  else
1379  {
1380  SCIP_Real feastol;
1381  SCIP_Real gaptol;
1382 
1383  /* 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,
1384  * since MOSEK works with relative tolerance, we adjust our absolute tolerance accordingly, so that any solution satisfying the relative
1385  * tolerance in MOSEK satisfies our absolute tolerance) */
1386 #if CONVERT_ABSOLUTE_TOLERANCES
1387  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_PFEAS, sdpisolver->gaptol) );
1388  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_DFEAS, sdpisolver->sdpsolverfeastol / (1.0 + maxrhscoef)) );
1389  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_INFEAS, sdpisolver->sdpsolverfeastol / (1.0 + maxrhscoef)) );
1390  SCIPdebugMessage("Setting relative feasibility tolerance for MOSEK to %.10g / %g = %.12g\n", sdpisolver->sdpsolverfeastol,
1391  1.0 + maxrhscoef, sdpisolver->sdpsolverfeastol / (1.0 + maxrhscoef));
1392 #else
1393  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_PFEAS, sdpisolver->gaptol) );
1394  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_DFEAS, sdpisolver->sdpsolverfeastol) );
1395  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_INFEAS, sdpisolver->sdpsolverfeastol) );
1396 #endif
1397  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_MU_RED, sdpisolver->gaptol) );
1398  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_REL_GAP, sdpisolver->gaptol) );
1399 
1400  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, solvertimelimit) )
1401  {
1402  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_OPTIMIZER_MAX_TIME, solvertimelimit) );/*lint !e641*/
1403  }
1404 
1405  /* set objective cutoff */
1406  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, sdpisolver->objlimit) )
1407  {
1408  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_UPPER_OBJ_CUT, sdpisolver->objlimit / sdpisolver->objscalefactor) );
1409  }
1410 
1411  /* turn presolving on/off */
1412  if ( sdpisolver->usepresolving )
1413  {
1414  SCIPdebugMessage("Turning presolving on.\n");
1415  MOSEK_CALL( MSK_putintparam(sdpisolver->msktask, MSK_IPAR_PRESOLVE_USE, MSK_PRESOLVE_MODE_ON) );
1416  }
1417  else
1418  {
1419  SCIPdebugMessage("Turning presolving off.\n");
1420  MOSEK_CALL( MSK_putintparam(sdpisolver->msktask, MSK_IPAR_PRESOLVE_USE, MSK_PRESOLVE_MODE_OFF) );
1421  }
1422 
1423  /* turn scaling on/off */
1424  if ( sdpisolver->usescaling )
1425  {
1426  MOSEK_CALL( MSK_putintparam(sdpisolver->msktask, MSK_IPAR_INTPNT_SCALING, MSK_SCALING_FREE) );
1427  }
1428  else
1429  {
1430  MOSEK_CALL( MSK_putintparam(sdpisolver->msktask, MSK_IPAR_INTPNT_SCALING, MSK_SCALING_NONE) );
1431  }
1432 
1433  /* print whole problem (only for MOSEK < 9) and parameters if asked to */
1434 #ifdef SCIP_MORE_DEBUG
1435 #if MSK_VERSION_MAJOR < 9
1436  {
1437  int nmosekconss;
1438  int nmosekvars;
1439  int nmosekcones;
1440 
1441  MOSEK_CALL( MSK_getnumcon(sdpisolver->msktask, &nmosekconss) );
1442  MOSEK_CALL( MSK_getnumvar(sdpisolver->msktask, &nmosekvars) );
1443  MOSEK_CALL( MSK_getnumcone(sdpisolver->msktask, &nmosekcones) );
1444 
1445  MOSEK_CALL( MSK_printdata(sdpisolver->msktask, MSK_STREAM_LOG, 0, nmosekconss, 0, nmosekvars, 0, nmosekcones, 1, 1, 1, 1, 1, 1, 1, 1) );
1446  }
1447 #endif
1448 #ifdef SCIP_PRINT_PARAMETERS
1449  MOSEK_CALL( MSK_printparam(sdpisolver->msktask) );
1450 #endif
1451 #endif
1452 
1453  /* write to file if asked to */
1454 #ifdef SCIP_DEBUG_PRINTTOFILE
1455  SCIP_CALL( SCIPsdpiSolverWriteSDP(sdpisolver, "mosek.task") );
1456 #endif
1457 
1458  /* solve the problem */
1459  MOSEK_CALL( MSK_optimizetrm(sdpisolver->msktask, &(sdpisolver->terminationcode)) );/*lint !e641*/
1460  MOSEK_CALL( MSK_getdouinf(sdpisolver->msktask, MSK_DINF_OPTIMIZER_TIME, &sdpisolver->opttime) );
1461  MOSEK_CALL( MSK_getsolsta(sdpisolver->msktask, MSK_SOL_ITR, &sdpisolver->solstat) );/*lint !e641*/
1462 
1463  if ( sdpisolver->sdpinfo )
1464  {
1465  MOSEK_CALL( MSK_optimizersummary(sdpisolver->msktask, MSK_STREAM_LOG) );/*lint !e641*/
1466  MOSEK_CALL( MSK_analyzesolution(sdpisolver->msktask, MSK_STREAM_LOG, MSK_SOL_ITR) );/*lint !e641*/
1467  }
1468 
1469  SCIPdebugMessage("Solved problem using MOSEK, return code %d.\n", sdpisolver->terminationcode);
1470 
1471  sdpisolver->solved = TRUE;
1472 
1473  /* update number of SDP-iterations and -calls */
1474  ++sdpisolver->nsdpcalls;
1475  MOSEK_CALL( MSK_getnaintinf(sdpisolver->msktask, "MSK_IINF_INTPNT_ITER", &(sdpisolver->niterations)) );/*lint !e641*/
1476 
1477  /* possibly repair status */
1478  if ( sdpisolver->terminationcode == MSK_RES_TRM_STALL || (sdpisolver->solstat == MSK_SOL_STA_UNKNOWN && sdpisolver->terminationcode != MSK_RES_TRM_MAX_TIME) )
1479  {
1480  SCIP_Real pobj;
1481  SCIP_Real pviolcon;
1482  SCIP_Real pviolvar;
1483  SCIP_Real pviolbarvar;
1484  SCIP_Real dobj;
1485  SCIP_Real dviolcon;
1486  SCIP_Real dviolvar;
1487  SCIP_Real dviolbarvar;
1488 
1489  MOSEK_CALL( MSK_getsolutioninfo(sdpisolver->msktask, MSK_SOL_ITR, &pobj, &pviolcon, &pviolvar, &pviolbarvar, NULL, NULL,
1490  &dobj, &dviolcon, &dviolvar, &dviolbarvar, NULL) );
1491 
1492  SCIPdebugMessage("Absolute primal violations: constraints: %g, variables: %g, SDP: %g.\n", pviolcon, pviolvar, pviolbarvar);
1493  SCIPdebugMessage("Absolute dual violations: constraints: %g, variables: %g, SDP: %g.\n", dviolcon, dviolvar, dviolbarvar);
1494  if ( pviolcon <= sdpisolver->feastol && pviolvar <= sdpisolver->feastol && pviolbarvar <= sdpisolver->feastol
1495  && dviolcon <= sdpisolver->feastol && dviolvar <= sdpisolver->feastol && dviolbarvar <= sdpisolver->feastol )
1496  {
1497  if ( REALABS(dobj - pobj) <= sdpisolver->gaptol )
1498  {
1499  sdpisolver->terminationcode = MSK_RES_OK;
1500  sdpisolver->solstat = MSK_SOL_STA_OPTIMAL;
1501  SCIPdebugMessage("Detected stalling - repairing termination code and solution status to 'optimal'.\n");
1502  }
1503  }
1504  }
1505 
1506  /* if the problem has been stably solved but did not reach the required feasibility tolerance, even though the solver
1507  * reports feasibility, resolve it with adjusted tolerance */
1508 #if CONVERT_ABSOLUTE_TOLERANCES
1509  feastol = sdpisolver->sdpsolverfeastol / (1 + maxrhscoef);
1510 #else
1511  feastol = sdpisolver->sdpsolverfeastol;
1512 #endif
1513  gaptol = sdpisolver->gaptol;
1514 
1515  while ( SCIPsdpiSolverIsAcceptable(sdpisolver) && SCIPsdpiSolverIsDualFeasible(sdpisolver) && penaltyparam < sdpisolver->epsilon && feastol >= INFEASMINFEASTOL )
1516  {
1517  SCIP_Real* solvector;
1518  SCIP_Bool infeasible;
1519  SCIP_Bool solveagain = FALSE;
1520  SCIP_Real opttime;
1521  int nvarspointer;
1522  int newiterations;
1523 
1524  /* get current solution */
1525  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &solvector, nvars) );
1526  nvarspointer = nvars;
1527  SCIP_CALL( SCIPsdpiSolverGetSol(sdpisolver, NULL, solvector, &nvarspointer) );
1528  assert( nvarspointer == nvars );
1529 
1530  /* check the solution for feasibility with regards to our tolerance */
1531  SCIP_CALL( SCIPsdpSolcheckerCheck(sdpisolver->bufmem, nvars, lb, ub, nsdpblocks, sdpblocksizes, sdpnblockvars, sdpconstnnonz,
1532  sdpconstnblocknonz, sdpconstrow, sdpconstcol, sdpconstval, sdpnnonz, sdpnblockvarnonz, sdpvar, sdprow, sdpcol, sdpval,
1533  indchanges, nremovedinds, blockindchanges, nlpcons, lplhs, lprhs, lpnnonz, lprow, lpcol, lpval,
1534  solvector, sdpisolver->feastol, sdpisolver->epsilon, &infeasible) );
1535  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &solvector);
1536 
1537 #if CHECKVIOLATIONS == 1
1538  {
1539  /* The following code obtains the primal and dual solution reported from MOSEK and checks the violations of
1540  * the variable bounds, and linear as well as SDP constraints. Since MOSEK seems to use a different LAPACK
1541  * routine to compute the eigenvalues of a symmetric matrix, the violations of the SDP constraints in the
1542  * primal and dual reported from MOSEK and computed by SCIP-SDP differ slightly. Apart from that, the primal
1543  * violations (variables and linear constraints) SCIP-SDP computes the same violations as MOSEK. For the
1544  * dual problem however, MOSEK uses slack variables to obtain equalities, whereas the original (dual)
1545  * problem in SCIP-SDP may have inequalities. Thus, MOSEK reports violations in the dual with respect to the
1546  * slack variables and the corresponding equalities, whereas SCIP-SDP computes violations with respect to
1547  * the original inequalities. Thus, those violations differ. Moreover, the dual variable violations reported
1548  * from MOSEK seem to be the violations of the constraints in the dual problem, and the dual constraint
1549  * violations from MOSEK seem to be the violation of the variables in the dual problem, since the dual of
1550  * the primal constraints are the dual variables.
1551  */
1552  SCIP_Real* solvectorprimal;
1553  SCIP_Real** solmatrices;
1554  SCIP_Real maxabsviolbndsd;
1555  SCIP_Real sumabsviolbndsd;
1556  SCIP_Real maxabsviolconsd;
1557  SCIP_Real sumabsviolconsd;
1558  SCIP_Real maxabsviolsdpd;
1559  SCIP_Real sumabsviolsdpd;
1560  SCIP_Real maxabsviolbndsp;
1561  SCIP_Real sumabsviolbndsp;
1562  SCIP_Real maxabsviolconsp;
1563  SCIP_Real sumabsviolconsp;
1564  SCIP_Real maxabsviolsdpp;
1565  SCIP_Real sumabsviolsdpp;
1566  SCIP_Bool checkinfeas;
1567  SCIP_Real pobj;
1568  SCIP_Real pviolcon;
1569  SCIP_Real pviolvar;
1570  SCIP_Real pviolbarvar;
1571  SCIP_Real dobj;
1572  SCIP_Real dviolcon;
1573  SCIP_Real dviolvar;
1574  SCIP_Real dviolbarvar;
1575  int nprimalvars;
1576  int nprimalmatrixvars;
1577  int blocksize;
1578 
1579  /* get violations from Mosek */
1580  MOSEK_CALL( MSK_getsolutioninfo(sdpisolver->msktask, MSK_SOL_ITR, &pobj, &pviolcon, &pviolvar, &pviolbarvar, NULL, NULL,
1581  &dobj, &dviolcon, &dviolvar, &dviolbarvar, NULL) );
1582 
1583  nprimalvars = nlpvars + sdpisolver->nvarbounds;
1584  nprimalmatrixvars = nsdpblocks - nremovedblocks;
1585 
1586  /* get current solution */
1587  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &solvectorprimal, nprimalvars) );
1588  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &solmatrices, nprimalmatrixvars) );
1589  for (i = 0; i < nprimalmatrixvars; i++)
1590  {
1591  blocksize = mosekblocksizes[i];
1592  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &solmatrices[i], blocksize) );
1593  }
1594 
1595  MOSEK_CALL( MSK_getxx(sdpisolver->msktask, MSK_SOL_ITR, solvectorprimal) );
1596  for (i = 0; i < nprimalmatrixvars; i++)
1597  MOSEK_CALL( MSK_getbarxj(sdpisolver->msktask, MSK_SOL_ITR, i, solmatrices[i]) );
1598 
1599 #ifdef SCIP_PRINT_SOLU
1600  /* print primal and dual solution reported from MOSEK */
1601  SCIPdebugMessage("Dual solution reported from MOSEK transformed to our problem:\n");
1602  for (i = 0; i < nvars; i++)
1603  SCIPdebugMessage("y[%d] = %.15g\n", i, solvector[i]);
1604 
1605  SCIPdebugMessage("Primal solution reported from MOSEK:\n");
1606  for (i = 0; i < nprimalvars; i++)
1607  SCIPdebugMessage("x[%d] = %.15g\n", i, solvectorprimal[i]);
1608 
1609  for (i = 0; i < nprimalmatrixvars; i++)
1610  {
1611  blocksize = mosekblocksizes[i];
1612  for (j = 0; j < blocksize * (blocksize + 1) / 2; j++)
1613  SCIPdebugMessage("X_%d[%d] = %.15g\n", i, j, solmatrices[i][j]);
1614  }
1615 #endif
1616 
1617  /* check violations reported from Mosek */
1618  SCIP_CALL( SCIPsdpSolcheckerCheckAndGetViolDual(sdpisolver->bufmem, nvars, lb, ub, nsdpblocks, sdpblocksizes, sdpnblockvars, sdpconstnnonz,
1619  sdpconstnblocknonz, sdpconstrow, sdpconstcol, sdpconstval, sdpnnonz, sdpnblockvarnonz, sdpvar, sdprow, sdpcol, sdpval,
1620  indchanges, nremovedinds, blockindchanges, nlpcons, lplhs, lprhs, lpnnonz, lprow, lpcol, lpval,
1621  solvector, sdpisolver->feastol, sdpisolver->epsilon, &maxabsviolbndsd, &sumabsviolbndsd, &maxabsviolconsd, &sumabsviolconsd,
1622  &maxabsviolsdpd, &sumabsviolsdpd, &checkinfeas) );
1623  if ( checkinfeas )
1624  assert( infeasible );
1625 
1626  SCIP_CALL( SCIPsdpSolcheckerCheckAndGetViolPrimal(sdpisolver->bufmem, nvars, obj, lb, ub, sdpisolver->inputtomosekmapper, nsdpblocks,
1627  sdpblocksizes, sdpnblockvars, sdpconstnnonz, sdpconstnblocknonz, sdpconstrow, sdpconstcol, sdpconstval, sdpnnonz, sdpnblockvarnonz,
1628  sdpvar, sdprow, sdpcol, sdpval, indchanges, nremovedinds, blockindchanges, nremovedblocks, nlpcons, lplhs, lprhs, lpnnonz, lprow, lpcol,
1629  lpval, solvectorprimal, solmatrices, sdpisolver->feastol, sdpisolver->epsilon, &maxabsviolbndsp, &sumabsviolbndsp, &maxabsviolconsp,
1630  &sumabsviolconsp, &maxabsviolsdpp, &sumabsviolsdpp, &checkinfeas) );
1631  if ( checkinfeas )
1632  assert( infeasible );
1633 
1634  /* dviolcon is the maximal violation of the dual variables, since they are the dual of the primal constraints */
1635  SCIPdebugMessage("Maximal violations for the dual problem: vars: %g (Mosek), %g (SCIP-SDP); cons: %g (Mosek), %g (SCIP-SDP); SDP: %g (Mosek), %g (SCIP-SDP)\n",
1636  dviolcon, maxabsviolbndsd, dviolvar, maxabsviolconsd, dviolbarvar, maxabsviolsdpd);
1637  SCIPdebugMessage("Maximal violations for the primal problem: vars: %g (Mosek), %g (SCIP-SDP); cons: %g (Mosek), %g (SCIP-SDP); SDP: %g (Mosek), %g (SCIP-SDP)\n",
1638  pviolvar, maxabsviolbndsp, pviolcon, maxabsviolconsp, pviolbarvar, maxabsviolsdpp);
1639  SCIPdebugMessage("Sum of violations for the dual problem: vars: %g (SCIP-SDP); cons: %g (SCIP-SDP); SDP: %g (SCIP-SDP)\n",
1640  sumabsviolbndsd, sumabsviolconsd, sumabsviolsdpd);
1641  SCIPdebugMessage("Sum of violations for the primal problem: vars: %g (SCIP-SDP); cons: %g (SCIP-SDP); SDP: %g (SCIP-SDP)\n",
1642  sumabsviolbndsp, sumabsviolconsp, sumabsviolsdpp);
1643 
1644  for (i = 0; i < nprimalmatrixvars; i++)
1645  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &solmatrices[i]);
1646  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &solmatrices);
1647  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &solvectorprimal);
1648  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &solvector);
1649  }
1650 #endif
1651 
1652  if ( infeasible )
1653  {
1654  feastol *= INFEASFEASTOLCHANGE;
1655  if ( feastol >= INFEASMINFEASTOL )
1656  {
1657  SCIPdebugMessage("Solution feasible for Mosek but outside feasibility tolerance, changing Mosek feasibility tolerance to %g.\n", feastol);
1658  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_DFEAS, feastol) );
1659  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_INTPNT_CO_TOL_INFEAS, feastol) );
1660  solveagain = TRUE;
1661  }
1662  }
1663 
1664  if ( solveagain )
1665  {
1666  /* set the time limit */
1667  solvertimelimit = timelimit;
1668  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, solvertimelimit) )
1669  solvertimelimit -= SDPIclockGetTime(usedsdpitime);
1670 
1671  if ( solvertimelimit <= 0.0 )
1672  {
1673  sdpisolver->timelimit = TRUE;
1674  sdpisolver->solved = FALSE;
1675  }
1676  else
1677  {
1678  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, solvertimelimit) )
1679  {
1680  MOSEK_CALL( MSK_putdouparam(sdpisolver->msktask, MSK_DPAR_OPTIMIZER_MAX_TIME, solvertimelimit) );/*lint !e641*/
1681  }
1682 
1683  /* solve the problem */
1684  MOSEK_CALL( MSK_optimizetrm(sdpisolver->msktask, &(sdpisolver->terminationcode)) );/*lint !e641*/
1685  MOSEK_CALL( MSK_getsolsta(sdpisolver->msktask, MSK_SOL_ITR, &sdpisolver->solstat) );/*lint !e641*/
1686  MOSEK_CALL( MSK_getdouinf(sdpisolver->msktask, MSK_DINF_OPTIMIZER_TIME, &opttime) );
1687  sdpisolver->opttime += opttime;
1688 
1689  if ( sdpisolver->sdpinfo )
1690  {
1691  MOSEK_CALL( MSK_optimizersummary(sdpisolver->msktask, MSK_STREAM_LOG) );/*lint !e641*/
1692  MOSEK_CALL( MSK_analyzesolution(sdpisolver->msktask, MSK_STREAM_LOG, MSK_SOL_ITR) );/*lint !e641*/
1693  }
1694 
1695  /* update number of SDP-iterations and -calls */
1696  ++sdpisolver->nsdpcalls;
1697  MOSEK_CALL( MSK_getnaintinf(sdpisolver->msktask, "MSK_IINF_INTPNT_ITER", &newiterations) );/*lint !e641*/
1698  sdpisolver->niterations += newiterations;
1699 
1700  /* possibly repair status */
1701  if ( sdpisolver->terminationcode == MSK_RES_TRM_STALL || sdpisolver->solstat == MSK_SOL_STA_UNKNOWN )
1702  {
1703  SCIP_Real pobj;
1704  SCIP_Real pviolcon;
1705  SCIP_Real pviolvar;
1706  SCIP_Real pviolbarvar;
1707  SCIP_Real dobj;
1708  SCIP_Real dviolcon;
1709  SCIP_Real dviolvar;
1710  SCIP_Real dviolbarvar;
1711 
1712  MOSEK_CALL( MSK_getsolutioninfo(sdpisolver->msktask, MSK_SOL_ITR, &pobj, &pviolcon, &pviolvar, &pviolbarvar, NULL, NULL,
1713  &dobj, &dviolcon, &dviolvar, &dviolbarvar, NULL) );
1714 
1715  SCIPdebugMessage("Absolute primal violations: constraints: %g, variables: %g, SDP: %g.\n", pviolcon, pviolvar, pviolbarvar);
1716  SCIPdebugMessage("Absolute dual violations: constraints: %g, variables: %g, SDP: %g.\n", dviolcon, dviolvar, dviolbarvar);
1717  if ( pviolcon <= sdpisolver->feastol && pviolvar <= sdpisolver->feastol && pviolbarvar <= sdpisolver->feastol
1718  && dviolcon <= sdpisolver->feastol && dviolvar <= sdpisolver->feastol && dviolbarvar <= sdpisolver->feastol )
1719  {
1720  if ( REALABS(dobj - pobj) <= sdpisolver->gaptol )
1721  {
1722  sdpisolver->terminationcode = MSK_RES_OK;
1723  sdpisolver->solstat = MSK_SOL_STA_OPTIMAL;
1724  SCIPdebugMessage("Detected stalling - repairing termination code and solution status to 'optimal'.\n");
1725  }
1726  }
1727  }
1728  }
1729  }
1730  else
1731  {
1732  if ( infeasible )
1733  {
1734  sdpisolver->solved = FALSE;
1735  SCIPmessagePrintInfo(sdpisolver->messagehdlr, "MOSEK failed to reach required feasibility tolerance (feastol: %g, gaptol: %g)!\n", feastol, gaptol);
1736  }
1737  break;
1738  }
1739  }
1740 
1741  if ( sdpisolver->solved )
1742  {
1743  /* if using a penalty formulation, check if the solution is feasible for the original problem
1744  * we should always count it as infeasible if the penalty problem was unbounded */
1745  if ( penaltyparam >= sdpisolver->epsilon && (sdpisolver->solstat == MSK_SOL_STA_PRIM_INFEAS_CER) )
1746  {
1747  assert( feasorig != NULL );
1748  *feasorig = FALSE;
1749  SCIPdebugMessage("Penalty Problem unbounded!\n");
1750  }
1751  else if ( penaltyparam >= sdpisolver->epsilon && ( ! sdpisolver->timelimit ) && ( sdpisolver->terminationcode != MSK_RES_TRM_MAX_TIME ) )
1752  {
1753  SCIP_Real* moseksol;
1754  SCIP_Real trace = 0.0;
1755  SCIP_Real* x;
1756 
1757  assert( feasorig != NULL );
1758 
1759  /* get the r variable in the dual problem */
1760  BMSallocBufferMemoryArray(sdpisolver->bufmem, &moseksol, sdpisolver->nactivevars + 1);/*lint !e776*/
1761 
1762  MOSEK_CALL( MSK_gety(sdpisolver->msktask, MSK_SOL_ITR, moseksol) );/*lint !e641*/
1763 
1764  *feasorig = (moseksol[sdpisolver->nactivevars] < sdpisolver->feastol); /*lint !e413*/
1765 
1766  /* only set sdpisolver->feasorig to true if we solved with objective, because only in this case we want to compute
1767  * the objective value by hand since it is numerically more stable then the result returned by MOSEK */
1768  if ( withobj )
1769  sdpisolver->feasorig = *feasorig;
1770 
1771  /* if r > 0 also check the primal bound */
1772  if ( ! *feasorig && penaltybound != NULL )
1773  {
1774  SCIPdebugMessage("Solution not feasible in original problem, r = %g.\n", moseksol[sdpisolver->nactivevars]);
1775 
1776  /* compute Tr(X) */
1777 
1778  /* start with the diagonal entries of the primal semidefinite variables */
1779  for (b = 0; b < nsdpblocks; b++)
1780  {
1781  if ( blockindchanges[b] > -1 )
1782  {
1783  SCIP_Real* X; /* the upper triangular entries of matrix X */
1784  int size;
1785 
1786  size = sdpblocksizes[b] - nremovedinds[b];
1787 
1788  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &X, size * (size + 1) / 2) );
1789  MOSEK_CALL( MSK_getbarxj(sdpisolver->msktask, MSK_SOL_ITR, b - blockindchanges[b], X) );/*lint !e641*/
1790 
1791  /* iterate over all diagonal entries */
1792  for (i = 0; i < size; i++)
1793  {
1794  /* get index in the lower triangular part */
1795  ind = i * (i + 3) / 2;/*lint !e776*/ /* i*(i+1)/2 + i */
1796  assert( ind < size * (size + 1) / 2 );
1797  trace += X[ind];
1798  }
1799 
1800  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &X);
1801  }
1802  }
1803 
1804  /* add primal lp-variables */
1805  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &x, nlpvars + sdpisolver->nvarbounds) );
1806 
1807  MOSEK_CALL( MSK_getxx(sdpisolver->msktask, MSK_SOL_ITR, x) );/*lint !e641*/
1808 
1809  for (i = 0; i < nlpvars; i++)
1810  trace += x[i];
1811 
1812  BMSfreeBufferMemoryArrayNull(sdpisolver->bufmem, &x);
1813 
1814  /* if the relative gap is smaller than the tolerance, we return equality */
1815  if ( (penaltyparam - trace) / penaltyparam < PENALTYBOUNDTOL )/*lint !e414*/
1816  {
1817  assert( penaltybound != NULL );
1818  *penaltybound = TRUE;
1819  SCIPdebugMessage("Tr(X) = %g == %g = Gamma, penalty formulation not exact, Gamma should be increased or problem is infeasible.\n",
1820  trace, penaltyparam);
1821  }
1822  else
1823  *penaltybound = FALSE;
1824  }
1825  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &moseksol);
1826  }
1827  }
1828  }
1829 
1830  /* free memory */
1831  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &mosekblocksizes);
1832  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &mosekvarbounds);
1833 
1834  return SCIP_OKAY;
1835 }
1841 /*
1842  * Solution Information Methods
1843  */
1844 
1849 SCIP_Bool SCIPsdpiSolverWasSolved(
1850  SCIP_SDPISOLVER* sdpisolver
1851  )
1852 {
1853  assert( sdpisolver != NULL );
1854 
1855  return sdpisolver->solved;
1856 }
1857 
1865  SCIP_SDPISOLVER* sdpisolver
1866  )
1867 {
1868  assert( sdpisolver != NULL );
1869  CHECK_IF_SOLVED_BOOL( sdpisolver );
1870 
1871  switch ( sdpisolver->solstat )
1872  {
1873  case MSK_SOL_STA_UNKNOWN:
1874  case MSK_SOL_STA_PRIM_FEAS:
1875  case MSK_SOL_STA_DUAL_FEAS:
1876  return FALSE;
1877  case MSK_SOL_STA_OPTIMAL:
1878  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
1879  case MSK_SOL_STA_PRIM_INFEAS_CER:
1880  case MSK_SOL_STA_DUAL_INFEAS_CER:
1881  return TRUE;
1882  default:
1883  SCIPdebugMessage("Unknown return code in SCIPsdpiSolverFeasibilityKnown\n"); /* TODO: add illposed_cer */
1884  return FALSE;
1885  }/*lint !e788*/
1886 }
1887 
1889 SCIP_RETCODE SCIPsdpiSolverGetSolFeasibility(
1890  SCIP_SDPISOLVER* sdpisolver,
1891  SCIP_Bool* primalfeasible,
1892  SCIP_Bool* dualfeasible
1893  )
1894 {
1895  assert( sdpisolver != NULL );
1896  assert( primalfeasible != NULL );
1897  assert( dualfeasible != NULL );
1898  CHECK_IF_SOLVED( sdpisolver );
1899 
1900  switch ( sdpisolver->solstat )
1901  {
1902  case MSK_SOL_STA_OPTIMAL:
1903  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
1904  *primalfeasible = TRUE;
1905  *dualfeasible = TRUE;
1906  break;
1907  case MSK_SOL_STA_PRIM_INFEAS_CER:
1908  *primalfeasible = FALSE;
1909  *dualfeasible = FALSE;
1910  break;
1911  case MSK_SOL_STA_DUAL_INFEAS_CER:
1912  *primalfeasible = FALSE;
1913  *dualfeasible = FALSE;
1914  break;
1915  default:
1916  SCIPdebugMessage("MOSEK does not know about feasibility of solutions\n");
1917  return SCIP_LPERROR;
1918  }/*lint !e788*/
1919 
1920  return SCIP_OKAY;
1921 }
1922 
1927  SCIP_SDPISOLVER* sdpisolver
1928  )
1929 {
1930  assert( sdpisolver != NULL );
1931  CHECK_IF_SOLVED_BOOL( sdpisolver );
1932 
1933  switch ( sdpisolver->solstat )
1934  {
1935  case MSK_SOL_STA_DUAL_INFEAS_CER:
1936  case MSK_SOL_STA_OPTIMAL:
1937  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
1938  case MSK_SOL_STA_PRIM_INFEAS_CER:
1939  break;
1940  default:
1941  SCIPdebugMessage("MOSEK does not know about feasibility of solutions\n");
1942  break;
1943  }/*lint !e788*/
1944  return FALSE;
1945 }
1946 
1951  SCIP_SDPISOLVER* sdpisolver
1952  )
1953 {
1954  assert( sdpisolver != NULL );
1955  CHECK_IF_SOLVED_BOOL( sdpisolver );
1956 
1957  switch ( sdpisolver->solstat )
1958  {
1959  case MSK_SOL_STA_PRIM_INFEAS_CER:
1960  return TRUE;
1961  case MSK_SOL_STA_OPTIMAL:
1962  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
1963  case MSK_SOL_STA_DUAL_INFEAS_CER:
1964  break;
1965  default:
1966  SCIPdebugMessage("MOSEK does not know about feasibility of solutions\n");
1967  break;
1968  }/*lint !e788*/
1969  return FALSE;
1970 }
1971 
1976  SCIP_SDPISOLVER* sdpisolver
1977  )
1978 {
1979  assert( sdpisolver != NULL );
1980  CHECK_IF_SOLVED_BOOL( sdpisolver );
1981 
1982  switch ( sdpisolver->solstat )
1983  {
1984  case MSK_SOL_STA_OPTIMAL:
1985  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
1986  return TRUE;
1987  case MSK_SOL_STA_DUAL_INFEAS_CER:
1988  case MSK_SOL_STA_PRIM_INFEAS_CER:
1989  break;
1990  default:
1991  SCIPdebugMessage("MOSEK does not know about feasibility of solutions\n");
1992  break;
1993  }/*lint !e788*/
1994  return FALSE;
1995 }
1996 
2001  SCIP_SDPISOLVER* sdpisolver
2002  )
2003 {
2004  assert( sdpisolver != NULL );
2005  CHECK_IF_SOLVED_BOOL( sdpisolver );
2006 
2007  switch ( sdpisolver->solstat )
2008  {
2009  case MSK_SOL_STA_PRIM_INFEAS_CER:
2010  case MSK_SOL_STA_OPTIMAL:
2011  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
2012  case MSK_SOL_STA_DUAL_INFEAS_CER:
2013  break;
2014  default:
2015  SCIPdebugMessage("MOSEK does not know about feasibility of solutions\n");
2016  break;
2017  }/*lint !e788*/
2018  return FALSE;
2019 }
2020 
2025  SCIP_SDPISOLVER* sdpisolver
2026  )
2027 {
2028  assert( sdpisolver != NULL );
2029  CHECK_IF_SOLVED_BOOL( sdpisolver );
2030 
2031  switch ( sdpisolver->solstat )
2032  {
2033  case MSK_SOL_STA_DUAL_INFEAS_CER:
2034  return TRUE;
2035  case MSK_SOL_STA_OPTIMAL:
2036  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
2037  case MSK_SOL_STA_PRIM_INFEAS_CER:
2038  break;
2039  default:
2040  SCIPdebugMessage("MOSEK does not know about feasibility of solutions\n");
2041  break;
2042  }/*lint !e788*/
2043  return FALSE;
2044 }
2045 
2050  SCIP_SDPISOLVER* sdpisolver
2051  )
2052 {
2053  assert( sdpisolver != NULL );
2054  CHECK_IF_SOLVED_BOOL( sdpisolver );
2055 
2056  switch ( sdpisolver->solstat )
2057  {
2058  case MSK_SOL_STA_OPTIMAL:
2059  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
2060  return TRUE;
2061  case MSK_SOL_STA_PRIM_INFEAS_CER:
2062  case MSK_SOL_STA_DUAL_INFEAS_CER:
2063  break;
2064  default:
2065  SCIPdebugMessage("MOSEK does not know about feasibility of solutions\n");
2066  break;
2067  }/*lint !e788*/
2068  return FALSE;
2069 }
2070 
2072 SCIP_Bool SCIPsdpiSolverIsConverged(
2073  SCIP_SDPISOLVER* sdpisolver
2074  )
2075 {
2076  assert( sdpisolver != NULL );
2077 
2078  if ( sdpisolver->timelimit )
2079  return FALSE;
2080 
2081  CHECK_IF_SOLVED_BOOL( sdpisolver );
2082 
2083  /* check if Mosek stalled when it was already acceptable */
2084  if ( sdpisolver->terminationcode == MSK_RES_TRM_STALL )
2085  {
2086  SCIP_Real pobj;
2087  SCIP_Real dobj;
2088  SCIP_Real gapnormalization;
2089 
2090  /* check the solution status */
2091  switch ( sdpisolver->solstat )
2092  {
2093  case MSK_SOL_STA_UNKNOWN:
2094  case MSK_SOL_STA_PRIM_FEAS:
2095  case MSK_SOL_STA_DUAL_FEAS:
2096  return FALSE;
2097  case MSK_SOL_STA_OPTIMAL:
2098  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
2099  case MSK_SOL_STA_PRIM_INFEAS_CER:
2100  case MSK_SOL_STA_DUAL_INFEAS_CER:
2101  /* check duality gap */
2102  MOSEK_CALL_BOOL( MSK_getdualobj(sdpisolver->msktask, MSK_SOL_ITR, &dobj) );
2103  MOSEK_CALL_BOOL( MSK_getprimalobj(sdpisolver->msktask, MSK_SOL_ITR, &pobj) );
2104  /* for the relative gap we divide by max(1.0, min(pobj, dobj)), as this is also done in Mosek */
2105  gapnormalization = dobj > pobj ? (pobj > 1.0 ? pobj : 1.0) : (dobj > 1.0 ? dobj : 1.0);
2106  if ( REALABS((pobj-dobj) / gapnormalization) < sdpisolver->gaptol )
2107  return TRUE;
2108  else
2109  return FALSE;
2110  default:
2111  return FALSE;
2112  }
2113  }
2114 
2115  return sdpisolver->terminationcode == MSK_RES_OK;
2116 }
2117 
2119 SCIP_Bool SCIPsdpiSolverIsObjlimExc(
2120  SCIP_SDPISOLVER* sdpisolver
2121  )
2122 {
2123  assert( sdpisolver != NULL );
2124  CHECK_IF_SOLVED_BOOL( sdpisolver );
2125 
2126  return sdpisolver->terminationcode == MSK_RES_TRM_OBJECTIVE_RANGE;
2127 }
2128 
2130 SCIP_Bool SCIPsdpiSolverIsIterlimExc(
2131  SCIP_SDPISOLVER* sdpisolver
2132  )
2133 {
2134  assert( sdpisolver != NULL );
2135  CHECK_IF_SOLVED_BOOL( sdpisolver );
2136 
2137  return sdpisolver->terminationcode == MSK_RES_TRM_MAX_ITERATIONS;
2138 }
2139 
2141 SCIP_Bool SCIPsdpiSolverIsTimelimExc(
2142  SCIP_SDPISOLVER* sdpisolver
2143  )
2144 {
2145  assert( sdpisolver != NULL );
2146 
2147  if ( sdpisolver->timelimit )
2148  return TRUE;
2149 
2150  if ( ! sdpisolver->solved )
2151  return FALSE;
2152 
2153  return sdpisolver->terminationcode == MSK_RES_TRM_MAX_TIME;
2154 }
2155 
2168  SCIP_SDPISOLVER* sdpisolver
2169  )
2170 {
2171  assert( sdpisolver != NULL );
2172 
2173  if ( ! sdpisolver->solved )
2174  return -1;
2175 
2176  if ( sdpisolver->timelimit )
2177  return 5;
2178 
2179  switch ( sdpisolver->terminationcode )
2180  {
2181  case MSK_RES_OK:
2182  return 0;
2183  case MSK_RES_TRM_MAX_NUM_SETBACKS:
2184  case MSK_RES_TRM_NUMERICAL_PROBLEM:
2185  case MSK_RES_TRM_STALL:
2186  return 2;
2187  case MSK_RES_TRM_OBJECTIVE_RANGE:
2188  return 3;
2189  case MSK_RES_TRM_MAX_ITERATIONS:
2190  return 4;
2191  case MSK_RES_TRM_MAX_TIME:
2192  return 5;
2193  default:
2194  return 7;
2195  }/*lint !e788*/
2196 }
2197 
2199 SCIP_Bool SCIPsdpiSolverIsOptimal(
2200  SCIP_SDPISOLVER* sdpisolver
2201  )
2202 {
2203  assert( sdpisolver != NULL );
2204 
2205  if ( sdpisolver->timelimit )
2206  return FALSE;
2207 
2208  CHECK_IF_SOLVED_BOOL( sdpisolver );
2209 
2210  if ( sdpisolver->terminationcode != MSK_RES_OK )
2211  return FALSE;
2212 
2213  if ( sdpisolver->solstat != MSK_SOL_STA_OPTIMAL )
2214  return FALSE;
2215 
2216  return TRUE;
2217 }
2218 
2222 SCIP_Bool SCIPsdpiSolverIsAcceptable(
2223  SCIP_SDPISOLVER* sdpisolver
2224  )
2225 {
2226  assert( sdpisolver != NULL );
2227 
2228  if ( sdpisolver->timelimit )
2229  return FALSE;
2230 
2231  if ( ! sdpisolver->solved )
2232  return FALSE;
2233 
2234  return SCIPsdpiSolverIsConverged(sdpisolver) && SCIPsdpiSolverFeasibilityKnown(sdpisolver);
2235 }
2236 
2238 SCIP_RETCODE SCIPsdpiSolverIgnoreInstability(
2239  SCIP_SDPISOLVER* sdpisolver,
2240  SCIP_Bool* success
2241  )
2242 {/*lint --e{715}*/
2243  SCIPdebugMessage("Not implemented yet\n");
2244  return SCIP_LPERROR;
2245 }
2246 
2248 SCIP_RETCODE SCIPsdpiSolverGetObjval(
2249  SCIP_SDPISOLVER* sdpisolver,
2250  SCIP_Real* objval
2251  )
2252 {
2253  SCIP_Real* moseksol;
2254 
2255  assert( sdpisolver != NULL );
2256  CHECK_IF_SOLVED( sdpisolver );
2257  assert( objval != NULL );
2258 
2259  /* check for unboundedness */
2260  if ( SCIPsdpiSolverIsDualUnbounded(sdpisolver) || SCIPsdpiSolverIsPrimalInfeasible(sdpisolver) )
2261  {
2262  *objval = -SCIPsdpiSolverInfinity(sdpisolver);
2263  return SCIP_OKAY;
2264  }
2265 
2266  if ( sdpisolver->penalty && ! sdpisolver->feasorig )
2267  {
2268  /* in this case we cannot really trust the solution given by MOSEK, since changes in the value of r much less than epsilon can
2269  * cause huge changes in the objective, so using the objective value given by MOSEK is numerically more stable */
2270  MOSEK_CALL( MSK_getdualobj(sdpisolver->msktask, MSK_SOL_ITR, objval) );
2271 
2272  /* reverse scaling */
2273  *objval *= sdpisolver->objscalefactor;
2274  }
2275  else
2276  {
2277  int v;
2278 
2279  /* since the objective value given by MOSEK sometimes differs slightly from the correct value for the given solution,
2280  * we get the solution from MOSEK and compute the correct objective value */
2281  BMSallocBufferMemoryArray(sdpisolver->bufmem, &moseksol, sdpisolver->penalty ? sdpisolver->nactivevars + 1 : sdpisolver->nactivevars);
2282  MOSEK_CALL( MSK_gety(sdpisolver->msktask, MSK_SOL_ITR, moseksol) );/*lint !e641*/
2283 
2284  *objval = 0.0;
2285  for (v = 0; v < sdpisolver->nactivevars; v++)
2286  *objval += moseksol[v] * sdpisolver->objcoefs[v];
2287 
2288  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &moseksol);
2289  }
2290 
2291  /* as we didn't add the fixed (lb = ub) variables to MOSEK, we have to add their contributions to the objective as well */
2292  *objval += sdpisolver->fixedvarsobjcontr;
2293 
2294  return SCIP_OKAY;
2295 }
2296 
2301 SCIP_RETCODE SCIPsdpiSolverGetSol(
2302  SCIP_SDPISOLVER* sdpisolver,
2303  SCIP_Real* objval,
2304  SCIP_Real* dualsol,
2305  int* dualsollength
2307  )
2308 {
2309  int v;
2310  SCIP_Real* moseksol;
2311 
2312  assert( sdpisolver != NULL );
2313  CHECK_IF_SOLVED( sdpisolver );
2314  assert( dualsollength != NULL );
2315 
2316  if ( *dualsollength > 0 )
2317  {
2318  assert( dualsol != NULL );
2319  if ( *dualsollength < sdpisolver->nvars )
2320  {
2321  SCIPdebugMessage("The given array in SCIPsdpiSolverGetSol only had length %d, but %d was needed", *dualsollength, sdpisolver->nvars);
2322  *dualsollength = sdpisolver->nvars;
2323 
2324  return SCIP_OKAY;
2325  }
2326 
2327  BMSallocBufferMemoryArray(sdpisolver->bufmem, &moseksol, sdpisolver->penalty ? sdpisolver->nactivevars + 1 : sdpisolver->nactivevars);
2328 
2329  MOSEK_CALL( MSK_gety(sdpisolver->msktask, MSK_SOL_ITR, moseksol) );/*lint !e641*/
2330 
2331  /* 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) */
2332  for (v = 0; v < sdpisolver->nvars; v++)
2333  {
2334  if ( sdpisolver->inputtomosekmapper[v] >= 0 )
2335  dualsol[v] = moseksol[sdpisolver->inputtomosekmapper[v]];
2336  else
2337  {
2338  /* this is the value that was saved when inserting, as this variable has lb=ub */
2339  assert( -sdpisolver->inputtomosekmapper[v] <= sdpisolver->nvars - sdpisolver->nactivevars );
2340  dualsol[v] = sdpisolver->fixedvarsval[(-1 * sdpisolver->inputtomosekmapper[v]) - 1]; /*lint !e679*/ /* -1 because we wanted strictly negative vals */
2341  }
2342  }
2343 
2344  /* if both solution and objective should be printed, we can use the solution to compute the objective */
2345  if ( objval != NULL )
2346  {
2347  if ( sdpisolver->penalty && ! sdpisolver->feasorig )
2348  {
2349  /* in this case we cannot really trust the solution given by MOSEK, since changes in the value of r much less than epsilon can
2350  * cause huge changes in the objective, so using the objective value given by MOSEK is numerically more stable */
2351  MOSEK_CALL( MSK_getdualobj(sdpisolver->msktask, MSK_SOL_ITR, objval) );
2352 
2353  /* reverse scaling */
2354  *objval *= sdpisolver->objscalefactor;
2355  }
2356  else
2357  {
2358  /* since the objective value given by MOSEK sometimes differs slightly from the correct value for the given solution,
2359  * we get the solution from MOSEK and compute the correct objective value */
2360  *objval = 0.0;
2361  for (v = 0; v < sdpisolver->nactivevars; v++)
2362  *objval += moseksol[v] * sdpisolver->objcoefs[v];
2363  }
2364 
2365  /* as we didn't add the fixed (lb = ub) variables to MOSEK, we have to add their contributions to the objective as well */
2366  *objval += sdpisolver->fixedvarsobjcontr;
2367  }
2368 
2369  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &moseksol);
2370  }
2371  else if ( objval != NULL )
2372  {
2373  SCIP_CALL( SCIPsdpiSolverGetObjval(sdpisolver, objval) );
2374  }
2375 
2376  return SCIP_OKAY;
2377 }
2378 
2381  SCIP_SDPISOLVER* sdpisolver,
2382  int nblocks,
2383  int* startXnblocknonz
2385  )
2386 { /*lint --e{715}*/
2387  SCIPdebugMessage("Not implemented yet\n");
2388 
2389  return SCIP_PLUGINNOTFOUND;
2390 }
2391 
2399 SCIP_RETCODE SCIPsdpiSolverGetPreoptimalSol(
2400  SCIP_SDPISOLVER* sdpisolver,
2401  SCIP_Bool* success,
2402  SCIP_Real* dualsol,
2403  int* dualsollength,
2405  int nblocks,
2406  int* startXnblocknonz,
2408  int** startXrow,
2409  int** startXcol,
2410  SCIP_Real** startXval
2411  )
2412 {/*lint !e1784*/
2413  SCIPdebugMessage("Not implemented yet\n");
2414  return SCIP_LPERROR;
2415 }/*lint !e715*/
2416 
2425  SCIP_SDPISOLVER* sdpisolver,
2426  SCIP_Real* lbvars,
2427  SCIP_Real* ubvars,
2428  int* arraylength
2430  )
2431 {
2432  SCIP_Real* primalvars;
2433  int nprimalvars;
2434  int i;
2435 
2436  assert( sdpisolver != NULL );
2437  CHECK_IF_SOLVED( sdpisolver );
2438  assert( arraylength != NULL );
2439  assert( lbvars != NULL );
2440  assert( ubvars != NULL );
2441 
2442  /* check if the arrays are long enough */
2443  if ( *arraylength < sdpisolver->nvars )
2444  {
2445  *arraylength = sdpisolver->nvars;
2446  SCIPdebugMessage("Insufficient length of array in SCIPsdpiSolverGetPrimalBoundVars (gave %d, needed %d)\n", *arraylength, sdpisolver->nvars);
2447  return SCIP_OKAY;
2448  }
2449 
2450  /* initialize the return-arrays with zero */
2451  for (i = 0; i < sdpisolver->nvars; i++)
2452  {
2453  lbvars[i] = 0.0;
2454  ubvars[i] = 0.0;
2455  }
2456 
2457  /* get number of primal variables in MOSEK */
2458  MOSEK_CALL( MSK_getnumvar(sdpisolver->msktask, &nprimalvars) );/*lint !e641*/
2459 
2460  BMSallocBufferMemoryArray(sdpisolver->bufmem, &primalvars, nprimalvars);
2461 
2462  MOSEK_CALL( MSK_getxx(sdpisolver->msktask, MSK_SOL_ITR, primalvars) );/*lint !e641*/
2463 
2464  /* iterate over all variable bounds and insert the corresponding primal variables in the right positions of the return-arrays */
2465  assert( sdpisolver->nvarbounds <= 2 * sdpisolver->nvars );
2466 
2467  for (i = 0; i < sdpisolver->nvarbounds; i++)
2468  {
2469  if ( sdpisolver->varboundpos[i] < 0 )
2470  {
2471  /* this is a lower bound */
2472 
2473  /* the last nvarbounds entries correspond to the varbounds; we need to unscale these values */
2474  lbvars[sdpisolver->mosektoinputmapper[-1 * sdpisolver->varboundpos[i] -1]] = primalvars[nprimalvars - sdpisolver->nvarbounds + i] * sdpisolver->objscalefactor;
2475  }
2476  else
2477  {
2478  /* this is an upper bound */
2479  assert( sdpisolver->varboundpos[i] > 0 );
2480 
2481  /* the last nvarbounds entries correspond to the varbounds; we need to unscale these values */
2482  ubvars[sdpisolver->mosektoinputmapper[sdpisolver->varboundpos[i] - 1]] = primalvars[nprimalvars - sdpisolver->nvarbounds + i] * sdpisolver->objscalefactor;
2483  }
2484  }
2485 
2486  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &primalvars);
2487 
2488  return SCIP_OKAY;
2489 }
2490 
2492 SCIP_RETCODE SCIPsdpiSolverGetPrimalNonzeros(
2493  SCIP_SDPISOLVER* sdpisolver,
2494  int nblocks,
2495  int* startXnblocknonz
2496  )
2497 {/*lint --e{715}*/
2498  SCIPdebugMessage("Not implemented yet\n");
2499  return SCIP_LPERROR;
2500 }
2501 
2508 SCIP_RETCODE SCIPsdpiSolverGetPrimalMatrix(
2509  SCIP_SDPISOLVER* sdpisolver,
2510  int nblocks,
2511  int* startXnblocknonz,
2513  int** startXrow,
2514  int** startXcol,
2515  SCIP_Real** startXval
2516  )
2517 {/*lint --e{715}*/
2518  SCIPdebugMessage("Not implemented yet\n");
2519  return SCIP_LPERROR;
2520 }
2521 
2524  SCIP_SDPISOLVER* sdpisolver
2525  )
2526 {/*lint --e{715}*/
2527  SCIPdebugMessage("Not implemented yet\n");
2528  return SCIP_INVALID;
2529 }
2530 
2532 SCIP_RETCODE SCIPsdpiSolverGetTime(
2533  SCIP_SDPISOLVER* sdpisolver,
2534  SCIP_Real* opttime
2535  )
2536 {
2537  assert( sdpisolver != NULL );
2538  assert( opttime != NULL );
2539 
2540  *opttime = sdpisolver->opttime;
2541 
2542  return SCIP_OKAY;
2543 }
2544 
2546 SCIP_RETCODE SCIPsdpiSolverGetIterations(
2547  SCIP_SDPISOLVER* sdpisolver,
2548  int* iterations
2549  )
2550 {
2551  assert( sdpisolver != NULL );
2552  assert( iterations != NULL );
2553 
2554  *iterations = sdpisolver->niterations;
2555 
2556  return SCIP_OKAY;
2557 }
2558 
2560 SCIP_RETCODE SCIPsdpiSolverGetSdpCalls(
2561  SCIP_SDPISOLVER* sdpisolver,
2562  int* calls
2563  )
2564 {/*lint --e{715,1784}*/
2565  assert( sdpisolver != NULL );
2566  assert( calls != NULL );
2567 
2568  *calls = sdpisolver->nsdpcalls;
2569 
2570  return SCIP_OKAY;
2571 }
2572 
2574 SCIP_RETCODE SCIPsdpiSolverSettingsUsed(
2575  SCIP_SDPISOLVER* sdpisolver,
2577  )
2578 {
2579  assert( sdpisolver != NULL );
2580  assert( usedsetting != NULL );
2581 
2582  if ( ! SCIPsdpiSolverIsAcceptable(sdpisolver) )
2583  *usedsetting = SCIP_SDPSOLVERSETTING_UNSOLVED;
2584  else if ( sdpisolver->penalty )
2585  *usedsetting = SCIP_SDPSOLVERSETTING_PENALTY;
2586  else
2587  *usedsetting = SCIP_SDPSOLVERSETTING_FAST;
2588 
2589  return SCIP_OKAY;
2590 }
2591 
2597 /*
2598  * Numerical Methods
2599  */
2600 
2605 SCIP_Real SCIPsdpiSolverInfinity(
2606  SCIP_SDPISOLVER* sdpisolver
2607  )
2608 {/*lint --e{715}*/
2609  return 1.0e16;
2610 }
2611 
2613 SCIP_Bool SCIPsdpiSolverIsInfinity(
2614  SCIP_SDPISOLVER* sdpisolver,
2615  SCIP_Real val
2616  )
2617 {
2618  return ((val <= -SCIPsdpiSolverInfinity(sdpisolver)) || (val >= SCIPsdpiSolverInfinity(sdpisolver)));
2619 }
2620 
2622 SCIP_RETCODE SCIPsdpiSolverGetRealpar(
2623  SCIP_SDPISOLVER* sdpisolver,
2625  SCIP_Real* dval
2626  )
2627 {
2628  assert( sdpisolver != NULL );
2629  assert( dval != NULL );
2630 
2631  switch( type )
2632  {
2633  case SCIP_SDPPAR_EPSILON:
2634  *dval = sdpisolver->epsilon;
2635  break;
2636  case SCIP_SDPPAR_GAPTOL:
2637  *dval = sdpisolver->gaptol;
2638  break;
2639  case SCIP_SDPPAR_FEASTOL:
2640  *dval = sdpisolver->feastol;
2641  break;
2643  *dval = sdpisolver->sdpsolverfeastol;
2644  break;
2645  case SCIP_SDPPAR_OBJLIMIT:
2646  *dval = sdpisolver->objlimit;
2647  break;
2648  default:
2649  return SCIP_PARAMETERUNKNOWN;
2650  }/*lint !e788*/
2651 
2652  return SCIP_OKAY;
2653 }
2654 
2656 SCIP_RETCODE SCIPsdpiSolverSetRealpar(
2657  SCIP_SDPISOLVER* sdpisolver,
2659  SCIP_Real dval
2660  )
2661 {
2662  assert( sdpisolver != NULL );
2663 
2664  switch( type )
2665  {
2666  case SCIP_SDPPAR_EPSILON:
2667  sdpisolver->epsilon = dval;
2668  SCIPdebugMessage("Setting sdpisolver epsilon to %g.\n", dval);
2669  break;
2670  case SCIP_SDPPAR_GAPTOL:
2671  sdpisolver->gaptol = dval;
2672  SCIPdebugMessage("Setting sdpisolver gaptol to %g.\n", dval);
2673  break;
2674  case SCIP_SDPPAR_FEASTOL:
2675  sdpisolver->feastol = dval;
2676  SCIPdebugMessage("Setting sdpisolver feastol to %g.\n", dval);
2677  break;
2679  sdpisolver->sdpsolverfeastol = dval;
2680  SCIPdebugMessage("Setting sdpisolver sdpsolverfeastol to %g.\n", dval);
2681  break;
2682  case SCIP_SDPPAR_OBJLIMIT:
2683  SCIPdebugMessage("Setting sdpisolver objlimit to %g.\n", dval);
2684  sdpisolver->objlimit = dval;
2685  break;
2686  default:
2687  return SCIP_PARAMETERUNKNOWN;
2688  }/*lint !e788*/
2689 
2690  return SCIP_OKAY;
2691 }
2692 
2694 SCIP_RETCODE SCIPsdpiSolverGetIntpar(
2695  SCIP_SDPISOLVER* sdpisolver,
2697  int* ival
2698  )
2699 {
2700  assert( sdpisolver != NULL );
2701 
2702  switch( type )
2703  {
2704  case SCIP_SDPPAR_SDPINFO:
2705  *ival = (int) sdpisolver->sdpinfo;
2706  SCIPdebugMessage("Getting sdpisolver information output (%d).\n", *ival);
2707  break;
2708  case SCIP_SDPPAR_NTHREADS:
2709  *ival = sdpisolver->nthreads;
2710  SCIPdebugMessage("Getting sdpisolver number of threads: %d.\n", *ival);
2711  break;
2713  *ival = (int) sdpisolver->usepresolving;
2714  SCIPdebugMessage("Getting usepresolving (%d).\n", *ival);
2715  break;
2717  *ival = (int) sdpisolver->usescaling;
2718  SCIPdebugMessage("Getting usescaling (%d).\n", *ival);
2719  break;
2720  case SCIP_SDPPAR_SCALEOBJ:
2721  *ival = (int) sdpisolver->scaleobj;
2722  SCIPdebugMessage("Getting scaleobj (%d).\n", *ival);
2723  break;
2724  default:
2725  return SCIP_PARAMETERUNKNOWN;
2726  }/*lint !e788*/
2727 
2728  return SCIP_OKAY;
2729 }
2730 
2732 SCIP_RETCODE SCIPsdpiSolverSetIntpar(
2733  SCIP_SDPISOLVER* sdpisolver,
2735  int ival
2736  )
2737 {
2738  assert( sdpisolver != NULL );
2739 
2740  switch( type )
2741  {
2742  case SCIP_SDPPAR_NTHREADS:
2743  sdpisolver->nthreads = ival;
2744  SCIPdebugMessage("Setting sdpisolver number of threads to %d.\n", ival);
2745  break;
2746  case SCIP_SDPPAR_SDPINFO:
2747  assert( 0 <= ival && ival <= 1 );
2748  sdpisolver->sdpinfo = (SCIP_Bool) ival;
2749  SCIPdebugMessage("Setting sdpisolver information output (%d).\n", ival);
2750  break;
2752  assert( 0 <= ival && ival <= 1 );
2753  sdpisolver->usepresolving = (SCIP_Bool) ival;
2754  SCIPdebugMessage("Setting usepresolving (%d).\n", ival);
2755  break;
2757  assert( 0 <= ival && ival <= 1 );
2758  sdpisolver->usescaling = (SCIP_Bool) ival;
2759  SCIPdebugMessage("Setting usescaling (%d).\n", ival);
2760  break;
2761  case SCIP_SDPPAR_SCALEOBJ:
2762  assert( 0 <= ival && ival <= 1 );
2763  sdpisolver->scaleobj = (SCIP_Bool) ival;
2764  SCIPdebugMessage("Setting scaleobj (%d).\n", ival);
2765  break;
2766  default:
2767  return SCIP_PARAMETERUNKNOWN;
2768  }/*lint !e788*/
2769 
2770  return SCIP_OKAY;
2771 }
2772 
2774 SCIP_RETCODE SCIPsdpiSolverComputeLambdastar(
2775  SCIP_SDPISOLVER* sdpisolver,
2776  SCIP_Real maxguess
2777  )
2778 {/*lint --e{715}*/
2779  SCIPdebugMessage("Lambdastar parameter not used by MOSEK"); /* this parameter is only used by SDPA */
2780 
2781  return SCIP_OKAY;
2782 }
2783 
2786  SCIP_SDPISOLVER* sdpisolver,
2787  SCIP_Real maxcoeff,
2788  SCIP_Real* penaltyparam
2789  )
2790 {/*lint --e{1784}*/
2791  SCIP_Real compval;
2792 
2793  assert( sdpisolver != NULL );
2794  assert( penaltyparam != NULL );
2795 
2796  compval = PENALTYPARAM_FACTOR * maxcoeff;
2797 
2798  if ( compval < MIN_PENALTYPARAM )
2799  {
2800  SCIPdebugMessage("Setting penaltyparameter to %g.\n", MIN_PENALTYPARAM);
2801  *penaltyparam = MIN_PENALTYPARAM;
2802  }
2803  else if ( compval > MAX_PENALTYPARAM )
2804  {
2805  SCIPdebugMessage("Setting penaltyparameter to %g.\n", MAX_PENALTYPARAM);
2806  *penaltyparam = MAX_PENALTYPARAM;
2807  }
2808  else
2809  {
2810  SCIPdebugMessage("Setting penaltyparameter to %g.\n", compval);
2811  *penaltyparam = compval;
2812  }
2813 
2814  return SCIP_OKAY;
2815 }
2816 
2819  SCIP_SDPISOLVER* sdpisolver,
2820  SCIP_Real penaltyparam,
2821  SCIP_Real* maxpenaltyparam
2822  )
2823 {/*lint --e{1784}*/
2824  SCIP_Real compval;
2825 
2826  assert( sdpisolver != NULL );
2827  assert( maxpenaltyparam != NULL );
2828 
2829  compval = penaltyparam * MAXPENALTYPARAM_FACTOR;
2830 
2831  if ( compval < MAX_MAXPENALTYPARAM )
2832  {
2833  *maxpenaltyparam = compval;
2834  SCIPdebugMessage("Setting maximum penaltyparameter to %g.\n", compval);
2835  }
2836  else
2837  {
2838  *maxpenaltyparam = MAX_MAXPENALTYPARAM;
2839  SCIPdebugMessage("Setting penaltyparameter to %g.\n", MAX_MAXPENALTYPARAM);
2840  }
2841 
2842  return SCIP_OKAY;
2843 }
2844 
2850 /*
2851  * File Interface Methods
2852  */
2853 
2858 SCIP_RETCODE SCIPsdpiSolverReadSDP(
2859  SCIP_SDPISOLVER* sdpisolver,
2860  const char* fname
2861  )
2862 {/*lint --e{715}*/
2863  SCIPdebugMessage("Not implemented yet\n");
2864  return SCIP_LPERROR;
2865 }
2866 
2868 SCIP_RETCODE SCIPsdpiSolverWriteSDP(
2869  SCIP_SDPISOLVER* sdpisolver,
2870  const char* fname
2871  )
2872 {
2873  assert( sdpisolver != NULL );
2874  assert( fname != NULL );
2875 
2876  MOSEK_CALL( MSK_writedata(sdpisolver->msktask, fname) );/*lint !e641*/
2877 
2878  return SCIP_OKAY;
2879 }
2880 
SCIP_RETCODE SCIPsdpiSolverGetTime(SCIP_SDPISOLVER *sdpisolver, SCIP_Real *opttime)
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)
SCIP_RETCODE SCIPsdpSolcheckerCheckAndGetViolDual(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, SCIP_Real *lplhs, SCIP_Real *lprhs, int lpnnonz, int *lprow, int *lpcol, SCIP_Real *lpval, SCIP_Real *solvector, SCIP_Real feastol, SCIP_Real epsilon, SCIP_Real *maxabsviolbnds, SCIP_Real *sumabsviolbnds, SCIP_Real *maxabsviolcons, SCIP_Real *sumabsviolcons, SCIP_Real *maxabsviolsdp, SCIP_Real *sumabsviolsdp, SCIP_Bool *infeasible)
enum SCIP_SDPSolverSetting SCIP_SDPSOLVERSETTING
Definition: type_sdpi.h:83
SCIP_RETCODE SCIPsdpiSolverResetCounter(SCIP_SDPISOLVER *sdpisolver)
SCIP_Bool SCIPsdpiSolverIsDualFeasible(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, SCIP_Real *lplhs, SCIP_Real *lprhs, int lpnnonz, int *lprow, int *lpcol, SCIP_Real *lpval, SCIP_Real *solvector, SCIP_Real feastol, SCIP_Real epsilon, SCIP_Bool *infeasible)
Definition: sdpsolchecker.c:62
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
static int calcGrowSize(int initsize, int num)
#define MOSEK_CALL_BOOL(x)
SCIP_Bool SCIPsdpiSolverIsPrimalUnbounded(SCIP_SDPISOLVER *sdpisolver)
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 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)
#define INFEASFEASTOLCHANGE
SCIP_RETCODE SCIPsdpiSolverGetSol(SCIP_SDPISOLVER *sdpisolver, SCIP_Real *objval, SCIP_Real *dualsol, int *dualsollength)
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, SCIP_Real *lplhs, SCIP_Real *lprhs, 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, SDPI_CLOCK *usedsdpitime, SCIP_Bool *feasorig, SCIP_Bool *penaltybound)
SCIP_RETCODE SCIPsdpiSolverGetObjval(SCIP_SDPISOLVER *sdpisolver, SCIP_Real *objval)
#define BMS_CALL(x)
checks a given SDP solution for feasibility
const char * SCIPsdpiSolverGetSolverDesc(void)
SCIP_RETCODE SCIPsdpiSolverGetPreoptimalPrimalNonzeros(SCIP_SDPISOLVER *sdpisolver, int nblocks, int *startXnblocknonz)
static SCIP_RETCODE ensureMappingDataMemory(SCIP_SDPISOLVER *sdpisolver, int nvars)
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_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, SCIP_Real *lplhs, SCIP_Real *lprhs, 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, SDPI_CLOCK *usedsdpitime)
SCIP_Bool SCIPsdpiSolverIsIterlimExc(SCIP_SDPISOLVER *sdpisolver)
#define MOSEK_CALLM(x)
SCIP_Real SDPIclockGetTime(SDPI_CLOCK *clck)
Definition: sdpiclock.c:250
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)
methods for clocks and timing
SCIP_Bool SCIPsdpiSolverIsAcceptable(SCIP_SDPISOLVER *sdpisolver)
struct SCIP_SDPiSolver SCIP_SDPISOLVER
Definition: sdpisolver.h:71
SCIP_RETCODE SCIPsdpiSolverSetRealpar(SCIP_SDPISOLVER *sdpisolver, SCIP_SDPPARAM type, SCIP_Real dval)
SCIP_RETCODE SCIPsdpiSolverGetIntpar(SCIP_SDPISOLVER *sdpisolver, SCIP_SDPPARAM type, int *ival)
static void MSKAPI printstr(void *handler, MSKCONST char str[])
#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)
char solvername[SCIP_MAXSTRLEN]
enum SCIP_SDPParam SCIP_SDPPARAM
Definition: type_sdpi.h:72
SCIP_RETCODE SCIPsdpSolcheckerCheckAndGetViolPrimal(BMS_BUFMEM *bufmem, int nvars, SCIP_Real *obj, SCIP_Real *lb, SCIP_Real *ub, int *inputtomosekmapper, 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, SCIP_Real *lplhs, SCIP_Real *lprhs, int lpnnonz, int *lprow, int *lpcol, SCIP_Real *lpval, SCIP_Real *solvector, SCIP_Real **solmatrices, SCIP_Real feastol, SCIP_Real epsilon, SCIP_Real *maxabsviolbnds, SCIP_Real *sumabsviolbnds, SCIP_Real *maxabsviolcons, SCIP_Real *sumabsviolcons, SCIP_Real *maxabsviolsdp, SCIP_Real *sumabsviolsdp, SCIP_Bool *infeasible)
SCIP_Bool SCIPsdpiSolverIsDualUnbounded(SCIP_SDPISOLVER *sdpisolver)
SCIP_Bool SCIPsdpiSolverIsTimelimExc(SCIP_SDPISOLVER *sdpisolver)
SCIP_Bool SCIPsdpiSolverDoesWarmstartNeedPrimal(void)
SCIP_Bool SCIPsdpiSolverFeasibilityKnown(SCIP_SDPISOLVER *sdpisolver)
#define MAX_PENALTYPARAM