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