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