SCIP-SDP  3.1.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
sdpisolver_dsdp.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of SCIPSDP - a solving framework for mixed-integer */
4 /* semidefinite programs based on SCIP. */
5 /* */
6 /* Copyright (C) 2011-2013 Discrete Optimization, TU Darmstadt */
7 /* EDOM, FAU Erlangen-Nürnberg */
8 /* 2014-2018 Discrete Optimization, TU Darmstadt */
9 /* */
10 /* */
11 /* This program is free software; you can redistribute it and/or */
12 /* modify it under the terms of the GNU Lesser General Public License */
13 /* as published by the Free Software Foundation; either version 3 */
14 /* of the License, or (at your option) any later version. */
15 /* */
16 /* This program is distributed in the hope that it will be useful, */
17 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
18 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
19 /* GNU Lesser General Public License for more details. */
20 /* */
21 /* You should have received a copy of the GNU Lesser General Public License */
22 /* along with this program; if not, write to the Free Software */
23 /* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.*/
24 /* */
25 /* */
26 /* Based on SCIP - Solving Constraint Integer Programs */
27 /* Copyright (C) 2002-2018 Zuse Institute Berlin */
28 /* SCIP is distributed under the terms of the SCIP Academic Licence, */
29 /* see file COPYING in the SCIP distribution. */
30 /* */
31 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
32 
33 /*#define SCIP_DEBUG*/
34 /*#define SCIP_MORE_DEBUG*/
35 
41 #include <assert.h>
42 #include <sys/time.h>
43 
44 #include "sdpi/sdpisolver.h"
45 
46 /* turn off warning for DSDSP */
47 #pragma GCC diagnostic ignored "-Wstrict-prototypes"
48 #include "dsdp5.h" /* for DSDPUsePenalty, etc */
49 #pragma GCC diagnostic warning "-Wstrict-prototypes"
50 
51 
52 #include "blockmemshell/memory.h" /* for memory allocation */
53 #include "scip/def.h" /* for SCIP_Real, _Bool, ... */
54 #include "scip/pub_misc.h" /* for sorting */
55 #include "sdpi/sdpsolchecker.h" /* to check solution with regards to feasibility tolerance */
56 #include "scip/pub_message.h" /* for debug and error message */
57 
58 /* turn off lint warnings for whole file: */
59 /*lint --e{788,818}*/
60 
61 #define PENALTYBOUNDTOL 1E-3
64 #define MIN_PENALTYPARAM 1e5
65 #define MAX_PENALTYPARAM 1e12
66 #define PENALTYPARAM_FACTOR 1e4
67 #define MAX_MAXPENALTYPARAM 1e15
68 #define MAXPENALTYPARAM_FACTOR 1e6
69 #define INFEASFEASTOLCHANGE 0.1
70 #define INFEASMINFEASTOL 1E-9
73 #define DSDP_CALL(x) do \
74  { \
75  int _dsdperrorcode_; \
76  if ( (_dsdperrorcode_ = (x)) != 0 ) \
77  { \
78  SCIPerrorMessage("DSDP-Error <%d> in function call.\n", _dsdperrorcode_); \
79  return SCIP_LPERROR; \
80  } \
81  } \
82  while( FALSE )
83 
85 #define DSDP_CALL_BOOL(x) do \
86  { \
87  int _dsdperrorcode_; \
88  if ( (_dsdperrorcode_ = (x)) != 0 ) \
89  { \
90  SCIPerrorMessage("DSDP-Error <%d> in function call.\n", _dsdperrorcode_); \
91  return FALSE; \
92  } \
93  } \
94  while( FALSE )
95 
97 #define DSDP_CALLM(x) do \
98  { \
99  int _dsdperrorcode_; \
100  if ( (_dsdperrorcode_ = (x)) != 0 ) \
101  { \
102  SCIPerrorMessage("DSDP-Error <%d> in function call.\n", _dsdperrorcode_); \
103  return SCIP_NOMEMORY; \
104  } \
105  } \
106  while( FALSE )
107 
109 #define BMS_CALL(x) do \
110  { \
111  if( NULL == (x) ) \
112  { \
113  SCIPerrorMessage("No memory in function call.\n"); \
114  return SCIP_NOMEMORY; \
115  } \
116  } \
117  while( FALSE )
118 
120 #define TIMEOFDAY_CALL(x) do \
121  { \
122  int _errorcode_; \
123  if ( (_errorcode_ = (x)) != 0 ) \
124  { \
125  SCIPerrorMessage("Error in gettimeofday! \n"); \
126  return SCIP_ERROR; \
127  } \
128  } \
129  while( FALSE )
130 
132 #define CHECK_IF_SOLVED(sdpisolver) do \
133  { \
134  if (!(sdpisolver->solved)) \
135  { \
136  SCIPerrorMessage("Tried to access solution information for SDP %d ahead of solving!\n", sdpisolver->sdpcounter); \
137  return SCIP_LPERROR; \
138  } \
139  } \
140  while( FALSE )
141 
143 #define CHECK_IF_SOLVED_BOOL(sdpisolver) do \
144  { \
145  if (!(sdpisolver->solved)) \
146  { \
147  SCIPerrorMessage("Tried to access solution information for SDP %d ahead of solving!\n", sdpisolver->sdpcounter); \
148  return FALSE; \
149  } \
150  } \
151  while( FALSE )
152 
153 
155 struct SCIP_SDPiSolver
156 {
157  SCIP_MESSAGEHDLR* messagehdlr;
158  BMS_BLKMEM* blkmem;
159  BMS_BUFMEM* bufmem;
160  DSDP dsdp;
161  SDPCone sdpcone;
162  LPCone lpcone;
163  BCone bcone;
164  int nvars;
165  int nactivevars;
166  int* inputtodsdpmapper;
169  int* dsdptoinputmapper;
170  SCIP_Real* fixedvarsval;
171  SCIP_Real fixedvarsobjcontr;
172  SCIP_Real* objcoefs;
173  SCIP_Bool solved;
174  int sdpcounter;
175  SCIP_Real epsilon;
176  SCIP_Real gaptol;
177  SCIP_Real feastol;
178  SCIP_Real sdpsolverfeastol;
179  SCIP_Real penaltyparam;
180  SCIP_Real objlimit;
181  SCIP_Bool sdpinfo;
182  SCIP_Bool penalty;
183  SCIP_Bool penaltyworbound;
184  SCIP_Bool feasorig;
186  SCIP_SDPSOLVERSETTING usedsetting;
187  SCIP_Bool timelimit;
188  SCIP_Bool timelimitinitial;
189  int niterations;
190  int nsdpcalls;
191  SCIP_Real* preoptimalsol;
192  SCIP_Bool preoptimalsolexists;
193  SCIP_Real preoptimalgap;
194 };
195 
197 typedef struct Timings
198 {
199  struct timeval starttime;
200  SCIP_Real timelimit;
201  SCIP_Bool stopped;
202 } Timings;
203 
204 
205 /*
206  * Local Functions
207  */
208 
212 static
214  int i,
215  int j
216  )
217 {
218  assert( j >= 0 );
219  assert( i >= j );
220 
221  return i*(i+1)/2 + j;
222 }
223 
224 #ifndef NDEBUG
225 
226 static
227 SCIP_Bool isFixed(
228  SCIP_SDPISOLVER* sdpisolver,
229  SCIP_Real lb,
230  SCIP_Real ub
231  )
232 {
233  assert( lb < ub + sdpisolver->feastol );
234 
235  return (ub-lb <= sdpisolver->epsilon);
236 }
237 #else
238 #define isFixed(sdpisolver,lb,ub) (ub-lb <= sdpisolver->epsilon)
239 #endif
240 
242 static
243 void sortColRow(
244  int* row,
245  int* col,
246  SCIP_Real* val,
247  int length
248  )
249 {
250  int firstentry;
251  int nextentry = 0;
252 
253  /* first sort by col indices */
254  SCIPsortIntIntReal(col, row, val, length);
255 
256  /* for those with identical col-indices now sort by non-decreasing row-index, first find all entries with the same col-index */
257  while (nextentry < length)
258  {
259  firstentry = nextentry; /* the next col starts where the last one ended */
260 
261  while (nextentry < length && col[nextentry] == col[firstentry]) /* as long as the row still matches, increase nextentry */
262  ++nextentry;
263 
264  /* now sort all entries between firstentry and nextentry-1 by their row-indices */
265  SCIPsortIntReal(row + firstentry, val + firstentry, nextentry - firstentry);
266  }
267 }
268 
270 static
272  DSDP dsdp,
273  void* ctx
274  )
275 {
276  Timings* timings;
277  struct timeval currenttime;
278  SCIP_Real startseconds;
279  SCIP_Real currentseconds;
280  SCIP_Real elapsedtime;
281 
282  assert( dsdp != NULL );
283  assert( ctx != NULL );
284 
285  timings = (Timings*) ctx;
286 
287  startseconds = (SCIP_Real) (timings->starttime).tv_sec + (SCIP_Real) (timings->starttime).tv_usec / 1e6;
288 
289  TIMEOFDAY_CALL( gettimeofday(&currenttime, NULL) );/*lint !e438, !e550, !e641 */
290  currentseconds = (SCIP_Real) currenttime.tv_sec + (SCIP_Real) currenttime.tv_usec / 1e6;
291 
292  elapsedtime = currentseconds - startseconds;
293 
294  if ( elapsedtime > timings->timelimit )
295  {
296  DSDP_CALL( DSDPSetConvergenceFlag(dsdp, DSDP_USER_TERMINATION) );/*lint !e641 */
297  timings->stopped = TRUE;
298  SCIPdebugMessage("Time limit reached! Stopping DSDP.\n");
299  }
300 
301  return 0;
302 }
303 
305 static
307  DSDP dsdp,
308  void* ctx
309  )
310 {
311  SCIP_Real absgap;
312  SCIP_Real relgap;
313  SCIP_Real pobj;
314  SCIP_Real dobj;
315  SCIP_Real r;
316 
317  /* we only need to set the preoptimal solution once and we do not save it if the penalty formulation was used (in that case we won't warmstart
318  * anyways and, most importantly, if solving without bound on r, we added another variable, so the memory would not be enough)
319  */
320  if ( ((SCIP_SDPISOLVER*) ctx)->preoptimalsolexists || ((SCIP_SDPISOLVER*) ctx)->penalty || ((SCIP_SDPISOLVER*) ctx)->penaltyworbound )
321  return 0;
322 
323  DSDP_CALL( DSDPGetPPObjective(dsdp,&pobj) );
324  DSDP_CALL( DSDPGetDDObjective(dsdp,&dobj) );
325  DSDP_CALL( DSDPGetDualityGap(dsdp,&absgap) );
326 
327  relgap = absgap / (1.0 + (REALABS(dobj)/2) + (REALABS(pobj)/2) ); /* compare dsdpconverge.c */
328 
329  /* check feasibility through penalty variable r */
330  DSDP_CALL( DSDPGetR(dsdp,&r) );
331 
332  if ( r < ((SCIP_SDPISOLVER*) ctx)->feastol && relgap < ((SCIP_SDPISOLVER*) ctx)->preoptimalgap )
333  {
334  DSDP_CALL( DSDPGetY(dsdp, ((SCIP_SDPISOLVER*) ctx)->preoptimalsol, ((SCIP_SDPISOLVER*) ctx)->nactivevars) );
335  ((SCIP_SDPISOLVER*) ctx)->preoptimalsolexists = TRUE;
336  SCIPdebugMessage("penalty variable %f, gap %f -> saving preoptimal solution\n", r, relgap);
337  }
338 
339  return 0;
340 }
341 
342 
343 /*
344  * Miscellaneous Methods
345  */
346 
352 const char* SCIPsdpiSolverGetSolverName(
353  void
354  )
355 {
356  return "DSDP"; /* getting the version is not supported in DSDP */
357 }
358 
360 const char* SCIPsdpiSolverGetSolverDesc(
361  void
362  )
363 {
364  return "Dual-Scaling Interior Point SDP-Solver by S. Benson, Y. Ye, and X. Zhang (http://www.mcs.anl.gov/hs/software/DSDP/)";
365 }
366 
374  SCIP_SDPISOLVER* sdpisolver
375  )
376 {
377  assert( sdpisolver != NULL );
378  return (void*) sdpisolver->dsdp;
379 }
380 
383  void
384  )
385 {
386  return 1E-6;
387 }
388 
389 
392  void
393  )
394 {
395  return 1E-4;
396 }
397 
400  void
401  )
402 {
403  return 10;
404 }
405 
408  void
409  )
410 {
411  return FALSE;
412 }
413 
417 /*
418  * SDPI Creation and Destruction Methods
419  */
420 
425 SCIP_RETCODE SCIPsdpiSolverCreate(
426  SCIP_SDPISOLVER** sdpisolver,
427  SCIP_MESSAGEHDLR* messagehdlr,
428  BMS_BLKMEM* blkmem,
429  BMS_BUFMEM* bufmem
430  )
431 {
432  assert( sdpisolver != NULL );
433  assert( blkmem != NULL );
434  assert( bufmem != NULL );
435 
436  SCIPdebugMessage("Calling SCIPsdpiCreate \n");
437 
438  BMS_CALL( BMSallocBlockMemory(blkmem, sdpisolver) );
439 
440  (*sdpisolver)->messagehdlr = messagehdlr;
441  (*sdpisolver)->blkmem = blkmem;
442  (*sdpisolver)->bufmem = bufmem;
443 
444  /* the following four variables will be properly initialized only immediatly prior to solving because DSDP and the
445  * SDPCone need information about the number of variables and sdpblocks during creation */
446  (*sdpisolver)->dsdp = NULL;
447  (*sdpisolver)->sdpcone = NULL;
448  (*sdpisolver)->lpcone = NULL;
449  (*sdpisolver)->bcone = NULL;
450 
451  (*sdpisolver)->nvars = 0;
452  (*sdpisolver)->nactivevars = 0;
453  (*sdpisolver)->inputtodsdpmapper = NULL;
454  (*sdpisolver)->dsdptoinputmapper = NULL;
455  (*sdpisolver)->fixedvarsval = NULL;
456  (*sdpisolver)->fixedvarsobjcontr = 0.0;
457  (*sdpisolver)->objcoefs = NULL;
458  (*sdpisolver)->solved = FALSE;
459  (*sdpisolver)->timelimit = FALSE;
460  (*sdpisolver)->timelimitinitial = FALSE;
461  (*sdpisolver)->penalty = FALSE;
462  (*sdpisolver)->penaltyworbound = FALSE;
463  (*sdpisolver)->feasorig = FALSE;
464  (*sdpisolver)->sdpcounter = 0;
465  (*sdpisolver)->niterations = 0;
466  (*sdpisolver)->nsdpcalls = 0;
467 
468  (*sdpisolver)->epsilon = 1e-9;
469  (*sdpisolver)->gaptol = 1e-4;
470  (*sdpisolver)->feastol = 1e-6;
471  (*sdpisolver)->sdpsolverfeastol = 1e-6;
472  (*sdpisolver)->penaltyparam = 1e5;
473  (*sdpisolver)->objlimit = SCIPsdpiSolverInfinity(*sdpisolver);
474  (*sdpisolver)->sdpinfo = FALSE;
475  (*sdpisolver)->usedsetting = SCIP_SDPSOLVERSETTING_UNSOLVED;
476  (*sdpisolver)->preoptimalsolexists = FALSE;
477  (*sdpisolver)->preoptimalgap = -1.0;
478 
479  return SCIP_OKAY;
480 }
481 
483 SCIP_RETCODE SCIPsdpiSolverFree(
484  SCIP_SDPISOLVER** sdpisolver
485  )
486 {
487  assert( sdpisolver != NULL );
488  assert( *sdpisolver != NULL );
489 
490  SCIPdebugMessage("Freeing SDPISolver\n");
491 
492  if ( (*sdpisolver)->dsdp != NULL )
493  {
494  DSDP_CALL( DSDPDestroy((*sdpisolver)->dsdp) );
495  }
496 
497  if ( (*sdpisolver)->nvars > 0 )
498  BMSfreeBlockMemoryArray((*sdpisolver)->blkmem, &(*sdpisolver)->inputtodsdpmapper, (*sdpisolver)->nvars);/*lint !e737 */
499 
500  if ( (*sdpisolver)->nactivevars > 0 )
501  {
502  BMSfreeBlockMemoryArray((*sdpisolver)->blkmem, &(*sdpisolver)->preoptimalsol, (*sdpisolver)->nactivevars);
503  BMSfreeBlockMemoryArray((*sdpisolver)->blkmem, &(*sdpisolver)->dsdptoinputmapper, (*sdpisolver)->nactivevars);/*lint !e737 */
504  BMSfreeBlockMemoryArray((*sdpisolver)->blkmem, &(*sdpisolver)->objcoefs, (*sdpisolver)->nactivevars); /*lint !e776*/
505  }
506 
507  if ( (*sdpisolver)->nvars >= (*sdpisolver)->nactivevars )
508  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->fixedvarsval, (*sdpisolver)->nvars - (*sdpisolver)->nactivevars); /*lint !e776*/
509 
510  BMSfreeBlockMemory((*sdpisolver)->blkmem, sdpisolver);
511 
512  return SCIP_OKAY;
513 }
514 
516 SCIP_RETCODE SCIPsdpiSolverIncreaseCounter(
517  SCIP_SDPISOLVER* sdpisolver
518  )
519 {
520  assert( sdpisolver != NULL );
521 
522  sdpisolver->sdpcounter++;
523 
524  return SCIP_OKAY;
525 }
526 
528 SCIP_RETCODE SCIPsdpiSolverResetCounter(
529  SCIP_SDPISOLVER* sdpisolver
530  )
531 {
532  assert( sdpisolver != NULL );
533 
534  SCIPdebugMessage("Resetting counter of SDP-Interface from %d to 0.\n", sdpisolver->sdpcounter);
535  sdpisolver->sdpcounter = 0;
536 
537  return SCIP_OKAY;
538 }
539 
543 /*
544  * Solving Methods
545  */
546 
565 SCIP_RETCODE SCIPsdpiSolverLoadAndSolve(
566  SCIP_SDPISOLVER* sdpisolver,
567  int nvars,
568  SCIP_Real* obj,
569  SCIP_Real* lb,
570  SCIP_Real* ub,
571  int nsdpblocks,
572  int* sdpblocksizes,
573  int* sdpnblockvars,
574  int sdpconstnnonz,
575  int* sdpconstnblocknonz,
577  int** sdpconstrow,
578  int** sdpconstcol,
579  SCIP_Real** sdpconstval,
580  int sdpnnonz,
581  int** sdpnblockvarnonz,
583  int** sdpvar,
585  int*** sdprow,
586  int*** sdpcol,
587  SCIP_Real*** sdpval,
588  int** indchanges,
590  int* nremovedinds,
591  int* blockindchanges,
592  int nremovedblocks,
593  int nlpcons,
594  int noldlpcons,
595  SCIP_Real* lplhs,
596  SCIP_Real* lprhs,
597  int* rownactivevars,
598  int lpnnonz,
599  int* lprow,
600  int* lpcol,
601  SCIP_Real* lpval,
602  SCIP_Real* starty,
603  int* startZnblocknonz,
605  int** startZrow,
607  int** startZcol,
609  SCIP_Real** startZval,
611  int* startXnblocknonz,
613  int** startXrow,
615  int** startXcol,
617  SCIP_Real** startXval,
619  SCIP_SDPSOLVERSETTING startsettings,
621  SCIP_Real timelimit
622  )
623 {
624  return SCIPsdpiSolverLoadAndSolveWithPenalty(sdpisolver, 0.0, TRUE, TRUE, nvars, obj, lb, ub, nsdpblocks, sdpblocksizes, sdpnblockvars,
625  sdpconstnnonz, sdpconstnblocknonz, sdpconstrow, sdpconstcol, sdpconstval, sdpnnonz, sdpnblockvarnonz, sdpvar, sdprow, sdpcol, sdpval,
626  indchanges, nremovedinds, blockindchanges, nremovedblocks, nlpcons, noldlpcons, lplhs, lprhs, rownactivevars, lpnnonz, lprow, lpcol,
627  lpval, starty, startZnblocknonz, startZrow, startZcol, startZval, startXnblocknonz, startXrow, startXcol, startXval, startsettings,
628  timelimit, NULL, NULL);
629 }
630 
654  SCIP_SDPISOLVER* sdpisolver,
655  SCIP_Real penaltyparam,
656  SCIP_Bool withobj,
657  SCIP_Bool rbound,
658  int nvars,
659  SCIP_Real* obj,
660  SCIP_Real* lb,
661  SCIP_Real* ub,
662  int nsdpblocks,
663  int* sdpblocksizes,
664  int* sdpnblockvars,
665  int sdpconstnnonz,
666  int* sdpconstnblocknonz,
668  int** sdpconstrow,
669  int** sdpconstcol,
670  SCIP_Real** sdpconstval,
671  int sdpnnonz,
672  int** sdpnblockvarnonz,
674  int** sdpvar,
676  int*** sdprow,
677  int*** sdpcol,
678  SCIP_Real*** sdpval,
679  int** indchanges,
681  int* nremovedinds,
682  int* blockindchanges,
683  int nremovedblocks,
684  int nlpcons,
685  int noldlpcons,
686  SCIP_Real* lplhs,
687  SCIP_Real* lprhs,
688  int* rownactivevars,
689  int lpnnonz,
690  int* lprow,
691  int* lpcol,
692  SCIP_Real* lpval,
693  SCIP_Real* starty,
694  int* startZnblocknonz,
696  int** startZrow,
698  int** startZcol,
700  SCIP_Real** startZval,
702  int* startXnblocknonz,
704  int** startXrow,
706  int** startXcol,
708  SCIP_Real** startXval,
710  SCIP_SDPSOLVERSETTING startsettings,
712  SCIP_Real timelimit,
713  SCIP_Bool* feasorig,
715  SCIP_Bool* penaltybound
717  )
718 {/*lint --e{413}*/
719  int* dsdpconstind = NULL; /* indices for constant SDP-constraint-matrices, needs to be stored for DSDP during solving and be freed only afterwards */
720  SCIP_Real* dsdpconstval = NULL; /* non-zero values for constant SDP-constraint-matrices, needs to be stored for DSDP during solving and be freed only afterwards */
721  int* dsdpind = NULL; /* indices for SDP-constraint-matrices, needs to be stored for DSDP during solving and be freed only afterwards */
722  SCIP_Real* dsdpval = NULL; /* non-zero values for SDP-constraint-matrices, needs to be stored for DSDP during solving and be freed only afterwards */
723  int* dsdplpbegcol = NULL; /* starting-indices for all columns in LP, needs to be stored for DSDP during solving and be freed only afterwards */
724  int* dsdplprow = NULL; /* row indices in LP, needs to be stored for DSDP during solving and be freed only afterwards */
725  SCIP_Real* dsdplpval = NULL; /* nonzeroes in LP, needs to be stored for DSDP during solving and be freed only afterwards */
726  int i;
727  int j;
728  int ind;
729  int block;
730  int startind;
731  int nfixedvars;
732  int dsdpnlpnonz = 0;
733  int nrnonz = 0;
734  int oldnactivevars;
735  SCIP_Real feastol;
736  Timings timings;
737 
738 #ifdef SCIP_DEBUG
739  DSDPTerminationReason reason; /* this will later be used to check if DSDP converged */
740 #endif
741 
742  assert( sdpisolver != NULL );
743  assert( penaltyparam > -1 * sdpisolver->epsilon );
744  assert( penaltyparam < sdpisolver->epsilon || ( feasorig != NULL ) );
745  assert( nvars > 0 );
746  assert( obj != NULL );
747  assert( lb != NULL );
748  assert( ub != NULL );
749  assert( nsdpblocks >= 0 );
750  assert( nsdpblocks == 0 || sdpblocksizes != NULL );
751  assert( nsdpblocks == 0 || sdpnblockvars != NULL );
752  assert( sdpconstnnonz >= 0 );
753  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstnblocknonz != NULL );
754  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstrow != NULL );
755  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstcol != NULL );
756  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstval != NULL );
757  assert( sdpnnonz >= 0 );
758  assert( nsdpblocks == 0 || sdpnblockvarnonz != NULL );
759  assert( nsdpblocks == 0 || sdpvar != NULL );
760  assert( nsdpblocks == 0 || sdprow != NULL );
761  assert( nsdpblocks == 0 || sdpcol != NULL );
762  assert( nsdpblocks == 0 || sdpval != NULL );
763  assert( nsdpblocks == 0 || indchanges != NULL );
764  assert( nsdpblocks == 0 || nremovedinds != NULL );
765  assert( nsdpblocks == 0 || blockindchanges != NULL );
766  assert( 0 <= nremovedblocks && nremovedblocks <= nsdpblocks );
767  assert( nlpcons >= 0 );
768  assert( noldlpcons >= nlpcons );
769  assert( nlpcons == 0 || lplhs != NULL );
770  assert( nlpcons == 0 || lprhs != NULL );
771  assert( nlpcons == 0 || rownactivevars != NULL );
772  assert( lpnnonz >= 0 );
773  assert( nlpcons == 0 || lprow != NULL );
774  assert( nlpcons == 0 || lpcol != NULL );
775  assert( nlpcons == 0 || lpval != NULL );
776 
777  sdpisolver->penalty = penaltyparam > sdpisolver->epsilon;
778 
779  if ( timelimit <= 0.0 )
780  {
781  sdpisolver->timelimit = TRUE;
782  sdpisolver->timelimitinitial = TRUE;
783  sdpisolver->solved = FALSE;
784  return SCIP_OKAY;
785  }
786  else
787  sdpisolver->timelimitinitial = FALSE;
788 
789  sdpisolver->feasorig = FALSE;
790 
791  /* start the timing */
792  TIMEOFDAY_CALL( gettimeofday(&(timings.starttime), NULL) );/*lint !e438, !e550, !e641 */
793  timings.timelimit = timelimit;
794  timings.stopped = FALSE;
795 
796  /* 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
797  * same SDP), also remember settings for statistics */
798  if ( penaltyparam < sdpisolver->epsilon )
799  {
800  SCIPdebugMessage("Inserting Data into DSDP for SDP (%d) \n", ++sdpisolver->sdpcounter);
801  sdpisolver->usedsetting = SCIP_SDPSOLVERSETTING_FAST;
802  }
803  else
804  {
805  SCIPdebugMessage("Inserting Data again into DSDP for SDP (%d) \n", sdpisolver->sdpcounter);
806  sdpisolver->usedsetting = SCIP_SDPSOLVERSETTING_PENALTY;
807  }
808 
809  /* allocate memory for inputtomosekmapper, mosektoinputmapper and the fixed and active variable information, for the latter this will
810  * later be shrinked if the needed size is known */
811  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->inputtodsdpmapper), sdpisolver->nvars, nvars) );
812  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->dsdptoinputmapper), sdpisolver->nactivevars, nvars) );
813  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->fixedvarsval), sdpisolver->nvars - sdpisolver->nactivevars, nvars) ); /*lint !e776*/
814  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->objcoefs), sdpisolver->nactivevars, nvars) ); /*lint !e776*/
815 
816  sdpisolver->nvars = nvars;
817  oldnactivevars = sdpisolver->nactivevars;
818  sdpisolver->nactivevars = 0;
819  nfixedvars = 0;
820  sdpisolver->niterations = 0;
821  sdpisolver->nsdpcalls = 0;
822 
823  /* find the fixed variables */
824  sdpisolver->fixedvarsobjcontr = 0.0;
825  for (i = 0; i < nvars; i++)
826  {
827  if ( isFixed(sdpisolver, lb[i], ub[i]) )
828  {
829  nfixedvars++;
830  sdpisolver->inputtodsdpmapper[i] = -nfixedvars;
831  sdpisolver->fixedvarsobjcontr += obj[i] * lb[i]; /* this is the value this variable contributes to the objective */
832  sdpisolver->fixedvarsval[nfixedvars - 1] = lb[i]; /* if lb=ub, than this is the value the variable will have in every solution */
833  SCIPdebugMessage("Fixing variable %d locally to %f for SDP %d in DSDP\n", i, lb[i], sdpisolver->sdpcounter);
834  }
835  else
836  {
837  sdpisolver->dsdptoinputmapper[sdpisolver->nactivevars] = i;
838  sdpisolver->objcoefs[sdpisolver->nactivevars] = obj[i];
839  sdpisolver->nactivevars++;
840  sdpisolver->inputtodsdpmapper[i] = sdpisolver->nactivevars; /* dsdp starts counting at 1, so we do this after increasing nactivevars */
841  SCIPdebugMessage("Variable %d becomes variable %d for SDP %d in DSDP\n", i, sdpisolver->inputtodsdpmapper[i], sdpisolver->sdpcounter);
842  }
843  }
844  assert( sdpisolver->nactivevars + nfixedvars == sdpisolver->nvars );
845  if ( penaltyparam > sdpisolver->epsilon && (! rbound) )
846  {
847  SCIPdebugMessage("Variable %d is the slack variable for the explicit penalty formulation\n", sdpisolver->nactivevars + 1);
848  }
849 
850  /* if we want to solve without objective, we reset fixedvarsobjcontr */
851  if ( ! withobj )
852  sdpisolver->fixedvarsobjcontr = 0.0;
853 
854  /* shrink the fixedvars, objcoefs and mosektoinputmapper arrays to the right size */
855  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->objcoefs), nvars, sdpisolver->nactivevars) );
856  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->fixedvarsval), nvars, nfixedvars) );
857  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->dsdptoinputmapper), nvars, sdpisolver->nactivevars) );
858 
859  /* adjust length of preoptimal solution array */
860  if ( sdpisolver->nactivevars != oldnactivevars )
861  {
862  if ( oldnactivevars == 0 )
863  {
864  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->preoptimalsol), sdpisolver->nactivevars) );
865  }
866  else
867  {
868  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->preoptimalsol), oldnactivevars, sdpisolver->nactivevars) );
869  }
870  }
871  sdpisolver->preoptimalsolexists = FALSE;
872 
873  /* insert data */
874 
875  if ( sdpisolver->dsdp != NULL )
876  {
877  DSDP_CALL( DSDPDestroy(sdpisolver->dsdp) ); /* if there already exists a DSDP-instance, destroy the old one */
878  }
879 
880  /* in case we don't want to bound r, we can't use the penalty formulation in DSDP and have to give r explicitly */
881  if ( penaltyparam > sdpisolver->epsilon && (! rbound) )
882  {
883  DSDP_CALLM( DSDPCreate(sdpisolver->nactivevars + 1, &(sdpisolver->dsdp)) );
884  sdpisolver->penaltyworbound = TRUE;
885  }
886  else
887  {
888  DSDP_CALLM( DSDPCreate(sdpisolver->nactivevars, &(sdpisolver->dsdp)) );
889  sdpisolver->penaltyworbound = FALSE;
890  }
891  DSDP_CALLM( DSDPCreateSDPCone(sdpisolver->dsdp, nsdpblocks - nremovedblocks, &(sdpisolver->sdpcone)) );
892  DSDP_CALLM( DSDPCreateLPCone(sdpisolver->dsdp, &(sdpisolver->lpcone)) );
893  DSDP_CALLM( DSDPCreateBCone(sdpisolver->dsdp, &(sdpisolver->bcone)) );
894 
895 #ifdef SCIP_MORE_DEBUG
896  SCIPmessagePrintInfo(sdpisolver->messagehdlr, "setting objective values for SDP %d:\n", sdpisolver->sdpcounter);
897 #endif
898 
899  for (i = 0; i < sdpisolver->nactivevars; i++)
900  {
901  if ( withobj )
902  {
903  /* insert objective value, DSDP counts from 1 to n instead of 0 to n-1, *(-1) because DSDP maximizes instead of minimizing */
904  DSDP_CALL( DSDPSetDualObjective(sdpisolver->dsdp, i+1, -1.0 * obj[sdpisolver->dsdptoinputmapper[i]]) );
905 #ifdef SCIP_MORE_DEBUG
906  SCIPmessagePrintInfo(sdpisolver->messagehdlr, "var %d (was var %d): %f, ", i+1, sdpisolver->dsdptoinputmapper[i], obj[sdpisolver->dsdptoinputmapper[i]]);
907 #endif
908  }
909  else
910  {
911  DSDP_CALL( DSDPSetDualObjective(sdpisolver->dsdp, i+1, 0.0) );
912  }
913 
914  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, lb[sdpisolver->dsdptoinputmapper[i]]) )
915  {
916  /* insert lower bound, DSDP counts from 1 to n instead of 0 to n-1 */
917  DSDP_CALL( BConeSetLowerBound(sdpisolver->bcone, i+1, lb[sdpisolver->dsdptoinputmapper[i]]) );
918  }
919 
920  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, ub[sdpisolver->dsdptoinputmapper[i]]) )
921  {
922  /* insert upper bound, DSDP counts from 1 to n instead of 0 to n-1 */
923  DSDP_CALL(BConeSetUpperBound(sdpisolver->bcone, i+1, ub[sdpisolver->dsdptoinputmapper[i]]));
924  }
925  }
926 
927  /* insert the objective value for r if solving without rbound, it is variable nactivevars + 1 and the objective is multiplied by -1 as we maximize */
928  if ( penaltyparam > sdpisolver->epsilon && (! rbound) )
929  {
930  DSDP_CALL( DSDPSetDualObjective(sdpisolver->dsdp, sdpisolver->nactivevars + 1, -1.0 * penaltyparam) );
931 #ifdef SCIP_MORE_DEBUG
932  SCIPmessagePrintInfo(sdpisolver->messagehdlr, "slack variable r: %f, ", penaltyparam);
933 #endif
934  }
935 
936 #ifdef SCIP_MORE_DEBUG
937  SCIPmessagePrintInfo(sdpisolver->messagehdlr, "\n");
938  SCIPdebugMessage("ATTENTION: BConeView shows the WRONG sign for the lower bound!\n");
939  BConeView(sdpisolver->bcone);
940 #endif
941 
942  /* set blocksizes */
943  for (block = 0; block < nsdpblocks; ++block)
944  {
945  /* only insert blocksizes for the blocks we didn't remove */
946  if ( blockindchanges[block] > -1 )
947  {
948  /* (blocks are counted from 0 to m-1) */
949  DSDP_CALL( SDPConeSetBlockSize(sdpisolver->sdpcone, block- blockindchanges[block], sdpblocksizes[block] - nremovedinds[block]) );
950  }
951  }
952 
953  /* start inserting the non-constant SDP-Constraint-Matrices */
954  if ( sdpnnonz > 0 )
955  {
956  int v;
957  int k;
958  int blockvar;
959 
960  nrnonz = 0;
961 
962  /* allocate memory */
963  /* This needs to be one long array, because DSDP uses it for solving so all nonzeros have to be in it and it may not be freed before the
964  * problem is solved. The distinct blocks/variables (for the i,j-parts) are then given by dsdpind + startind, which gives a pointer to the
965  * first array-element belonging to this block and then the number of elements in this block is given to DSDP for iterating over it. */
966 
967  if ( penaltyparam > sdpisolver->epsilon && (! rbound) )
968  {
969  /* we need to compute the total number of nonzeros for the slack variable r, which equals the total number of diagonal entries */
970  for (block = 0; block < nsdpblocks; block++)
971  nrnonz += sdpblocksizes[block] - nremovedinds[block];
972  assert( nrnonz >= 0 );
973 
974  /* indices given to DSDP, for this the elements in the lower triangular part of the matrix are labeled from 0 to n*(n+1)/2 -1 */
975  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &dsdpind, sdpnnonz + nrnonz) ); /*lint !e776*/
976  /* values given to DSDP, these will be multiplied by -1 because in DSDP -1* (sum A_i^j y_i - A_0) should be positive semidefinite */
977  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &dsdpval, sdpnnonz + nrnonz) ); /*lint !e776*/
978  }
979  else
980  {
981  /* indices given to DSDP, for this the elements in the lower triangular part of the matrix are labeled from 0 to n*(n+1)/2 -1 */
982  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &dsdpind, sdpnnonz) );
983  /* values given to DSDP, these will be multiplied by -1 because in DSDP -1* (sum A_i^j y_i - A_0) should be positive semidefinite */
984  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &dsdpval, sdpnnonz) );
985  }
986 
987  ind = 0; /* this will be used for iterating over the nonzeroes */
988 
989  for (block = 0; block < nsdpblocks; block++)
990  {
991  for (i = 0; i < sdpisolver->nactivevars; i++)
992  {
993  /* we iterate over all non-fixed variables, so add them to the dsdp arrays for this block/var combination */
994  v = sdpisolver->dsdptoinputmapper[i];
995 
996  /* find the position of variable v in this block */
997  blockvar = -1;
998  for (k = 0; k < sdpnblockvars[block]; k++)
999  {
1000  if ( v == sdpvar[block][k] )
1001  {
1002  blockvar = k;
1003  break;
1004  }
1005  }
1006 
1007  startind = ind;
1008 
1009  if ( blockvar > -1 ) /* the variable exists in this block */
1010  {
1011  for (k = 0; k < sdpnblockvarnonz[block][blockvar]; k++)
1012  {
1013  /* rows and cols with active nonzeros should not be removed */
1014  assert( indchanges[block][sdprow[block][blockvar][k]] > -1 && indchanges[block][sdpcol[block][blockvar][k]] > -1 );
1015 
1016  /* substract the number of removed indices before the row and col to get the indices after fixings */
1017  dsdpind[ind] = compLowerTriangPos(sdprow[block][blockvar][k] - indchanges[block][sdprow[block][blockvar][k]],
1018  sdpcol[block][blockvar][k] - indchanges[block][sdpcol[block][blockvar][k]]);
1019  dsdpval[ind] = -1.0 * sdpval[block][blockvar][k]; /* *(-1) because in DSDP -1* (sum A_i^j y_i - A_0) should be positive semidefinite */
1020  ind++;
1021  }
1022 
1023  /* sort the arrays for this matrix (by non decreasing indices) as this might help the solving time of DSDP */
1024  SCIPsortIntReal(dsdpind + startind, dsdpval + startind, sdpnblockvarnonz[block][blockvar]);
1025 
1026  assert( blockindchanges[block] > -1 ); /* we shouldn't insert into blocks we removed */
1027 
1028  /* i + 1 because DSDP starts counting the variables at 1, adding startind shifts the arrays to the first
1029  * nonzero belonging to this block and this variable */
1030  DSDP_CALL( SDPConeSetASparseVecMat(sdpisolver->sdpcone, block - blockindchanges[block], i + 1, sdpblocksizes[block] - nremovedinds[block],
1031  1.0, 0, dsdpind + startind,dsdpval + startind, sdpnblockvarnonz[block][blockvar]));
1032  }
1033  }
1034  }
1035 
1036  if ( penaltyparam > sdpisolver->epsilon && (! rbound) )
1037  {
1038  startind = ind;
1039  /* add r * Identity for each block */
1040  for (block = 0; block < nsdpblocks; block++)
1041  {
1042  if ( blockindchanges[block] > -1 )
1043  {
1044  for (i = 0; i < sdpblocksizes[block] - nremovedinds[block]; i++)
1045  {
1046  dsdpind[ind] = compLowerTriangPos(i, i);
1047  dsdpval[ind] = -1.0; /* *(-1) because in DSDP -1* (sum A_i^j y_i - A_0 + r*I) should be positive semidefinite */
1048  ind++;
1049  }
1050  DSDP_CALL( SDPConeSetASparseVecMat(sdpisolver->sdpcone, block - blockindchanges[block], sdpisolver->nactivevars + 1,
1051  sdpblocksizes[block] - nremovedinds[block], 1.0, 0, dsdpind + ind - (sdpblocksizes[block] - nremovedinds[block]) ,
1052  dsdpval + ind - (sdpblocksizes[block] - nremovedinds[block]), sdpblocksizes[block] - nremovedinds[block]) ); /*lint !e679*/
1053  }
1054  }
1055  assert( ind - startind == nrnonz );
1056  }
1057  }
1058 
1059  /* start inserting the constant matrix */
1060  if ( sdpconstnnonz > 0 )
1061  {
1062  assert( nsdpblocks > 0 );
1063  assert( sdpconstnblocknonz!= NULL );
1064  assert( sdpconstcol != NULL );
1065  assert( sdpconstrow != NULL );
1066  assert( sdpconstval != NULL );
1067 
1068  /* allocate memory */
1069 
1070  /* DSDP uses these for solving, so they may not be freed before the problem is solved. */
1071 
1072  /* indices given to DSDP, for this the elements in the lower triangular part of the matrix are labeled from 0 to n*(n+1)/2 -1 */
1073  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &dsdpconstind, sdpconstnnonz) );
1074  /* values given to DSDP, for this the original values are mutliplied by -1 because in DSDP -1* (sum A_i^j y_i - A_0) should be positive semidefinite */
1075  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &dsdpconstval, sdpconstnnonz) );
1076 
1077  ind = 0;
1078 
1079  for (block = 0; block < nsdpblocks; block++)
1080  {
1081  startind = ind; /* starting index of this block in the dsdpconst arrays */
1082 
1083  if ( sdpconstnblocknonz[block] > 0 )
1084  {
1085  /* insert the constant-nonzeros */
1086  for (i = 0; i < sdpconstnblocknonz[block]; i++)
1087  {
1088  /* rows and cols with nonzeros should not be removed */
1089  assert( indchanges[block][sdpconstrow[block][i]] > -1 && indchanges[block][sdpconstcol[block][i]] > -1 );
1090 
1091  /* substract the number of deleted indices before this to get the index after variable fixings */
1092  dsdpconstind[ind] = compLowerTriangPos(sdpconstrow[block][i] - indchanges[block][sdpconstrow[block][i]],
1093  sdpconstcol[block][i] - indchanges[block][sdpconstcol[block][i]]);
1094  dsdpconstval[ind] = -1 * sdpconstval[block][i]; /* *(-1) because in DSDP -1* (sum A_i^j y_i - A_0^j) should be positive semidefinite */
1095  ind++;
1096  }
1097 
1098  /* sort the arrays for this Matrix (by non decreasing indices) as this might help the solving time of DSDP */
1099  SCIPsortIntReal(dsdpconstind + startind, dsdpconstval + startind, sdpconstnblocknonz[block]);
1100 
1101  assert( blockindchanges[block] > -1 ); /* we shouldn't insert into a block we removed */
1102 
1103  /* constant matrix is given as variable 0, the arrays are shifted to the first element of this block by adding
1104  * startind, ind - startind gives the number of elements for this block */
1105  DSDP_CALL( SDPConeSetASparseVecMat(sdpisolver->sdpcone, block - blockindchanges[block], 0, sdpblocksizes[block] - nremovedinds[block],
1106  1.0, 0, dsdpconstind + startind, dsdpconstval + startind, ind - startind));
1107  }
1108  }
1109  }
1110 
1111 #ifdef SCIP_MORE_DEBUG
1112  SDPConeView2(sdpisolver->sdpcone);
1113 #endif
1114 
1115  /* start inserting the LP constraints */
1116  if ( nlpcons > 0 || lpnnonz > 0 || ! SCIPsdpiSolverIsInfinity(sdpisolver, sdpisolver->objlimit) )
1117  {
1118  int nextcol;
1119  int* rowmapper; /* maps the lhs- and rhs-inequalities of the old LP-cons to their constraint numbers in DSDP */
1120  int pos;
1121  int newpos;
1122  int nlpineqs;
1123 
1124  assert( noldlpcons > 0 );
1125  assert( lprhs != NULL );
1126  assert( lpcol != NULL );
1127  assert( lprow != NULL );
1128  assert( lpval != NULL );
1129 
1130  /* allocate memory to save which lpconstraints are mapped to which index, entry 2i corresponds to the left hand side of row i, 2i+1 to the rhs */
1131  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &rowmapper, 2*noldlpcons) ); /*lint !e647*/
1132 
1133  /* compute the rowmapper and the number of inequalities we have to add to DSDP (as we have to split the ranged rows) */
1134  pos = 0;
1135  newpos = 0; /* the position in the lhs and rhs arrays */
1136  for (i = 0; i < noldlpcons; i++)
1137  {
1138  if ( rownactivevars[i] >= 2 )
1139  {
1140  if ( lplhs[newpos] > - SCIPsdpiSolverInfinity(sdpisolver) )
1141  {
1142  rowmapper[2*i] = pos; /*lint !e679*/
1143  pos++;
1144  }
1145  else
1146  rowmapper[2*i] = -1; /*lint !e679*/
1147 
1148  if ( lprhs[newpos] < SCIPsdpiSolverInfinity(sdpisolver) )
1149  {
1150  rowmapper[2*i + 1] = pos; /*lint !e679*/
1151  pos++;
1152  }
1153  else
1154  rowmapper[2*i + 1] = -1; /*lint !e679*/
1155 
1156  newpos++;
1157  }
1158  else
1159  {
1160  rowmapper[2*i] = -1; /*lint !e679*/
1161  rowmapper[2*i + 1] = -1; /*lint !e679*/
1162  }
1163  }
1164  nlpineqs = pos;
1165  assert( nlpineqs <= 2*nlpcons ); /* *2 comes from left- and right-hand-sides */
1166 
1167  /* memory allocation */
1168 
1169  /* these arrays are needed in DSDP during solving, so they may only be freed afterwards */
1170  /* dsdplpbegcol[i] gives the number of nonzeros in column 0 (right hand side) till i-1 (i going from 1 till m, with extra entries 0 (always 0)
1171  * and m+1 (always lpcons + lpnnonz)) */
1172  if ( penaltyparam > sdpisolver->epsilon && (! rbound) )
1173  {
1174  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &dsdplpbegcol, sdpisolver->nactivevars + 3) ); /* extra entry for r */ /*lint !e776*/
1175  }
1176  else
1177  {
1178  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &dsdplpbegcol, sdpisolver->nactivevars + 2) ); /*lint !e776*/
1179  }
1180 
1181  /* dsdplprow saves the row indices of the LP for DSDP */
1182  /* worst-case length is 2*lpnnonz + nlpineqs, because left- and right-hand-sides are also included in the vectorand we might have to duplicate the
1183  * non-zeros when splitting the ranged rows, this will be shortened after the exact length after fixings is known, in case we have an objective limit,
1184  * this is increased by one entry for the right-hand-side and at most nvars entries for the nonzeros, in case of rbound = FALSE, where we have to add
1185  * the entries for r ourselves, we have to add another nlpineqs for one entry for r for each active lp-constraint */
1186  if ( SCIPsdpiSolverIsInfinity(sdpisolver, sdpisolver->objlimit) )
1187  {
1188  if ( penaltyparam > sdpisolver->epsilon && (! rbound) )
1189  {
1190  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &dsdplprow, 2 * nlpineqs + 2*lpnnonz) ); /*lint !e647*/
1191  }
1192  else
1193  {
1194  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &dsdplprow, nlpineqs + 2*lpnnonz) ); /*lint !e647*/
1195  }
1196  }
1197  else
1198  {
1199  if ( penaltyparam > sdpisolver->epsilon && (! rbound) )
1200  {
1201  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &dsdplprow, (nlpineqs + 1) + 2*lpnnonz + nvars + nlpineqs) ); /*lint !e647*/
1202  }
1203  else
1204  {
1205  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &dsdplprow, (nlpineqs + 1) + 2*lpnnonz + nvars) ); /*lint !e647*/
1206  }
1207  }
1208 
1209  /* values given to DSDP */
1210  /* dsdplprow saves the row indices of the LP for DSDP */
1211  /* worst-case length is 2*lpnnonz + nlpineqs, because left- and right-hand-sides are also included in the vectorand we might have to duplicate the
1212  * non-zeros when splitting the ranged rows, this will be shortened after the exact length after fixings is known, in case we have an objective limit,
1213  * this is increased by one entry for the right-hand-side and at most nvars entries for the nonzeros, in case of rbound = FALSE, where we have to add
1214  * the entries for r ourselves, we have to add another nlpineqs for one entry for r for each active lp-constraint */
1215  if ( SCIPsdpiSolverIsInfinity(sdpisolver, sdpisolver->objlimit) )
1216  {
1217  if ( penaltyparam > sdpisolver->epsilon && (! rbound) )
1218  {
1219  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &dsdplpval, 2 * nlpineqs + 2*lpnnonz) ); /*lint !e647*/
1220  }
1221  else
1222  {
1223  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &dsdplpval, nlpineqs + 2*lpnnonz) ); /*lint !e647*/
1224  }
1225  }
1226  else
1227  {
1228  if ( penaltyparam > sdpisolver->epsilon && (! rbound) )
1229  {
1230  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &dsdplpval, (nlpineqs + 1) + 2*lpnnonz + nvars + nlpineqs) ); /*lint !e647*/
1231  }
1232  else
1233  {
1234  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &dsdplpval, (nlpineqs + 1) + 2*lpnnonz + nvars) ); /*lint !e647*/
1235  }
1236  }
1237 
1238  /* add all left- and right-hand-sides that are greater than zero (if their corresponding inequalities exist), the pos counter is increased for every
1239  * active row, to get the correct row numbers, the nonz-counter only if the lhs/rhs is unequal to zero and added to DSDP */
1240  dsdpnlpnonz = 0;
1241  pos = 0;
1242  for (i = 0; i < nlpcons; i++)
1243  {
1244  if ( lplhs[i] > - SCIPsdpiSolverInfinity(sdpisolver) )
1245  {
1246  if ( REALABS(lplhs[i]) > sdpisolver->epsilon )
1247  {
1248  dsdplprow[dsdpnlpnonz] = pos;
1249  dsdplpval[dsdpnlpnonz] = -lplhs[i]; /* we multiply by -1 because DSDP wants <= instead of >= */
1250  dsdpnlpnonz++;
1251  }
1252  pos++;
1253  }
1254  if ( lprhs[i] < SCIPsdpiSolverInfinity(sdpisolver) )
1255  {
1256  if ( REALABS(lprhs[i]) > sdpisolver->epsilon )
1257  {
1258  dsdplprow[dsdpnlpnonz] = pos;
1259  dsdplpval[dsdpnlpnonz] = lprhs[i];
1260  dsdpnlpnonz++;
1261  }
1262  pos++;
1263  }
1264  }
1265  assert( pos == nlpineqs );
1266 
1267  /* add the right-hand-side for the objective bound */
1268  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, sdpisolver->objlimit) )
1269  {
1270  if ( REALABS(sdpisolver->objlimit) > sdpisolver->epsilon )
1271  {
1272  dsdplprow[dsdpnlpnonz] = nlpcons; /* this is the last lp-constraint, as DSDP counts from 0 to nlpcons-1, this is number nlpcons */
1273  dsdplpval[dsdpnlpnonz] = sdpisolver->objlimit; /* as we want <= upper bound, this is the correct type of inequality for DSDP */
1274  dsdpnlpnonz++;
1275  }
1276  }
1277 
1278  /* now add the nonzeros */
1279 
1280  /* for this we have to sort the nonzeros by col first and then by row, as this is the sorting DSDP wants */
1281  sortColRow(lprow, lpcol, lpval, lpnnonz);
1282 
1283  /* iterate over all nonzeros to add the active ones to the dsdp arrays and compute dsdplpbegcol */
1284  nextcol = 0;
1285  dsdplpbegcol[0] = 0;
1286  for (i = 0; i < lpnnonz; i++)
1287  {
1288  /* if a new variable starts, set the corresponding dsdplpbegcol-entry */
1289  if ( lpcol[i] >= nextcol )
1290  {
1291  /* set the dsdplpbegcol entries, as there might be active variables which appear only in the sdp but not the lp-part, we also have to set
1292  * the starting values for all variables in between to the same value (as we also set the entry for the found variable, this for-queue
1293  * will always have at least one index in the index set) */
1294  for (j = nextcol; j <= lpcol[i]; j++)
1295  {
1296  if ( sdpisolver->inputtodsdpmapper[j] >= 0 )
1297  {
1298  assert( ! (isFixed(sdpisolver, lb[j], ub[j])) );
1299  dsdplpbegcol[sdpisolver->inputtodsdpmapper[j]] = dsdpnlpnonz;
1300 
1301  /* add the entry to the objlimit-lp-constraint for the last variables */
1302  if ( (! SCIPsdpiSolverIsInfinity(sdpisolver, sdpisolver->objlimit)) && (REALABS( obj[j] ) > sdpisolver->epsilon))
1303  {
1304  dsdplprow[dsdpnlpnonz] = nlpcons;
1305  dsdplpval[dsdpnlpnonz] = obj[j];
1306  dsdpnlpnonz++;
1307  }
1308  }
1309  }
1310  nextcol = j;
1311  }
1312 
1313  /* add the nonzero, if it isn't fixed and the row isn't to be deleted (because it is only a variable bound) */
1314  if ( ! isFixed(sdpisolver, lb[lpcol[i]], ub[lpcol[i]]) )
1315  {
1316  /* add it to the inequality for the lhs of the ranged row, if it exists */
1317  if ( rowmapper[2*lprow[i]] > -1 ) /*lint !e679*/
1318  {
1319  /* the index is adjusted for deleted lp rows, also rows are numbered 0,...,nlpcons-1 in DSDP, as they are
1320  * here, nlpcons is added to the index as the first nlpcons entries correspond to the right hand sides */
1321  dsdplprow[dsdpnlpnonz] = rowmapper[2*lprow[i]]; /*lint !e679*/
1322  dsdplpval[dsdpnlpnonz] = -lpval[i]; /* - because dsdp wants <= instead of >= constraints */
1323  dsdpnlpnonz++;
1324  }
1325  /* add it to the inequality for the rhs of the ranged row, if it exists */
1326  if ( rowmapper[2*lprow[i] + 1] > -1 ) /*lint !e679*/
1327  {
1328  /* the index is adjusted for deleted lp rows, also rows are numbered 0,...,nlpcons-1 in DSDP, as they are
1329  * here, nlpcons is added to the index as the first nlpcons entries correspond to the right hand sides */
1330  dsdplprow[dsdpnlpnonz] = rowmapper[2*lprow[i] + 1]; /*lint !e679*/
1331  dsdplpval[dsdpnlpnonz] = lpval[i];
1332  dsdpnlpnonz++;
1333  }
1334  }
1335 #ifndef SCIP_NDEBUG
1336  /* if this is an active nonzero for the row, it should have at least one active var */
1337  else
1338  assert( isFixed(sdpisolver, lb[lpcol[i]], ub[lpcol[i]]) || rownactivevars[lprow[i]] == 1 );
1339 #endif
1340  }
1341 
1342  /* set the begcol array for all remaining variables (that aren't part of the LP-part), and also set the objlimit-constraint-entries */
1343  for (j = nextcol; j < nvars; j++)
1344  {
1345  if ( sdpisolver->inputtodsdpmapper[j] >= 0 )
1346  {
1347  assert( ! (isFixed(sdpisolver, lb[j], ub[j])) );
1348  dsdplpbegcol[sdpisolver->inputtodsdpmapper[j]] = dsdpnlpnonz;
1349  /* add the entry to the objlimit-lp-constraint for the last variables */
1350  if ( (! SCIPsdpiSolverIsInfinity(sdpisolver, sdpisolver->objlimit)) && (REALABS( obj[j] ) > sdpisolver->epsilon))
1351  {
1352  dsdplprow[dsdpnlpnonz] = nlpcons;
1353  dsdplpval[dsdpnlpnonz] = obj[j];
1354  dsdpnlpnonz++;
1355  }
1356  }
1357  }
1358 
1359  dsdplpbegcol[sdpisolver->nactivevars + 1] = dsdpnlpnonz; /*lint !e679*/
1360 
1361  /* add r * Identity if using a penalty formulation without a bound on r */
1362  if ( penaltyparam > sdpisolver->epsilon && (! rbound) )
1363  {
1364  for (i = 0; i < nlpineqs; i++)
1365  {
1366  dsdplprow[dsdpnlpnonz] = i;
1367  dsdplpval[dsdpnlpnonz] = -1.0; /* for >=-inequalities we would add a +1, but then we have to multiply these with -1 for DSDP */
1368  dsdpnlpnonz++;
1369  }
1370  dsdplpbegcol[sdpisolver->nactivevars + 2] = dsdpnlpnonz; /*lint !e679*/
1371  }
1372 
1373  /* free the memory for the rowshifts-array */
1374  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &rowmapper); /*lint !e647, !e737*/
1375 
1376  /* shrink the dsdplp-arrays */
1377  if ( SCIPsdpiSolverIsInfinity(sdpisolver, sdpisolver->objlimit) )
1378  {
1379  if ( penaltyparam > sdpisolver->epsilon && (! rbound) )
1380  {
1381  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &dsdplprow, 2*nlpineqs + 2*lpnnonz, dsdpnlpnonz) ); /*lint !e647*/
1382  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &dsdplpval, 2*nlpineqs + 2*lpnnonz, dsdpnlpnonz) ); /*lint !e647*/
1383  }
1384  else
1385  {
1386  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &dsdplprow, nlpineqs + 2*lpnnonz, dsdpnlpnonz) ); /*lint !e647*/
1387  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &dsdplpval, nlpineqs + 2*lpnnonz, dsdpnlpnonz) ); /*lint !e647*/
1388  }
1389  }
1390  else
1391  {
1392  if ( penaltyparam > sdpisolver->epsilon && (! rbound) )
1393  {
1394  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &dsdplprow, (nlpineqs + 1) + 2*lpnnonz + nvars + nlpineqs, dsdpnlpnonz) ); /*lint !e647*/
1395  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &dsdplpval, (nlpineqs + 1) + 2*lpnnonz + nvars + nlpineqs, dsdpnlpnonz) ); /*lint !e647*/
1396  }
1397  else
1398  {
1399  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &dsdplprow, (nlpineqs + 1) + 2*lpnnonz + nvars, dsdpnlpnonz) ); /*lint !e647*/
1400  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &dsdplpval, (nlpineqs + 1) + 2*lpnnonz + nvars, dsdpnlpnonz) ); /*lint !e647*/
1401  }
1402  }
1403  /* add the arrays to dsdp (in this case we need no additional if for the penalty version without bounds, as we already added the extra var,
1404  * so DSDP knows, that there is an additional entry in dsdplpbegcol which then gives the higher number of nonzeros) */
1405  if ( SCIPsdpiSolverIsInfinity(sdpisolver, sdpisolver->objlimit) )
1406  {
1407  DSDP_CALL( LPConeSetData(sdpisolver->lpcone, nlpineqs, dsdplpbegcol, dsdplprow, dsdplpval) );
1408  }
1409  else
1410  {
1411  DSDP_CALL( LPConeSetData(sdpisolver->lpcone, nlpineqs + 1, dsdplpbegcol, dsdplprow, dsdplpval) );
1412  }
1413 #ifdef SCIP_MORE_DEBUG
1414  LPConeView(sdpisolver->lpcone);
1415 #endif
1416  }
1417 
1418  SCIPdebugMessage("Calling DSDP-Solve for SDP (%d) \n", sdpisolver->sdpcounter);
1419 
1420  DSDP_CALL( DSDPSetGapTolerance(sdpisolver->dsdp, sdpisolver->gaptol) ); /* set DSDP's tolerance for duality gap */
1421  DSDP_CALL( DSDPSetRTolerance(sdpisolver->dsdp, sdpisolver->sdpsolverfeastol) ); /* set DSDP's tolerance for the SDP-constraints */
1422  if ( sdpisolver-> sdpinfo )
1423  {
1424  DSDP_CALL( DSDPSetStandardMonitor(sdpisolver->dsdp, 1) ); /* output DSDP information after every 1 iteration */
1425  }
1426 
1427  /* set the penalty parameter (only if rbound = TRUE, otherwise we had to add everything ourselves) */
1428  if ( penaltyparam >= sdpisolver->epsilon && rbound ) /* in sdpisolverSolve this is called with an exact 0 */
1429  {
1430  DSDP_CALL( DSDPSetPenaltyParameter(sdpisolver->dsdp, penaltyparam) );
1431  DSDP_CALL( DSDPUsePenalty(sdpisolver->dsdp, 1) );
1432  }
1433  else
1434  {
1435  /* set the penalty parameter to the default value */
1436  DSDP_CALL( DSDPSetPenaltyParameter(sdpisolver->dsdp, sdpisolver->penaltyparam) );
1437  }
1438 
1439  /* set the starting solution */
1440  if ( starty != NULL )
1441  {
1442  for (i = 0; i < sdpisolver->nactivevars; i++) /* we iterate over the variables in DSDP */
1443  {
1444  DSDP_CALL( DSDPSetY0(sdpisolver->dsdp, i + 1, starty[sdpisolver->dsdptoinputmapper[i]]) ); /* i+1 since DSDP uses indices 1 to n */
1445  }
1446  }
1447 
1448  /* start the solving process */
1449  DSDP_CALLM( DSDPSetup(sdpisolver->dsdp) );
1450  /* if there is a timelimit, set the corresponding callback */
1451  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, timelimit) )
1452  {
1453  DSDP_CALLM( DSDPSetMonitor(sdpisolver->dsdp, checkTimeLimitDSDP, (void*) &timings) );
1454  }
1455  /* if preoptimal solutions should be saved for warmstarting purposes, set the corresponding callback */
1456  if ( sdpisolver->preoptimalgap >= 0.0 )
1457  {
1458  DSDP_CALL( DSDPSetMonitor(sdpisolver->dsdp, checkGapSetPreoptimalSol, (void*) sdpisolver) );
1459  }
1460  DSDP_CALL( DSDPSolve(sdpisolver->dsdp) );
1461 
1462  sdpisolver->nsdpcalls++;
1463  DSDP_CALL( DSDPGetIts(sdpisolver->dsdp, &(sdpisolver->niterations)) );
1464 
1465  /* check if solving was stopped because of the time limit */
1466  if ( timings.stopped )
1467  {
1468  sdpisolver->timelimit = TRUE;
1469  sdpisolver->solved = FALSE;
1470  }
1471  else
1472  {
1473  sdpisolver->timelimit = FALSE;
1474  DSDP_CALL( DSDPComputeX(sdpisolver->dsdp) ); /* computes X and determines feasibility and unboundedness of the solution */
1475  sdpisolver->solved = TRUE;
1476  }
1477 
1478  /* if the problem has been stably solved but did not reach the required feasibility tolerance, even though the solver
1479  * reports feasibility, resolve it with adjusted tolerance */
1480  feastol = sdpisolver->sdpsolverfeastol;
1481 
1482  while ( SCIPsdpiSolverIsAcceptable(sdpisolver) && SCIPsdpiSolverIsDualFeasible(sdpisolver) && penaltyparam < sdpisolver->epsilon && feastol >= INFEASMINFEASTOL )
1483  {
1484  SCIP_Real* solvector;
1485  int nvarspointer;
1486  SCIP_Bool infeasible;
1487  int newiterations;
1488 
1489  /* get current solution */
1490  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &solvector, nvars) );
1491  nvarspointer = nvars;
1492  SCIP_CALL( SCIPsdpiSolverGetSol(sdpisolver, NULL, solvector, &nvarspointer) );
1493  assert( nvarspointer == nvars );
1494 
1495  /* check the solution for feasibility with regards to our tolerance */
1496  SCIP_CALL( SCIPsdpSolcheckerCheck(sdpisolver->bufmem, nvars, lb, ub, nsdpblocks, sdpblocksizes, sdpnblockvars, sdpconstnnonz,
1497  sdpconstnblocknonz, sdpconstrow, sdpconstcol, sdpconstval, sdpnnonz, sdpnblockvarnonz, sdpvar, sdprow, sdpcol, sdpval,
1498  indchanges, nremovedinds, blockindchanges, nlpcons, noldlpcons, lplhs, lprhs, rownactivevars, lpnnonz, lprow, lpcol, lpval,
1499  solvector, sdpisolver->feastol, sdpisolver->epsilon, &infeasible) );
1500 
1501  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &solvector);
1502 
1503  if ( infeasible )
1504  {
1505  SCIPdebugMessage("Solution feasible for DSDP but outside feasibility tolerance, changing SDPA feasibility tolerance from %f to %f\n",
1506  feastol, feastol * INFEASFEASTOLCHANGE);
1507  feastol *= INFEASFEASTOLCHANGE;
1508 
1509  if ( feastol >= INFEASMINFEASTOL )
1510  {
1511  /* update settings */
1512  DSDP_CALL( DSDPSetRTolerance(sdpisolver->dsdp, feastol) ); /* set DSDP's tolerance for the SDP-constraints */
1513 
1514  DSDP_CALL( DSDPSolve(sdpisolver->dsdp) );
1515 
1516  /* update number of SDP-iterations and -calls */
1517  sdpisolver->nsdpcalls++;
1518  DSDP_CALL( DSDPGetIts(sdpisolver->dsdp, &newiterations) );
1519  sdpisolver->niterations += newiterations;
1520 
1521  /* check if solving was stopped because of the time limit */
1522  if ( timings.stopped )
1523  {
1524  sdpisolver->timelimit = TRUE;
1525  sdpisolver->solved = FALSE;
1526  }
1527  else
1528  {
1529  sdpisolver->timelimit = FALSE;
1530  DSDP_CALL( DSDPComputeX(sdpisolver->dsdp) ); /* computes X and determines feasibility and unboundedness of the solution */
1531  sdpisolver->solved = TRUE;
1532  }
1533  }
1534  else
1535  {
1536  sdpisolver->solved = FALSE;
1537  SCIPmessagePrintInfo(sdpisolver->messagehdlr, "SDPA failed to reach required feasibility tolerance! \n");
1538  }
1539  }
1540  else
1541  break;
1542  }
1543 
1544  /*these arrays were used to give information to DSDP and were needed during solving and for computing X, so they may only be freed now*/
1545  if ( sdpconstnnonz > 0 )
1546  {
1547  BMSfreeBlockMemoryArray(sdpisolver->blkmem, &dsdpconstval, sdpconstnnonz);/*lint !e737 */
1548  BMSfreeBlockMemoryArray(sdpisolver->blkmem, &dsdpconstind, sdpconstnnonz);/*lint !e737 */
1549  }
1550 
1551  if ( sdpnnonz > 0 )
1552  {
1553  if ( penaltyparam > sdpisolver->epsilon && (! rbound) )
1554  {
1555  BMSfreeBlockMemoryArray(sdpisolver->blkmem, &dsdpval, sdpnnonz + nrnonz); /*lint !e737, !e776*/
1556  BMSfreeBlockMemoryArray(sdpisolver->blkmem, &dsdpind, sdpnnonz + nrnonz); /*lint !e737, !e776*/
1557  }
1558  else
1559  {
1560  BMSfreeBlockMemoryArray(sdpisolver->blkmem, &dsdpval, sdpnnonz);/*lint !e737 */
1561  BMSfreeBlockMemoryArray(sdpisolver->blkmem, &dsdpind, sdpnnonz);/*lint !e737 */
1562  }
1563  }
1564 
1565  if ( nlpcons > 0 || lpnnonz > 0 )
1566  {
1567  BMSfreeBlockMemoryArray(sdpisolver->blkmem, &dsdplpval, dsdpnlpnonz);/*lint !e644, !e737*/
1568  BMSfreeBlockMemoryArray(sdpisolver->blkmem, &dsdplprow, dsdpnlpnonz);/*lint !e737 */
1569  if ( penaltyparam > sdpisolver->epsilon && (! rbound) )
1570  {
1571  BMSfreeBlockMemoryArray(sdpisolver->blkmem, &dsdplpbegcol, sdpisolver->nactivevars + 3); /*lint !e737, !e776*/
1572  }
1573  else
1574  {
1575  BMSfreeBlockMemoryArray(sdpisolver->blkmem, &dsdplpbegcol, sdpisolver->nactivevars + 2); /*lint !e737, !e776*/
1576  }
1577  }
1578 
1579 #ifdef SCIP_DEBUG
1580  DSDP_CALL( DSDPStopReason(sdpisolver->dsdp, &reason) );
1581 
1582  switch ( reason )
1583  {
1584  case DSDP_CONVERGED:
1585  SCIPdebugMessage("DSDP converged!\n");
1586  break;
1587 
1588  case DSDP_INFEASIBLE_START:
1589  SCIPdebugMessage("DSDP started with an infeasible point!\n");
1590  break;
1591 
1592  case DSDP_SMALL_STEPS:
1593  SCIPdebugMessage("Short step lengths created by numerical difficulties prevented progress in DSDP!\n");
1594  break;
1595 
1596  case DSDP_INDEFINITE_SCHUR_MATRIX:
1597  SCIPdebugMessage("Schur Matrix in DSDP was indefinite but should have been positive semidefinite!\n");
1598  break;
1599 
1600  case DSDP_MAX_IT:
1601  SCIPdebugMessage("DSDP reached maximum number of iterations!\n");
1602  break;
1603 
1604  case DSDP_NUMERICAL_ERROR:
1605  SCIPdebugMessage("A numerical error occured in DSDP!\n");
1606  break;
1607 
1608  case DSDP_UPPERBOUND:
1609  SCIPdebugMessage("Dual objective value in DSDP reached upper bound.\n");
1610  break;
1611 
1612  case DSDP_USER_TERMINATION:
1613  SCIPdebugMessage("DSDP didn't stop solving, did you?\n");
1614  break;
1615 
1616  case CONTINUE_ITERATING:
1617  SCIPdebugMessage("DSDP wants to continue iterating but somehow was stopped!\n");
1618  break;
1619 
1620  default:
1621  SCIPdebugMessage("Unknown stopping reason in DSDP!\n");
1622  break;
1623  }
1624 #endif
1625 
1626  if ( penaltyparam >= sdpisolver->epsilon && sdpisolver->solved )
1627  {
1628  if ( rbound )
1629  {
1630  /* in this case we used the penalty-formulation of DSDP, so we can check their value of r */
1631  SCIP_Real rval;
1632  SCIP_Real trace;
1633 
1634  DSDP_CALL( DSDPGetR(sdpisolver->dsdp, &rval) );
1635 
1636  *feasorig = (rval < sdpisolver->feastol );
1637 
1638  /* only set sdpisolver->feasorig to true if we solved with objective, because only in this case we want to compute
1639  * the objective value by hand since it is numerically more stable then the result returned by DSDP */
1640  if ( withobj )
1641  sdpisolver->feasorig = *feasorig;
1642 
1643  /* if r > 0 or we are in debug mode, also check the primal bound */
1644 #ifdef NDEBUG
1645  if ( ! *feasorig )
1646  {
1647 #endif
1648  if ( penaltybound != NULL )
1649  {
1650  SCIPdebugMessage("Solution not feasible in original problem, r = %f\n", rval);
1651 
1652  /* get the trace of X to compare it with the penalty parameter */
1653  DSDP_CALL( DSDPGetTraceX(sdpisolver->dsdp, &trace) );
1654 
1655 #if 0 /* DSDP doesn't seem to adhere to its own feasiblity tolerance */
1656  assert( trace < penaltyparam + sdpisolver->feastol ); /* solution should be primal feasible */
1657 #endif
1658 
1659  /* if the relative gap is smaller than the tolerance, we return equality */
1660  if ( (penaltyparam - trace) / penaltyparam < PENALTYBOUNDTOL )
1661  {
1662  *penaltybound = TRUE;
1663  SCIPdebugMessage("Tr(X) = %f == %f = Gamma, penalty formulation not exact, Gamma should be increased or problem is infeasible\n",
1664  trace, penaltyparam);
1665  }
1666  else
1667  *penaltybound = FALSE;
1668  }
1669 #ifdef NDEBUG
1670  }
1671 #endif
1672  }
1673  else
1674  {
1675  SCIP_Real* dsdpsol;
1676  SCIP_Real trace;
1677 
1678  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &dsdpsol, sdpisolver->nactivevars + 1) ); /*lint !e776*/
1679  /* last entry of DSDPGetY needs to be the number of variables, will return an error otherwise */
1680  DSDP_CALL( DSDPGetY(sdpisolver->dsdp, dsdpsol, sdpisolver->nactivevars + 1) );
1681 
1682  *feasorig = (dsdpsol[sdpisolver->nactivevars] < sdpisolver->feastol); /* r is the last variable in DSDP, so the last entry gives us the value */
1683 #ifdef NDEBUG
1684  if ( ! *feasorig )
1685  {
1686 #endif
1687  if ( penaltybound != NULL )
1688  {
1689  SCIPdebugMessage("Solution not feasible in original problem, r = %f\n", dsdpsol[sdpisolver->nactivevars]);
1690 
1691  /* get the trace of X to compare it with the penalty parameter */
1692  DSDP_CALL( DSDPGetTraceX(sdpisolver->dsdp, &trace) );
1693 
1694 #if 0 /* DSDP doesn't seem to adhere to its own feasiblity tolerance */
1695  assert( trace < penaltyparam + sdpisolver->feastol ); /* solution should be primal feasible */
1696 #endif
1697 
1698  /* if the relative gap is smaller than the tolerance, we return equality */
1699  if ( (penaltyparam - trace) / penaltyparam < PENALTYBOUNDTOL )
1700  {
1701  *penaltybound = TRUE;
1702  SCIPdebugMessage("Tr(X) = %f == %f = Gamma, penalty formulation not exact, Gamma should be increased or problem is infeasible\n",
1703  trace, penaltyparam);
1704  }
1705  else
1706  *penaltybound = FALSE;
1707  }
1708 #ifdef NDEBUG
1709  }
1710 #endif
1711  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &dsdpsol);
1712  }
1713  }
1714 
1715  return SCIP_OKAY;
1716 }/*lint !e715 */
1722 /*
1723  * Solution Information Methods
1724  */
1725 
1730 SCIP_Bool SCIPsdpiSolverWasSolved(
1731  SCIP_SDPISOLVER* sdpisolver
1732  )
1733 {
1734  assert( sdpisolver != NULL );
1735  return sdpisolver->solved;
1736 }
1737 
1745  SCIP_SDPISOLVER* sdpisolver
1746  )
1747 {
1748  DSDPSolutionType pdfeasible;
1749 
1750  assert( sdpisolver != NULL );
1751  CHECK_IF_SOLVED_BOOL( sdpisolver );
1752 
1753  DSDP_CALL_BOOL( DSDPGetSolutionType(sdpisolver->dsdp, &pdfeasible) );
1754 
1755  if ( pdfeasible == DSDP_PDUNKNOWN )
1756  return FALSE;
1757 
1758  return TRUE;
1759 }
1760 
1762 SCIP_RETCODE SCIPsdpiSolverGetSolFeasibility(
1763  SCIP_SDPISOLVER* sdpisolver,
1764  SCIP_Bool* primalfeasible,
1765  SCIP_Bool* dualfeasible
1766  )
1767 {
1768  DSDPSolutionType pdfeasible;
1769 
1770  assert( sdpisolver != NULL );
1771  assert( primalfeasible != NULL );
1772  assert( dualfeasible != NULL );
1773  CHECK_IF_SOLVED( sdpisolver );
1774 
1775  DSDP_CALL( DSDPGetSolutionType(sdpisolver->dsdp, &pdfeasible) );
1776 
1777  switch ( pdfeasible )
1778  {
1779  case DSDP_PDFEASIBLE:
1780  *primalfeasible = TRUE;
1781  *dualfeasible = TRUE;
1782  break;
1783 
1784  case DSDP_UNBOUNDED:
1785  *primalfeasible = FALSE;
1786  *dualfeasible = TRUE;
1787  break;
1788 
1789  case DSDP_INFEASIBLE:
1790  *primalfeasible = TRUE;
1791  *dualfeasible = FALSE;
1792  break;
1793 
1794  default: /* should only include DSDP_PDUNKNOWN */
1795  SCIPerrorMessage("DSDP doesn't know if primal and dual solutions are feasible\n");
1796  return SCIP_LPERROR;
1797  }
1798 
1799  return SCIP_OKAY;
1800 }
1801 
1805  SCIP_SDPISOLVER* sdpisolver
1806  )
1807 {
1808  DSDPSolutionType pdfeasible;
1809 
1810  assert( sdpisolver != NULL );
1811  CHECK_IF_SOLVED_BOOL( sdpisolver );
1812 
1813  DSDP_CALL_BOOL( DSDPGetSolutionType(sdpisolver->dsdp, &pdfeasible) );
1814  if ( pdfeasible == DSDP_PDUNKNOWN )
1815  {
1816 /* SCIPerrorMessage("DSDP doesn't know if primal and dual solutions are feasible");
1817  SCIPABORT();
1818  return SCIP_LPERROR;*/
1819  SCIPdebugMessage("DSDP doesn't know if primal and dual solutions are feasible.");
1820  return FALSE;
1821  }
1822  else if ( pdfeasible == DSDP_INFEASIBLE )
1823  return TRUE;
1824 
1825  return FALSE;
1826 }
1827 
1831  SCIP_SDPISOLVER* sdpisolver
1832  )
1833 {
1834  DSDPSolutionType pdfeasible;
1835 
1836  assert( sdpisolver != NULL );
1837  CHECK_IF_SOLVED_BOOL( sdpisolver );
1838 
1839  DSDP_CALL_BOOL( DSDPGetSolutionType(sdpisolver->dsdp, &pdfeasible) );
1840  if ( pdfeasible == DSDP_PDUNKNOWN )
1841  {
1842 /* SCIPerrorMessage("DSDP doesn't know if primal and dual solutions are feasible");
1843  SCIPABORT();
1844  return SCIP_LPERROR;*/
1845  SCIPdebugMessage("DSDP doesn't know if primal and dual solutions are feasible");
1846  return FALSE;
1847  }
1848  else if ( pdfeasible == DSDP_UNBOUNDED )
1849  return TRUE;
1850 
1851  return FALSE;
1852 }
1853 
1857  SCIP_SDPISOLVER* sdpisolver
1858  )
1859 {
1860  DSDPSolutionType pdfeasible;
1861 
1862  assert( sdpisolver != NULL );
1863  CHECK_IF_SOLVED_BOOL( sdpisolver );
1864 
1865  DSDP_CALL_BOOL( DSDPGetSolutionType(sdpisolver->dsdp, &pdfeasible) );
1866  if ( pdfeasible == DSDP_PDUNKNOWN )
1867  {
1868  SCIPdebugMessage("DSDP doesn't know if primal and dual solutions are feasible");
1869  return FALSE;
1870  }
1871  else if ( pdfeasible == DSDP_UNBOUNDED )
1872  return FALSE;
1873 
1874  return TRUE;
1875 }
1876 
1880  SCIP_SDPISOLVER* sdpisolver
1881  )
1882 {
1883  DSDPSolutionType pdfeasible;
1884 
1885  assert( sdpisolver != NULL );
1886  CHECK_IF_SOLVED_BOOL( sdpisolver );
1887 
1888  DSDP_CALL_BOOL( DSDPGetSolutionType(sdpisolver->dsdp, &pdfeasible) );
1889  if ( pdfeasible == DSDP_PDUNKNOWN )
1890  {
1891  SCIPdebugMessage("DSDP doesn't know if primal and dual solutions are feasible");
1892  return FALSE;
1893  }
1894  else if ( pdfeasible == DSDP_UNBOUNDED )
1895  return TRUE;
1896 
1897  return FALSE;
1898 }
1899 
1903  SCIP_SDPISOLVER* sdpisolver
1904  )
1905 {
1906  DSDPSolutionType pdfeasible;
1907 
1908  assert( sdpisolver != NULL );
1909  CHECK_IF_SOLVED_BOOL( sdpisolver );
1910 
1911  DSDP_CALL_BOOL(DSDPGetSolutionType(sdpisolver->dsdp, &pdfeasible));
1912 
1913  if ( pdfeasible == DSDP_PDUNKNOWN )
1914  {
1915  SCIPdebugMessage("DSDP doesn't know if primal and dual solutions are feasible");
1916  return FALSE;
1917  }
1918  else if ( pdfeasible == DSDP_INFEASIBLE )
1919  return TRUE;
1920 
1921  return FALSE;
1922 }
1923 
1927  SCIP_SDPISOLVER* sdpisolver
1928  )
1929 {
1930  DSDPSolutionType pdfeasible;
1931 
1932  assert( sdpisolver != NULL );
1933  CHECK_IF_SOLVED_BOOL( sdpisolver );
1934 
1935  DSDP_CALL_BOOL( DSDPGetSolutionType(sdpisolver->dsdp, &pdfeasible) );
1936 
1937  if ( pdfeasible == DSDP_PDUNKNOWN )
1938  {
1939  SCIPdebugMessage("DSDP doesn't know if primal and dual solutions are feasible");
1940  return FALSE;
1941  }
1942  else if ( pdfeasible == DSDP_INFEASIBLE )
1943  return FALSE;
1944 
1945  return TRUE;
1946 }
1947 
1949 SCIP_Bool SCIPsdpiSolverIsConverged(
1950  SCIP_SDPISOLVER* sdpisolver
1951  )
1952 {
1953  DSDPTerminationReason reason;
1954 
1955  assert( sdpisolver != NULL );
1956 
1957  if ( sdpisolver->timelimit )
1958  return FALSE;
1959 
1960  if ( ! sdpisolver->solved )
1961  return FALSE;
1962 
1963  DSDP_CALL_BOOL( DSDPStopReason(sdpisolver->dsdp, &reason) );
1964 
1965  if ( reason == DSDP_CONVERGED )
1966  return TRUE;
1967 
1968  return FALSE;
1969 }
1970 
1972 SCIP_Bool SCIPsdpiSolverIsObjlimExc(
1973  SCIP_SDPISOLVER* sdpisolver
1974  )
1975 {/*lint --e{715}*/
1976  SCIPdebugMessage("Method not implemented for DSDP, as objective limit is given as an ordinary LP-constraint, so in case the objective limit was "
1977  "exceeded, the problem will be reported as infeasible ! \n");
1978 
1979  return FALSE;
1980 }
1981 
1983 SCIP_Bool SCIPsdpiSolverIsIterlimExc(
1984  SCIP_SDPISOLVER* sdpisolver
1985  )
1986 {
1987  DSDPTerminationReason reason;
1988 
1989  assert( sdpisolver != NULL );
1990  CHECK_IF_SOLVED_BOOL( sdpisolver );
1991 
1992  DSDP_CALL_BOOL( DSDPStopReason(sdpisolver->dsdp, &reason) );
1993 
1994  if ( reason == DSDP_MAX_IT )
1995  return TRUE;
1996 
1997  return FALSE;
1998 }
1999 
2001 SCIP_Bool SCIPsdpiSolverIsTimelimExc(
2002  SCIP_SDPISOLVER* sdpisolver
2003  )
2004 {
2005  assert( sdpisolver != NULL );
2006 
2007  return sdpisolver->timelimit;
2008 }
2009 
2021  SCIP_SDPISOLVER* sdpisolver
2022  )
2023 {
2024  DSDPTerminationReason reason;
2025  int dsdpreturn;
2026 
2027  assert( sdpisolver != NULL );
2028 
2029  if ( sdpisolver->dsdp == NULL || (! sdpisolver->solved) )
2030  return -1;
2031 
2032  if ( sdpisolver->timelimit )
2033  return 5;
2034 
2035  dsdpreturn = DSDPStopReason(sdpisolver->dsdp, &reason);
2036 
2037  if (dsdpreturn != 0)
2038  {
2039  SCIPerrorMessage("DSDP-Error <%d> in function call.\n", dsdpreturn);
2040  return 7;
2041  }
2042 
2043  switch ( reason )/*lint --e{788}*/
2044  {
2045  case DSDP_CONVERGED:
2046  return 0;
2047 
2048  case DSDP_INFEASIBLE_START:
2049  return 1;
2050 
2051  case DSDP_SMALL_STEPS:
2052  return 2;
2053 
2054  case DSDP_INDEFINITE_SCHUR_MATRIX:
2055  return 2;
2056 
2057  case DSDP_MAX_IT:
2058  return 4;
2059 
2060  case DSDP_NUMERICAL_ERROR:
2061  return 2;
2062 
2063  case DSDP_UPPERBOUND:
2064  return 3;
2065 
2066  case DSDP_USER_TERMINATION:
2067  return 5;
2068 
2069  default:
2070  return 7;
2071  }
2072 }
2073 
2075 SCIP_Bool SCIPsdpiSolverIsOptimal(
2076  SCIP_SDPISOLVER* sdpisolver
2077  )
2078 {
2079  assert( sdpisolver != NULL );
2080  return (SCIPsdpiSolverIsConverged(sdpisolver) && SCIPsdpiSolverIsPrimalFeasible(sdpisolver) && SCIPsdpiSolverIsDualFeasible(sdpisolver));
2081 }
2082 
2085 SCIP_Bool SCIPsdpiSolverIsAcceptable(
2086  SCIP_SDPISOLVER* sdpisolver
2087  )
2088 {
2089  assert( sdpisolver != NULL );
2090 
2091  return SCIPsdpiSolverIsConverged(sdpisolver);
2092 }
2093 
2095 SCIP_RETCODE SCIPsdpiSolverIgnoreInstability(
2096  SCIP_SDPISOLVER* sdpisolver,
2097  SCIP_Bool* success
2098  )
2099 {/*lint --e{715}*/
2100  SCIPdebugMessage("Not implemented yet\n");
2101  return SCIP_LPERROR;
2102 }
2103 
2105 SCIP_RETCODE SCIPsdpiSolverGetObjval(
2106  SCIP_SDPISOLVER* sdpisolver,
2107  SCIP_Real* objval
2108  )
2109 {
2110  SCIP_Real* dsdpsol;
2111  int dsdpnvars;
2112 
2113  assert( sdpisolver != NULL );
2114  assert( objval != NULL );
2115  CHECK_IF_SOLVED( sdpisolver );
2116 
2117  dsdpnvars = sdpisolver->penaltyworbound ? sdpisolver->nactivevars + 1 : sdpisolver->nactivevars; /* in the first case we added r as an explicit var */
2118 
2119  if ( sdpisolver->penalty && ( ! sdpisolver->feasorig ))
2120  {
2121  /* in this case we cannot really trust the solution given by DSDP, since changes in the value of r much less than epsilon can
2122  * cause huge changes in the objective, so using the objective value given by DSDP is numerically more stable */
2123  DSDP_CALL( DSDPGetDObjective(sdpisolver->dsdp, objval) );
2124  *objval = -1*(*objval); /*DSDP maximizes instead of minimizing, so the objective values were multiplied by -1 when inserted */
2125  }
2126  else
2127  {
2128  int v;
2129 
2130  /* since the objective value given by DSDP sometimes differs slightly from the correct value for the given solution,
2131  * we get the solution from DSDP and compute the correct objective value */
2132  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &dsdpsol, dsdpnvars) );
2133  DSDP_CALL( DSDPGetY(sdpisolver->dsdp, dsdpsol, dsdpnvars) ); /* last entry needs to be the number of variables, will return an error otherwise */
2134 
2135  /* use the solution to compute the correct objective value */
2136  *objval = 0.0;
2137  for (v = 0; v < sdpisolver->nactivevars; v++)
2138  *objval += sdpisolver->objcoefs[v] * dsdpsol[v];
2139  }
2140 
2141  /* as we didn't add the fixed (lb = ub) variables to dsdp, we have to add their contributions to the objective as well */
2142  *objval += sdpisolver->fixedvarsobjcontr;
2143 
2144  if ( ( ! sdpisolver->penalty ) || sdpisolver->feasorig )
2145  {
2146  BMSfreeBlockMemoryArray(sdpisolver->blkmem, &dsdpsol, dsdpnvars);/*lint !e737 */
2147  }
2148 
2149  return SCIP_OKAY;
2150 }
2151 
2156 SCIP_RETCODE SCIPsdpiSolverGetSol(
2157  SCIP_SDPISOLVER* sdpisolver,
2158  SCIP_Real* objval,
2159  SCIP_Real* dualsol,
2160  int* dualsollength
2162  )
2163 {
2164  SCIP_Real* dsdpsol;
2165  int v;
2166  int dsdpnvars;
2167 
2168  assert( sdpisolver != NULL );
2169  assert( dualsollength != NULL );
2170  CHECK_IF_SOLVED( sdpisolver );
2171 
2172  dsdpnvars = sdpisolver->penaltyworbound ? sdpisolver->nactivevars + 1 : sdpisolver->nactivevars; /* in the first case we added r as an explicit var */
2173 
2174  if ( *dualsollength > 0 )
2175  {
2176  assert( dualsol != NULL );
2177  if ( *dualsollength < sdpisolver->nvars )
2178  {
2179  SCIPdebugMessage("The given array in SCIPsdpiSolverGetSol only had length %d, but %d was needed", *dualsollength, sdpisolver->nvars);
2180  *dualsollength = sdpisolver->nvars;
2181 
2182  return SCIP_OKAY;
2183  }
2184 
2185  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &dsdpsol, dsdpnvars) );
2186  DSDP_CALL( DSDPGetY(sdpisolver->dsdp, dsdpsol, dsdpnvars) ); /* last entry needs to be the number of variables, will return an error otherwise */
2187 
2188  /* insert the entries into dualsol, for non-fixed vars we copy those from dsdp, the rest are the saved entries from inserting (they equal lb=ub) */
2189  for (v = 0; v < sdpisolver->nvars; v++)
2190  {
2191  if (sdpisolver->inputtodsdpmapper[v] > -1)
2192  {
2193  /* minus one because the inputtodsdpmapper gives the dsdp indices which start at one, but the array starts at 0 */
2194  dualsol[v] = dsdpsol[sdpisolver->inputtodsdpmapper[v] - 1];
2195  }
2196  else
2197  {
2198  /* this is the value that was saved when inserting, as this variable has lb=ub */
2199  dualsol[v] = sdpisolver->fixedvarsval[(-1 * sdpisolver->inputtodsdpmapper[v]) - 1]; /*lint !e679*/
2200  }
2201  }
2202 
2203  if ( objval != NULL )
2204  {
2205  if ( sdpisolver->penalty && ( ! sdpisolver->feasorig ))
2206  {
2207  /* in this case we cannot really trust the solution given by DSDP, since changes in the value of r much less than epsilon can
2208  * cause huge changes in the objective, so using the objective value given by DSDP is numerically more stable */
2209  DSDP_CALL( DSDPGetDObjective(sdpisolver->dsdp, objval) );
2210  *objval = -1*(*objval); /*DSDP maximizes instead of minimizing, so the objective values were multiplied by -1 when inserted */
2211  }
2212  else
2213  {
2214  /* use the solution to compute the correct objective value */
2215  *objval = 0.0;
2216  for (v = 0; v < sdpisolver->nactivevars; v++)
2217  *objval += sdpisolver->objcoefs[v] * dsdpsol[v];
2218  }
2219 
2220  /* as we didn't add the fixed (lb = ub) variables to dsdp, we have to add their contributions to the objective as well */
2221  *objval += sdpisolver->fixedvarsobjcontr;
2222  }
2223 
2224  BMSfreeBlockMemoryArray(sdpisolver->blkmem, &dsdpsol, dsdpnvars);/*lint !e737 */
2225  }
2226  else if ( objval != NULL )
2227  {
2228  SCIP_CALL( SCIPsdpiSolverGetObjval(sdpisolver, objval) );
2229  }
2230 
2231  return SCIP_OKAY;
2232 }
2233 
2236  SCIP_SDPISOLVER* sdpisolver,
2237  int nblocks,
2238  int* startXnblocknonz
2240  )
2241 {
2242  SCIPdebugMessage("Not implemented yet\n");
2243 
2244  return SCIP_PLUGINNOTFOUND;
2245 }
2246 
2254 SCIP_RETCODE SCIPsdpiSolverGetPreoptimalSol(
2255  SCIP_SDPISOLVER* sdpisolver,
2256  SCIP_Bool* success,
2257  SCIP_Real* dualsol,
2258  int* dualsollength,
2260  int nblocks,
2261  int* startXnblocknonz,
2263  int** startXrow,
2264  int** startXcol,
2265  SCIP_Real** startXval
2266  )
2267 {
2268  int v;
2269 
2270  assert( sdpisolver != NULL );
2271  assert( success != NULL );
2272  assert( dualsol != NULL );
2273  assert( dualsollength != NULL );
2274  assert( *dualsollength >= 0 );
2275 
2276  /* we do not want to return a primal matrix, since it is not used by DSDP for warmstarting purposes */
2277  assert( nblocks == -1 );
2278 
2279  if ( ! sdpisolver->preoptimalsolexists )
2280  {
2281  SCIPdebugMessage("Failed to retrieve preoptimal solution for warmstarting purposes. \n");
2282  *success = FALSE;
2283  return SCIP_OKAY;
2284  }
2285 
2286  if ( *dualsollength < sdpisolver->nvars )
2287  {
2288  SCIPdebugMessage("Insufficient memory in SCIPsdpiSolverGetPreoptimalSol: needed %d, given %d\n", sdpisolver->nvars, *dualsollength);
2289  *success = FALSE;
2290  *dualsollength = sdpisolver->nvars;
2291  return SCIP_OKAY;
2292  }
2293 
2294  for (v = 0; v < sdpisolver->nvars; v++)
2295  {
2296  if (sdpisolver->inputtodsdpmapper[v] > -1)
2297  {
2298  /* minus one because the inputtodsdpmapper gives the dsdp indices which start at one, but the array starts at 0 */
2299  dualsol[v] = sdpisolver->preoptimalsol[sdpisolver->inputtodsdpmapper[v] - 1];
2300  }
2301  else
2302  {
2303  /* this is the value that was saved when inserting, as this variable has lb=ub */
2304  dualsol[v] = sdpisolver->fixedvarsval[(-1 * sdpisolver->inputtodsdpmapper[v]) - 1]; /*lint !e679*/
2305  }
2306  }
2307 
2308 
2309  *dualsollength = sdpisolver->nvars;
2310  *success = TRUE;
2311 
2312  return SCIP_OKAY;
2313 }
2314 
2323  SCIP_SDPISOLVER* sdpisolver,
2324  SCIP_Real* lbvars,
2325  SCIP_Real* ubvars,
2326  int* arraylength
2328  )
2329 {
2330  SCIP_Real* lbvarsdsdp;
2331  SCIP_Real* ubvarsdsdp;
2332  int i;
2333 
2334  assert( sdpisolver != NULL );
2335  assert( lbvars != NULL );
2336  assert( ubvars != NULL );
2337  assert( arraylength != NULL );
2338  assert( *arraylength >= 0 );
2339  CHECK_IF_SOLVED( sdpisolver );
2340 
2341  /* check if the arrays are long enough */
2342  if ( *arraylength < sdpisolver->nvars )
2343  {
2344  *arraylength = sdpisolver->nvars;
2345  SCIPdebugMessage("Insufficient length of array in SCIPsdpiSolverGetPrimalBoundVars (gave %d, needed %d)\n", *arraylength, sdpisolver->nvars);
2346  return SCIP_OKAY;
2347  }
2348 
2349  /* allocate memory for the arrays given to DSDP */
2350  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &lbvarsdsdp, sdpisolver->nactivevars) );
2351  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &ubvarsdsdp, sdpisolver->nactivevars) );
2352 
2353  /* get the values for the active variables from DSDP */
2354  DSDP_CALL( BConeCopyX(sdpisolver->bcone, lbvarsdsdp, ubvarsdsdp, sdpisolver->nactivevars) );
2355 
2356  /* copy them to the right spots of lbvars & ubvars */
2357  for (i = 0; i < sdpisolver->nvars; i++)
2358  {
2359  if ( sdpisolver->inputtodsdpmapper[i] < 0 )
2360  {
2361  /* if the variable was fixed, it didn't exist in the relaxation, so we set the value to 0
2362  * (as DSDP already uses this value for unbounded vars) */
2363  lbvars[i] = 0;
2364  ubvars[i] = 0;
2365  }
2366  else
2367  {
2368  lbvars[i] = lbvarsdsdp[sdpisolver->inputtodsdpmapper[i] - 1];
2369  ubvars[i] = ubvarsdsdp[sdpisolver->inputtodsdpmapper[i] - 1];
2370  }
2371  }
2372 
2373  /* free allocated memory */
2374  BMSfreeBlockMemoryArrayNull(sdpisolver->blkmem, &ubvarsdsdp, sdpisolver->nactivevars);
2375  BMSfreeBlockMemoryArrayNull(sdpisolver->blkmem, &lbvarsdsdp, sdpisolver->nactivevars);
2376 
2377  return SCIP_OKAY;
2378 }
2379 
2381 SCIP_RETCODE SCIPsdpiSolverGetPrimalNonzeros(
2382  SCIP_SDPISOLVER* sdpisolver,
2383  int nblocks,
2384  int* startXnblocknonz
2385  )
2386 {/*lint --e{715,818}*/
2387  SCIPdebugMessage("Not implemented yet\n");
2388  return SCIP_LPERROR;
2389 }
2390 
2395 SCIP_RETCODE SCIPsdpiSolverGetPrimalMatrix(
2396  SCIP_SDPISOLVER* sdpisolver,
2397  int nblocks,
2398  int* startXnblocknonz,
2400  int** startXrow,
2401  int** startXcol,
2402  SCIP_Real** startXval
2403  )
2404 {/*lint --e{715,818}*/
2405  SCIPdebugMessage("Not implemented yet\n");
2406  return SCIP_LPERROR;
2407 }
2408 
2411  SCIP_SDPISOLVER* sdpisolver
2412  )
2413 {/*lint --e{715}*/
2414  SCIPdebugMessage("Not implemented yet\n");
2415  return SCIP_LPERROR;
2416 }
2417 
2419 SCIP_RETCODE SCIPsdpiSolverGetIterations(
2420  SCIP_SDPISOLVER* sdpisolver,
2421  int* iterations
2422  )
2423 {
2424  assert( sdpisolver != NULL );
2425  assert( iterations != NULL );
2426 
2427  if ( sdpisolver->timelimitinitial )
2428  *iterations = 0;
2429  else
2430  *iterations = sdpisolver->niterations;
2431 
2432  return SCIP_OKAY;
2433 }
2434 
2436 SCIP_RETCODE SCIPsdpiSolverGetSdpCalls(
2437  SCIP_SDPISOLVER* sdpisolver,
2438  int* calls
2439  )
2440 {
2441  assert( sdpisolver != NULL );
2442  assert( calls != NULL );
2443 
2444  if ( sdpisolver->timelimitinitial )
2445  *calls = 0;
2446  else
2447  *calls = sdpisolver->nsdpcalls;
2448 
2449  return SCIP_OKAY;
2450 }
2451 
2453 SCIP_RETCODE SCIPsdpiSolverSettingsUsed(
2454  SCIP_SDPISOLVER* sdpisolver,
2455  SCIP_SDPSOLVERSETTING* usedsetting
2456  )
2457 {
2458  assert( sdpisolver != NULL );
2459  assert( usedsetting != NULL );
2460 
2461  if ( ! SCIPsdpiSolverIsAcceptable(sdpisolver) )
2462  *usedsetting = SCIP_SDPSOLVERSETTING_UNSOLVED;
2463  else
2464  *usedsetting = sdpisolver->usedsetting;
2465 
2466  return SCIP_OKAY;
2467 }
2468 
2474 /*
2475  * Numerical Methods
2476  */
2477 
2482 SCIP_Real SCIPsdpiSolverInfinity(
2483  SCIP_SDPISOLVER* sdpisolver
2484  )
2485 {
2486  return 1E+20; /* default infinity from SCIP */
2487 }/*lint !e715 */
2488 
2490 SCIP_Bool SCIPsdpiSolverIsInfinity(
2491  SCIP_SDPISOLVER* sdpisolver,
2492  SCIP_Real val
2493  )
2494 {
2495  return ((val <= -SCIPsdpiSolverInfinity(sdpisolver)) || (val >= SCIPsdpiSolverInfinity(sdpisolver)));
2496 }
2497 
2499 SCIP_RETCODE SCIPsdpiSolverGetRealpar(
2500  SCIP_SDPISOLVER* sdpisolver,
2501  SCIP_SDPPARAM type,
2502  SCIP_Real* dval
2503  )
2504 {
2505  assert( sdpisolver != NULL );
2506  assert( dval != NULL );
2507 
2508  switch( type )/*lint --e{788}*/
2509  {
2510  case SCIP_SDPPAR_EPSILON:
2511  *dval = sdpisolver->epsilon;
2512  break;
2513  case SCIP_SDPPAR_GAPTOL:
2514  *dval = sdpisolver->gaptol;
2515  break;
2516  case SCIP_SDPPAR_FEASTOL:
2517  *dval = sdpisolver->feastol;
2518  break;
2520  *dval = sdpisolver->sdpsolverfeastol;
2521  break;
2523  *dval = sdpisolver->penaltyparam;
2524  break;
2525  case SCIP_SDPPAR_OBJLIMIT:
2526  *dval = sdpisolver->objlimit;
2527  break;
2529  *dval = sdpisolver->preoptimalgap;
2530  break;
2531  default:
2532  return SCIP_PARAMETERUNKNOWN;
2533  }
2534 
2535  return SCIP_OKAY;
2536 }
2537 
2539 SCIP_RETCODE SCIPsdpiSolverSetRealpar(
2540  SCIP_SDPISOLVER* sdpisolver,
2541  SCIP_SDPPARAM type,
2542  SCIP_Real dval
2543  )
2544 {
2545  assert( sdpisolver != NULL );
2546 
2547  switch( type )/*lint --e{788}*/
2548  {
2549  case SCIP_SDPPAR_EPSILON:
2550  sdpisolver->epsilon = dval;
2551  SCIPdebugMessage("Setting sdpisolver epsilon to %f.\n", dval);
2552  break;
2553  case SCIP_SDPPAR_GAPTOL:
2554  sdpisolver->gaptol = dval;
2555  SCIPdebugMessage("Setting sdpisolver gaptol to %f.\n", dval);
2556  break;
2557  case SCIP_SDPPAR_FEASTOL:
2558  sdpisolver->feastol = dval;
2559  SCIPdebugMessage("Setting sdpisolver feastol to %f.\n", dval);
2560  break;
2562  sdpisolver->sdpsolverfeastol = dval;
2563  SCIPdebugMessage("Setting sdpisolver sdpsolverfeastol to %f.\n", dval);
2564  break;
2566  sdpisolver->penaltyparam = dval;
2567  SCIPdebugMessage("Setting sdpisolver penaltyparameter to %f.\n", dval);
2568  break;
2569  case SCIP_SDPPAR_OBJLIMIT:
2570  SCIPdebugMessage("Setting sdpisolver objlimit to %f.\n", dval);
2571  sdpisolver->objlimit = dval;
2572  break;
2574  SCIPdebugMessage("Parameter SCIP_SDPPAR_LAMBDASTAR not used by DSDP"); /* this parameter is only used by SDPA */
2575  break;
2577  SCIPdebugMessage("Setting sdpisolver preoptgap to %f.\n", dval);
2578  sdpisolver->preoptimalgap = dval;
2579  break;
2580  default:
2581  return SCIP_PARAMETERUNKNOWN;
2582  }
2583 
2584  return SCIP_OKAY;
2585 }
2586 
2588 SCIP_RETCODE SCIPsdpiSolverGetIntpar(
2589  SCIP_SDPISOLVER* sdpisolver,
2590  SCIP_SDPPARAM type,
2591  int* ival
2592  )
2593 {
2594  assert( sdpisolver != NULL );
2595 
2596  switch( type )/*lint --e{788}*/
2597  {
2598  case SCIP_SDPPAR_SDPINFO:
2599  *ival = (int) sdpisolver->sdpinfo;
2600  SCIPdebugMessage("Getting sdpisolver information output (%d).\n", *ival);
2601  break;
2602  default:
2603  return SCIP_PARAMETERUNKNOWN;
2604  }
2605 
2606  return SCIP_OKAY;
2607 }
2608 
2610 SCIP_RETCODE SCIPsdpiSolverSetIntpar(
2611  SCIP_SDPISOLVER* sdpisolver,
2612  SCIP_SDPPARAM type,
2613  int ival
2614  )
2615 {
2616  assert( sdpisolver != NULL );
2617 
2618  switch( type )/*lint --e{788}*/
2619  {
2620  case SCIP_SDPPAR_SDPINFO:
2621  sdpisolver->sdpinfo = (SCIP_Bool) ival;
2622  SCIPdebugMessage("Setting sdpisolver information output (%d).\n", ival);
2623  break;
2624  default:
2625  return SCIP_PARAMETERUNKNOWN;
2626  }
2627 
2628  return SCIP_OKAY;
2629 }
2630 
2632 SCIP_RETCODE SCIPsdpiSolverComputeLambdastar(
2633  SCIP_SDPISOLVER* sdpisolver,
2634  SCIP_Real maxguess
2635  )
2636 {
2637  SCIPdebugMessage("Lambdastar parameter not used by DSDP"); /* this parameter is only used by SDPA */
2638 
2639  return SCIP_OKAY;
2640 }/*lint !e715 */
2641 
2644  SCIP_SDPISOLVER* sdpisolver,
2645  SCIP_Real maxcoeff,
2646  SCIP_Real* penaltyparam
2647  )
2648 {
2649  SCIP_Real compval;
2650 
2651  assert( sdpisolver != NULL );
2652  assert( penaltyparam != NULL );
2653 
2654  compval = PENALTYPARAM_FACTOR * maxcoeff;
2655 
2656  if ( compval < MIN_PENALTYPARAM )
2657  {
2658  SCIPdebugMessage("Setting penaltyparameter to %f.\n", MIN_PENALTYPARAM);
2659  sdpisolver->penaltyparam = MIN_PENALTYPARAM;
2660  *penaltyparam = MIN_PENALTYPARAM;
2661  }
2662  else if ( compval > MAX_PENALTYPARAM )
2663  {
2664  SCIPdebugMessage("Setting penaltyparameter to %f.\n", MAX_PENALTYPARAM);
2665  sdpisolver->penaltyparam = MAX_PENALTYPARAM;
2666  *penaltyparam = MAX_PENALTYPARAM;
2667  }
2668  else
2669  {
2670  SCIPdebugMessage("Setting penaltyparameter to %f.\n", compval);
2671  sdpisolver->penaltyparam = compval;
2672  *penaltyparam = compval;
2673  }
2674  return SCIP_OKAY;
2675 }
2676 
2679  SCIP_SDPISOLVER* sdpisolver,
2680  SCIP_Real penaltyparam,
2681  SCIP_Real* maxpenaltyparam
2682  )
2683 {
2684  SCIP_Real compval;
2685 
2686  assert( sdpisolver != NULL );
2687  assert( maxpenaltyparam != NULL );
2688 
2689  compval = penaltyparam * MAXPENALTYPARAM_FACTOR;
2690 
2691  if ( compval < MAX_MAXPENALTYPARAM )
2692  {
2693  *maxpenaltyparam = compval;
2694  SCIPdebugMessage("Setting maximum penaltyparameter to %f.\n", compval);
2695  }
2696  else
2697  {
2698  *maxpenaltyparam = MAX_MAXPENALTYPARAM;
2699  SCIPdebugMessage("Setting penaltyparameter to %f.\n", MAX_MAXPENALTYPARAM);
2700  }
2701 
2702  /* if the maximum penalty parameter is smaller than the initial penalty paramater, we decrease the initial one correspondingly */
2703  if ( sdpisolver->penaltyparam > *maxpenaltyparam )
2704  {
2705  SCIPdebugMessage("Decreasing penaltyparameter of %f to maximum penalty paramater of %f.\n", sdpisolver->penaltyparam, *maxpenaltyparam);
2706  sdpisolver->penaltyparam = *maxpenaltyparam;
2707  }
2708  return SCIP_OKAY;
2709 }
2710 
2716 /*
2717  * File Interface Methods
2718  */
2719 
2724 SCIP_RETCODE SCIPsdpiSolverReadSDP(
2725  SCIP_SDPISOLVER* sdpisolver,
2726  const char* fname
2727  )
2728 {/*lint --e{715}*/
2729  SCIPdebugMessage("Not implemented yet\n");
2730  return SCIP_LPERROR;
2731 }
2732 
2734 SCIP_RETCODE SCIPsdpiSolverWriteSDP(
2735  SCIP_SDPISOLVER* sdpisolver,
2736  const char* fname
2737  )
2738 {/*lint --e{715}*/
2739  SCIPdebugMessage("Not implemented yet\n");
2740  return SCIP_LPERROR;
2741 }
2742 
SCIP_Bool SCIPsdpiSolverIsConverged(SCIP_SDPISOLVER *sdpisolver)
int SCIPsdpiSolverGetInternalStatus(SCIP_SDPISOLVER *sdpisolver)
SCIP_Bool SCIPsdpiSolverIsPrimalFeasible(SCIP_SDPISOLVER *sdpisolver)
SCIP_Real SCIPsdpiSolverGetDefaultSdpiSolverGaptol(void)
SCIP_Bool SCIPsdpiSolverIsPrimalUnbounded(SCIP_SDPISOLVER *sdpisolver)
SCIP_Bool SCIPsdpiSolverIsObjlimExc(SCIP_SDPISOLVER *sdpisolver)
SCIP_Bool SCIPsdpiSolverIsDualFeasible(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverGetSol(SCIP_SDPISOLVER *sdpisolver, SCIP_Real *objval, SCIP_Real *dualsol, int *dualsollength)
SCIP_Real SCIPsdpiSolverInfinity(SCIP_SDPISOLVER *sdpisolver)
static SCIP_Bool isFixed(SCIP_SDPISOLVER *sdpisolver, SCIP_Real lb, SCIP_Real ub)
const char * SCIPsdpiSolverGetSolverDesc(void)
#define CHECK_IF_SOLVED_BOOL(sdpisolver)
enum SCIP_SDPSolverSetting SCIP_SDPSOLVERSETTING
Definition: type_sdpi.h:80
SCIP_RETCODE SCIPsdpiSolverGetIntpar(SCIP_SDPISOLVER *sdpisolver, SCIP_SDPPARAM type, int *ival)
int SCIPsdpiSolverGetDefaultSdpiSolverNpenaltyIncreases(void)
#define DSDP_CALL_BOOL(x)
SCIP_RETCODE SCIPsdpiSolverLoadAndSolveWithPenalty(SCIP_SDPISOLVER *sdpisolver, SCIP_Real penaltyparam, SCIP_Bool withobj, SCIP_Bool rbound, int nvars, SCIP_Real *obj, SCIP_Real *lb, SCIP_Real *ub, int nsdpblocks, int *sdpblocksizes, int *sdpnblockvars, int sdpconstnnonz, int *sdpconstnblocknonz, int **sdpconstrow, int **sdpconstcol, SCIP_Real **sdpconstval, int sdpnnonz, int **sdpnblockvarnonz, int **sdpvar, int ***sdprow, int ***sdpcol, SCIP_Real ***sdpval, int **indchanges, int *nremovedinds, int *blockindchanges, int nremovedblocks, int nlpcons, int noldlpcons, SCIP_Real *lplhs, SCIP_Real *lprhs, int *rownactivevars, int lpnnonz, int *lprow, int *lpcol, SCIP_Real *lpval, SCIP_Real *starty, int *startZnblocknonz, int **startZrow, int **startZcol, SCIP_Real **startZval, int *startXnblocknonz, int **startXrow, int **startXcol, SCIP_Real **startXval, SCIP_SDPSOLVERSETTING startsettings, SCIP_Real timelimit, SCIP_Bool *feasorig, SCIP_Bool *penaltybound)
SCIP_RETCODE SCIPsdpiSolverSettingsUsed(SCIP_SDPISOLVER *sdpisolver, SCIP_SDPSOLVERSETTING *usedsetting)
interface methods for specific SDP-solvers
#define MIN_PENALTYPARAM
SCIP_RETCODE SCIPsdpiSolverResetCounter(SCIP_SDPISOLVER *sdpisolver)
void * SCIPsdpiSolverGetSolverPointer(SCIP_SDPISOLVER *sdpisolver)
#define TIMEOFDAY_CALL(x)
SCIP_RETCODE SCIPsdpiSolverGetRealpar(SCIP_SDPISOLVER *sdpisolver, SCIP_SDPPARAM type, SCIP_Real *dval)
SCIP_RETCODE SCIPsdpiSolverCreate(SCIP_SDPISOLVER **sdpisolver, SCIP_MESSAGEHDLR *messagehdlr, BMS_BLKMEM *blkmem, BMS_BUFMEM *bufmem)
SCIP_Bool SCIPsdpiSolverIsInfinity(SCIP_SDPISOLVER *sdpisolver, SCIP_Real val)
#define PENALTYPARAM_FACTOR
SCIP_RETCODE SCIPsdpiSolverSetRealpar(SCIP_SDPISOLVER *sdpisolver, SCIP_SDPPARAM type, SCIP_Real dval)
SCIP_Bool SCIPsdpiSolverIsPrimalInfeasible(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverGetSolFeasibility(SCIP_SDPISOLVER *sdpisolver, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
SCIP_RETCODE SCIPsdpiSolverFree(SCIP_SDPISOLVER **sdpisolver)
#define DSDP_CALLM(x)
#define CHECK_IF_SOLVED(sdpisolver)
static void sortColRow(int *row, int *col, SCIP_Real *val, int length)
SCIP_Bool SCIPsdpiSolverIsDualUnbounded(SCIP_SDPISOLVER *sdpisolver)
SCIP_Bool SCIPsdpiSolverFeasibilityKnown(SCIP_SDPISOLVER *sdpisolver)
SCIP_Real SCIPsdpiSolverGetMaxPrimalEntry(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverGetObjval(SCIP_SDPISOLVER *sdpisolver, SCIP_Real *objval)
#define MAX_PENALTYPARAM
struct Timings Timings
#define BMS_CALL(x)
const char * SCIPsdpiSolverGetSolverName(void)
SCIP_RETCODE SCIPsdpiSolverComputeMaxPenaltyparam(SCIP_SDPISOLVER *sdpisolver, SCIP_Real penaltyparam, SCIP_Real *maxpenaltyparam)
SCIP_RETCODE SCIPsdpiSolverGetPreoptimalPrimalNonzeros(SCIP_SDPISOLVER *sdpisolver, int nblocks, int *startXnblocknonz)
SCIP_RETCODE SCIPsdpSolcheckerCheck(BMS_BUFMEM *bufmem, int nvars, SCIP_Real *lb, SCIP_Real *ub, int nsdpblocks, int *sdpblocksizes, int *sdpnblockvars, int sdpconstnnonz, int *sdpconstnblocknonz, int **sdpconstrow, int **sdpconstcol, SCIP_Real **sdpconstval, int sdpnnonz, int **sdpnblockvarnonz, int **sdpvar, int ***sdprow, int ***sdpcol, SCIP_Real ***sdpval, int **indchanges, int *nremovedinds, int *blockindchanges, int nlpcons, int noldlpcons, SCIP_Real *lplhs, SCIP_Real *lprhs, int *rownactivevars, int lpnnonz, int *lprow, int *lpcol, SCIP_Real *lpval, SCIP_Real *solvector, SCIP_Real feastol, SCIP_Real epsilon, SCIP_Bool *infeasible)
Definition: sdpsolchecker.c:58
checks a given SDP solution for feasibility
SCIP_RETCODE SCIPsdpiSolverSetIntpar(SCIP_SDPISOLVER *sdpisolver, SCIP_SDPPARAM type, int ival)
SCIP_Bool SCIPsdpiSolverIsIterlimExc(SCIP_SDPISOLVER *sdpisolver)
#define INFEASMINFEASTOL
#define INFEASFEASTOLCHANGE
#define MAXPENALTYPARAM_FACTOR
SCIP_RETCODE SCIPsdpiSolverGetPrimalBoundVars(SCIP_SDPISOLVER *sdpisolver, SCIP_Real *lbvars, SCIP_Real *ubvars, int *arraylength)
static int checkTimeLimitDSDP(DSDP dsdp, void *ctx)
SCIP_RETCODE SCIPsdpiSolverGetPrimalMatrix(SCIP_SDPISOLVER *sdpisolver, int nblocks, int *startXnblocknonz, int **startXrow, int **startXcol, SCIP_Real **startXval)
SCIP_RETCODE SCIPsdpiSolverIncreaseCounter(SCIP_SDPISOLVER *sdpisolver)
static int compLowerTriangPos(int i, int j)
static int checkGapSetPreoptimalSol(DSDP dsdp, void *ctx)
SCIP_RETCODE SCIPsdpiSolverLoadAndSolve(SCIP_SDPISOLVER *sdpisolver, int nvars, SCIP_Real *obj, SCIP_Real *lb, SCIP_Real *ub, int nsdpblocks, int *sdpblocksizes, int *sdpnblockvars, int sdpconstnnonz, int *sdpconstnblocknonz, int **sdpconstrow, int **sdpconstcol, SCIP_Real **sdpconstval, int sdpnnonz, int **sdpnblockvarnonz, int **sdpvar, int ***sdprow, int ***sdpcol, SCIP_Real ***sdpval, int **indchanges, int *nremovedinds, int *blockindchanges, int nremovedblocks, int nlpcons, int noldlpcons, SCIP_Real *lplhs, SCIP_Real *lprhs, int *rownactivevars, int lpnnonz, int *lprow, int *lpcol, SCIP_Real *lpval, SCIP_Real *starty, int *startZnblocknonz, int **startZrow, int **startZcol, SCIP_Real **startZval, int *startXnblocknonz, int **startXrow, int **startXcol, SCIP_Real **startXval, SCIP_SDPSOLVERSETTING startsettings, SCIP_Real timelimit)
SCIP_Bool SCIPsdpiSolverIsTimelimExc(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverComputeLambdastar(SCIP_SDPISOLVER *sdpisolver, SCIP_Real maxguess)
SCIP_Bool SCIPsdpiSolverWasSolved(SCIP_SDPISOLVER *sdpisolver)
#define MAX_MAXPENALTYPARAM
SCIP_RETCODE SCIPsdpiSolverIgnoreInstability(SCIP_SDPISOLVER *sdpisolver, SCIP_Bool *success)
struct SCIP_SDPiSolver SCIP_SDPISOLVER
Definition: sdpisolver.h:70
SCIP_Bool SCIPsdpiSolverDoesWarmstartNeedPrimal(void)
SCIP_Real SCIPsdpiSolverGetDefaultSdpiSolverFeastol(void)
SCIP_Bool SCIPsdpiSolverIsOptimal(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverGetPrimalNonzeros(SCIP_SDPISOLVER *sdpisolver, int nblocks, int *startXnblocknonz)
SCIP_RETCODE SCIPsdpiSolverGetSdpCalls(SCIP_SDPISOLVER *sdpisolver, int *calls)
SCIP_Bool SCIPsdpiSolverIsAcceptable(SCIP_SDPISOLVER *sdpisolver)
#define PENALTYBOUNDTOL
enum SCIP_SDPParam SCIP_SDPPARAM
Definition: type_sdpi.h:69
SCIP_RETCODE SCIPsdpiSolverComputePenaltyparam(SCIP_SDPISOLVER *sdpisolver, SCIP_Real maxcoeff, SCIP_Real *penaltyparam)
SCIP_Bool SCIPsdpiSolverIsDualInfeasible(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverWriteSDP(SCIP_SDPISOLVER *sdpisolver, const char *fname)
SCIP_RETCODE SCIPsdpiSolverReadSDP(SCIP_SDPISOLVER *sdpisolver, const char *fname)
SCIP_RETCODE SCIPsdpiSolverGetIterations(SCIP_SDPISOLVER *sdpisolver, int *iterations)
#define DSDP_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)