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