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