SCIP-SDP  3.1.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
sdpisolver_sdpa.cpp
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-2019 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-2019 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 *//* shows all added nonzero entries */
35 /* #define SCIP_DEBUG_PRINTTOFILE *//* prints each problem inserted into SDPA to the file sdpa.dat-s and the starting point to sdpa.ini-s */
36 
37 /* #define SDPA_RESETPARAMS */ /* this can be used together with an update to the SDPA source code to prevent memory leaks when using SCIP-SDP with SDPA */
38 
45 #include <assert.h>
46 
47 #include "sdpi/sdpisolver.h"
48 
49 /* turn off warnings for sdpa (doesn't seem to work) */
50 #pragma GCC diagnostic ignored "-Wstrict-prototypes"
51 #include "sdpa_call.h" /* SDPA callable library interface */
52 #pragma GCC diagnostic warning "-Wstrict-prototypes"
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 /* turn off lint warnings for whole file: */
61 /*lint --e{1784}*/
62 
63 
64 /* local defines */
65 #define GAPTOLCHANGE 1
66 #define FEASTOLCHANGE 1
67 #define PENALTYBOUNDTOL 1E-3
70 #define INFEASFEASTOLCHANGE 0.1
71 #define INFEASMINFEASTOL 1E-9
73 #define MIN_LAMBDASTAR 1e0
74 #define MAX_LAMBDASTAR 1e8
75 #define LAMBDASTAR_FACTOR 1e0
76 #define LAMBDASTAR_TWOPOINTS TRUE
77 #define LAMBDASTAR_THRESHOLD 1e1
78 #define LAMBDASTAR_LOW 1.5
79 #define LAMBDASTAR_HIGH 1e5
81 #define MIN_PENALTYPARAM 1e5
82 #define MAX_PENALTYPARAM 1e12
83 #define PENALTYPARAM_FACTOR 1e1
84 #define MAX_MAXPENALTYPARAM 1e15
85 #define MAXPENALTYPARAM_FACTOR 1e6
89 #define BMS_CALL(x) do \
90  { \
91  if( NULL == (x) ) \
92  { \
93  SCIPerrorMessage("No memory in function call.\n"); \
94  return SCIP_NOMEMORY; \
95  } \
96  } \
97  while( FALSE )
98 
100 #define CHECK_IF_SOLVED(sdpisolver) do \
101  { \
102  if (!(sdpisolver->solved)) \
103  { \
104  SCIPerrorMessage("Tried to access solution information for SDP %d ahead of solving!\n", sdpisolver->sdpcounter); \
105  return SCIP_LPERROR; \
106  } \
107  } \
108  while( FALSE )
109 
111 #define CHECK_IF_SOLVED_BOOL(sdpisolver) do \
112  { \
113  if (!(sdpisolver->solved)) \
114  { \
115  SCIPerrorMessage("Tried to access solution information for SDP %d ahead of solving!\n", sdpisolver->sdpcounter); \
116  return FALSE; \
117  } \
118  } \
119  while( FALSE )
120 
121 
123 struct SCIP_SDPiSolver
124 {
125  SCIP_MESSAGEHDLR* messagehdlr;
126  BMS_BLKMEM* blkmem;
127  BMS_BUFMEM* bufmem;
128  SDPA* sdpa;
129  int nvars;
130  int nactivevars;
131  int* inputtosdpamapper;
134  int* sdpatoinputmapper;
135  SCIP_Real* fixedvarsval;
136  SCIP_Real fixedvarsobjcontr;
137  SCIP_Real* objcoefs;
138  int nvarbounds;
139  int* varboundpos;
141  int* inputtovbmapper;
143  int ninputlpcons;
144  int nsdpalpcons;
145  int nsdpblocks;
146  int* rowmapper;
147  int* rowtoinputmapper;
148  int* inputtoblockmapper;
149  int** blockindmapper;
150  SCIP_Bool solved;
151  SCIP_Bool timelimit;
152  int sdpcounter;
153  int niterations;
154  int nsdpcalls;
155  SCIP_Real epsilon;
156  SCIP_Real gaptol;
157  SCIP_Real feastol;
158  SCIP_Real sdpsolverfeastol;
159  SCIP_Real objlimit;
160  SCIP_Bool sdpinfo;
161  SCIP_Bool penalty;
162  SCIP_Bool feasorig;
164  SCIP_Bool rbound;
165  SCIP_SDPSOLVERSETTING usedsetting;
166  SCIP_Real lambdastar;
167  SCIP_Real* preoptimalsol;
168  SCIP_Real** preoptimalsolx;
169  SCIP_Bool preoptimalsolexists;
170  SCIP_Real preoptimalgap;
171 };
172 
173 
174 /*
175  * Local Functions
176  */
177 
178 #ifndef NDEBUG
179 
180 static
181 SCIP_Bool isFixed(
182  SCIP_SDPISOLVER* sdpisolver,
183  SCIP_Real lb,
184  SCIP_Real ub
185  )
186 {
187  assert( sdpisolver != NULL );
188  assert( lb < ub + sdpisolver->feastol );
189 
190  return (ub-lb <= sdpisolver->epsilon);
191 }
192 #else
193 #define isFixed(sdpisolver,lb,ub) (ub-lb <= sdpisolver->epsilon)
194 #endif
195 
199 static
200 SCIP_RETCODE checkFeastolAndResolve(
201  SCIP_SDPISOLVER* sdpisolver,
202  SCIP_Real penaltyparam,
203  int nvars,
204  SCIP_Real* lb,
205  SCIP_Real* ub,
206  int nsdpblocks,
207  int* sdpblocksizes,
208  int* sdpnblockvars,
209  int sdpconstnnonz,
210  int* sdpconstnblocknonz,
212  int** sdpconstrow,
213  int** sdpconstcol,
214  SCIP_Real** sdpconstval,
215  int sdpnnonz,
216  int** sdpnblockvarnonz,
218  int** sdpvar,
220  int*** sdprow,
221  int*** sdpcol,
222  SCIP_Real*** sdpval,
223  int** indchanges,
225  int* nremovedinds,
226  int* blockindchanges,
227  int nlpcons,
228  int noldlpcons,
229  SCIP_Real* lplhs,
230  SCIP_Real* lprhs,
231  int* rownactivevars,
232  int lpnnonz,
233  int* lprow,
234  int* lpcol,
235  SCIP_Real* lpval,
236  SCIP_Real* feastol
237  )
238 {
239 #ifdef SCIP_DEBUG
240  char phase_string[15];
241 #endif
242 
243  assert( feastol != NULL );
244 
245  while ( SCIPsdpiSolverIsAcceptable(sdpisolver) && SCIPsdpiSolverIsDualFeasible(sdpisolver) && penaltyparam < sdpisolver->epsilon && *feastol >= INFEASMINFEASTOL )
246  {
247  SCIP_Real* solvector;
248  int nvarspointer;
249  SCIP_Bool infeasible;
250 
251  /* get current solution */
252  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &solvector, nvars) );
253  nvarspointer = nvars;
254  SCIP_CALL( SCIPsdpiSolverGetSol(sdpisolver, NULL, solvector, &nvarspointer) );
255  assert( nvarspointer == nvars );
256 
257  /* check the solution for feasibility with regards to our tolerance */
258  SCIP_CALL( SCIPsdpSolcheckerCheck(sdpisolver->bufmem, nvars, lb, ub, nsdpblocks, sdpblocksizes, sdpnblockvars, sdpconstnnonz,
259  sdpconstnblocknonz, sdpconstrow, sdpconstcol, sdpconstval, sdpnnonz, sdpnblockvarnonz, sdpvar, sdprow, sdpcol, sdpval,
260  indchanges, nremovedinds, blockindchanges, nlpcons, noldlpcons, lplhs, lprhs, rownactivevars, lpnnonz, lprow, lpcol, lpval,
261  solvector, sdpisolver->feastol, sdpisolver->epsilon, &infeasible) );
262 
263  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &solvector);
264 
265  if ( infeasible )
266  {
267  SCIPdebugMessage("Solution feasible for SDPA but outside feasibility tolerance, changing SDPA feasibility tolerance from %f to %f\n",
268  *feastol, *feastol * INFEASFEASTOLCHANGE);
269  *feastol *= INFEASFEASTOLCHANGE;
270 
271  if ( *feastol >= INFEASMINFEASTOL )
272  {
273  /* update settings */
274  sdpisolver->sdpa->setParameterEpsilonDash(*feastol);
275 
276 #ifdef SCIP_MORE_DEBUG
277  sdpisolver->sdpa->printParameters(stdout);
278 #endif
279  sdpisolver->sdpa->setInitPoint(false);
280 #ifdef SDPA_RESETPARAMS
281  sdpisolver->sdpa->resetParameters();
282 #else
283  sdpisolver->sdpa->initializeSolve();
284 #endif
285  sdpisolver->sdpa->solve();
286 
287  /* update number of SDP-iterations and -calls */
288  sdpisolver->niterations += (int) sdpisolver->sdpa->getIteration();
289  sdpisolver->nsdpcalls += 1;
290 
291 #ifdef SCIP_DEBUG
292  /* print the phase value , i.e. whether solving was successfull */
293  sdpisolver->sdpa->getPhaseString((char*)phase_string);
294  SCIPdebugMessage("SDPA solving finished with status %s (primal and dual here are switched in contrast to our formulation)\n", phase_string);
295 #endif
296  }
297  else
298  {
299  sdpisolver->solved = FALSE;
300  SCIPmessagePrintInfo(sdpisolver->messagehdlr, "SDPA failed to reach required feasibility tolerance! \n");
301  }
302  }
303  else
304  break;
305  }
306  return SCIP_OKAY;
307 }
308 
309 /*
310  * Miscellaneous Methods
311  */
312 
318 const char* SCIPsdpiSolverGetSolverName(
319  void
320  )
321 {/*lint !e1784*/
322  return "SDPA"; /* version number can only be printed to file/stdout */
323 }
324 
326 const char* SCIPsdpiSolverGetSolverDesc(
327  void
328  )
329 {/*lint !e1784*/
330  return "Primal-dual Interior Point Solver for SDPs developed by K. Fujisawa et al. (sdpa.sourceforge.net)";
331 }
332 
340  SCIP_SDPISOLVER* sdpisolver
341  )
342 {/*lint !e1784*/
343  assert( sdpisolver != NULL );
344  return (void*) sdpisolver->sdpa;
345 }
346 
349  void
350  )
351 {
352  return 1E-6;
353 }
354 
357  void
358  )
359 {
360  return 1E-4;
361 }
362 
365  void
366  )
367 {
368  return 2;
369 }
370 
373  void
374  )
375 {
376  return TRUE;
377 }
378 
382 /*
383  * SDPI Creation and Destruction Methods
384  */
385 
390 SCIP_RETCODE SCIPsdpiSolverCreate(
391  SCIP_SDPISOLVER** sdpisolver,
392  SCIP_MESSAGEHDLR* messagehdlr,
393  BMS_BLKMEM* blkmem,
394  BMS_BUFMEM* bufmem
395  )
396 {/*lint !e1784*/
397  assert( sdpisolver != NULL );
398  assert( blkmem != NULL );
399  assert( bufmem != NULL );
400 
401  SCIPdebugMessage("Calling SCIPsdpiCreate \n");
402 
403  BMS_CALL( BMSallocBlockMemory(blkmem, sdpisolver) );
404 
405  (*sdpisolver)->messagehdlr = messagehdlr;
406  (*sdpisolver)->blkmem = blkmem;
407  (*sdpisolver)->bufmem = bufmem;
408 
409  /* this will be properly initialized then calling solve */
410  (*sdpisolver)->sdpa = NULL;
411 
412  (*sdpisolver)->nvars = 0;
413  (*sdpisolver)->nactivevars = 0;
414  (*sdpisolver)->nsdpblocks = 0;
415  (*sdpisolver)->inputtosdpamapper = NULL;
416  (*sdpisolver)->sdpatoinputmapper = NULL;
417  (*sdpisolver)->inputtoblockmapper = NULL;
418  (*sdpisolver)->blockindmapper = NULL;
419  (*sdpisolver)->rowmapper = NULL;
420  (*sdpisolver)->rowtoinputmapper = NULL;
421  (*sdpisolver)->fixedvarsval = NULL;
422  (*sdpisolver)->fixedvarsobjcontr = 0.0;
423  (*sdpisolver)->objcoefs = NULL;
424  (*sdpisolver)->nvarbounds = 0;
425  (*sdpisolver)->varboundpos = NULL;
426  (*sdpisolver)->inputtovbmapper = NULL;
427  (*sdpisolver)->solved = FALSE;
428  (*sdpisolver)->timelimit = FALSE;
429  (*sdpisolver)->sdpcounter = 0;
430  (*sdpisolver)->niterations = 0;
431  (*sdpisolver)->nsdpcalls = 0;
432  (*sdpisolver)->ninputlpcons = 0;
433  (*sdpisolver)->nsdpalpcons = 0;
434 
435  (*sdpisolver)->epsilon = 1e-9;
436  (*sdpisolver)->gaptol = 1e-4;
437  (*sdpisolver)->feastol = 1e-6;
438  (*sdpisolver)->sdpsolverfeastol = 1e-6;
439  (*sdpisolver)->objlimit = SCIPsdpiSolverInfinity(*sdpisolver);
440  (*sdpisolver)->sdpinfo = FALSE;
441  (*sdpisolver)->usedsetting = SCIP_SDPSOLVERSETTING_UNSOLVED;
442 
443  (*sdpisolver)->preoptimalsolexists = FALSE;
444  (*sdpisolver)->preoptimalgap = -1.0;
445 
446  return SCIP_OKAY;
447 }
448 
450 SCIP_RETCODE SCIPsdpiSolverFree(
451  SCIP_SDPISOLVER** sdpisolver
452  )
453 {/*lint !e1784*/
454  int b;
455  int nsdpblocks;
456  int blocksize;
457 
458  assert( sdpisolver != NULL );
459  assert( *sdpisolver != NULL );
460 
461  SCIPdebugMessage("Freeing SDPISolver\n");
462 
463  if ( (*sdpisolver)->sdpa != NULL )
464  {
465  nsdpblocks = (*sdpisolver)->sdpa->getBlockType((*sdpisolver)->sdpa->getBlockNumber()) == SDPA::LP ?
466  (*sdpisolver)->sdpa->getBlockNumber() - 1 : (*sdpisolver)->sdpa->getBlockNumber();
467 
468  for (b = 0; b < nsdpblocks; b++)
469  {
470  blocksize = (*sdpisolver)->sdpa->getBlockSize(b + 1);
471 
472  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &((*sdpisolver)->blockindmapper[b]), blocksize);
473 
474  /* free the preoptimal solution X array TODO: there still some memory leaks in this case */
475  if ( (*sdpisolver)->preoptimalgap >= 0.0 )
476  {
477  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &((*sdpisolver)->preoptimalsolx[b]), blocksize * blocksize);
478  }
479  }
480  /* free LP block of preoptimal solution X array */
481  if ( (*sdpisolver)->preoptimalgap >= 0.0 )
482  {
483  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &((*sdpisolver)->preoptimalsolx[nsdpblocks + 1]), 2 * (*sdpisolver)->nsdpalpcons + (*sdpisolver)->nvarbounds);
484  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->preoptimalsolx, nsdpblocks + 1);
485  }
486  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->blockindmapper, nsdpblocks);
487  }
488 
489  /* free SDPA object using destructor and free memory via blockmemshell */
490  if ( (*sdpisolver)->sdpa != NULL)
491  delete (*sdpisolver)->sdpa;
492 
493  if ( (*sdpisolver)->nactivevars > 0 && (*sdpisolver)->preoptimalgap > 0.0 )
494  {
495  BMSfreeBlockMemoryArray((*sdpisolver)->blkmem, &(*sdpisolver)->preoptimalsol, (*sdpisolver)->nactivevars);
496  } /* TODO: may use the same construct for the remaining arrays */
497 
498  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->inputtoblockmapper, (*sdpisolver)->nsdpblocks);
499 
500  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->rowtoinputmapper, 2 * (*sdpisolver)->nsdpalpcons);
501  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->rowmapper, 2 * (*sdpisolver)->ninputlpcons);
502  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->varboundpos, 2 * (*sdpisolver)->nactivevars);
503  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->inputtovbmapper, 2 * (*sdpisolver)->nvars);
504  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->inputtosdpamapper, (*sdpisolver)->nvars);
505  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->sdpatoinputmapper, (*sdpisolver)->nactivevars);
506  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->fixedvarsval, (*sdpisolver)->nvars - (*sdpisolver)->nactivevars);
507  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->objcoefs, (*sdpisolver)->nactivevars);
508  BMSfreeBlockMemory((*sdpisolver)->blkmem, sdpisolver);
509 
510  return SCIP_OKAY;
511 }
512 
514 SCIP_RETCODE SCIPsdpiSolverIncreaseCounter(
515  SCIP_SDPISOLVER* sdpisolver
516  )
517 {/*lint !e1784*/
518  assert( sdpisolver != NULL );
519 
520  sdpisolver->sdpcounter++;
521 
522  return SCIP_OKAY;
523 }
524 
526 SCIP_RETCODE SCIPsdpiSolverResetCounter(
527  SCIP_SDPISOLVER* sdpisolver
528  )
529 {/*lint !e1784*/
530  assert( sdpisolver != NULL );
531 
532  SCIPdebugMessage("Resetting counter of SDP-Interface from %d to 0.\n", sdpisolver->sdpcounter);
533  sdpisolver->sdpcounter = 0;
534 
535  return SCIP_OKAY;
536 }
537 
541 /*
542  * Solving Methods
543  */
544 
563 SCIP_RETCODE SCIPsdpiSolverLoadAndSolve(
564  SCIP_SDPISOLVER* sdpisolver,
565  int nvars,
566  SCIP_Real* obj,
567  SCIP_Real* lb,
568  SCIP_Real* ub,
569  int nsdpblocks,
570  int* sdpblocksizes,
571  int* sdpnblockvars,
572  int sdpconstnnonz,
573  int* sdpconstnblocknonz,
575  int** sdpconstrow,
576  int** sdpconstcol,
577  SCIP_Real** sdpconstval,
578  int sdpnnonz,
579  int** sdpnblockvarnonz,
581  int** sdpvar,
583  int*** sdprow,
584  int*** sdpcol,
585  SCIP_Real*** sdpval,
586  int** indchanges,
588  int* nremovedinds,
589  int* blockindchanges,
590  int nremovedblocks,
591  int nlpcons,
592  int noldlpcons,
593  SCIP_Real* lplhs,
594  SCIP_Real* lprhs,
595  int* lprownactivevars,
596  int lpnnonz,
597  int* lprow,
598  int* lpcol,
599  SCIP_Real* lpval,
600  SCIP_Real* starty,
601  int* startZnblocknonz,
603  int** startZrow,
605  int** startZcol,
607  SCIP_Real** startZval,
609  int* startXnblocknonz,
611  int** startXrow,
613  int** startXcol,
615  SCIP_Real** startXval,
617  SCIP_SDPSOLVERSETTING startsettings,
619  SCIP_Real timelimit
620  )
621 {/*lint !e1784*/
622  return SCIPsdpiSolverLoadAndSolveWithPenalty(sdpisolver, 0.0, TRUE, FALSE, nvars, obj, lb, ub, nsdpblocks, sdpblocksizes, sdpnblockvars, sdpconstnnonz,
623  sdpconstnblocknonz, sdpconstrow, sdpconstcol, sdpconstval, sdpnnonz, sdpnblockvarnonz, sdpvar, sdprow, sdpcol, sdpval, indchanges,
624  nremovedinds, blockindchanges, nremovedblocks, nlpcons, noldlpcons, lplhs, lprhs, lprownactivevars, lpnnonz, lprow, lpcol, lpval,
625  starty, startZnblocknonz, startZrow, startZcol, startZval, startXnblocknonz, startXrow, startXcol, startXval, startsettings,
626  timelimit, NULL, NULL);
627 }
628 
652  SCIP_SDPISOLVER* sdpisolver,
653  SCIP_Real penaltyparam,
654  SCIP_Bool withobj,
655  SCIP_Bool rbound,
656  int nvars,
657  SCIP_Real* obj,
658  SCIP_Real* lb,
659  SCIP_Real* ub,
660  int nsdpblocks,
661  int* sdpblocksizes,
662  int* sdpnblockvars,
663  int sdpconstnnonz,
664  int* sdpconstnblocknonz,
666  int** sdpconstrow,
667  int** sdpconstcol,
668  SCIP_Real** sdpconstval,
669  int sdpnnonz,
670  int** sdpnblockvarnonz,
672  int** sdpvar,
674  int*** sdprow,
675  int*** sdpcol,
676  SCIP_Real*** sdpval,
677  int** indchanges,
679  int* nremovedinds,
680  int* blockindchanges,
681  int nremovedblocks,
682  int nlpcons,
683  int noldlpcons,
684  SCIP_Real* lplhs,
685  SCIP_Real* lprhs,
686  int* rownactivevars,
687  int lpnnonz,
688  int* lprow,
689  int* lpcol,
690  SCIP_Real* lpval,
691  SCIP_Real* starty,
692  int* startZnblocknonz,
694  int** startZrow,
696  int** startZcol,
698  SCIP_Real** startZval,
700  int* startXnblocknonz,
702  int** startXrow,
704  int** startXcol,
706  SCIP_Real** startXval,
708  SCIP_SDPSOLVERSETTING startsettings,
710  SCIP_Real timelimit,
711  SCIP_Bool* feasorig,
713  SCIP_Bool* penaltybound
715  )
716 {/*lint !e1784*/
717  SCIP_Real feastol;
718  SCIP_Real* sdpavarbounds;
719  int i;
720  int k;
721  int b;
722  int block;
723  int nfixedvars;
724  bool checkinput; /* should the input be checked for consistency in SDPA ? */
725  int lpconsind;
726  int lastrow;
727  int nlpineqs;
728  int pos;
729  int newpos;
730  int oldnvars;
731  int oldnactivevars;
732  int oldsdpalplength;
733  int ind;
734  int blockind;
735  int nsdpasdpblocks;
736  SCIP_Bool newlyallocated;
737 
738 #ifdef SCIP_DEBUG
739  char phase_string[15];
740 #endif
741 
742  assert( sdpisolver != NULL );
743  assert( penaltyparam > -1 * sdpisolver->epsilon );
744  assert( penaltyparam < sdpisolver->epsilon || ( feasorig != NULL ) );
745  assert( nvars > 0 );
746  assert( obj != NULL );
747  assert( lb != NULL );
748  assert( ub != NULL );
749  assert( nsdpblocks >= 0 );
750  assert( nsdpblocks == 0 || sdpblocksizes != NULL );
751  assert( nsdpblocks == 0 || sdpnblockvars != NULL );
752  assert( sdpconstnnonz >= 0 );
753  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstnblocknonz != NULL );
754  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstrow != NULL );
755  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstcol != NULL );
756  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstval != NULL );
757  assert( sdpnnonz >= 0 );
758  assert( nsdpblocks == 0 || sdpnblockvarnonz != NULL );
759  assert( nsdpblocks == 0 || sdpvar != NULL );
760  assert( nsdpblocks == 0 || sdprow != NULL );
761  assert( nsdpblocks == 0 || sdpcol != NULL );
762  assert( nsdpblocks == 0 || sdpval != NULL );
763  assert( nsdpblocks == 0 || indchanges != NULL );
764  assert( nsdpblocks == 0 || nremovedinds != NULL );
765  assert( nsdpblocks == 0 || blockindchanges != NULL );
766  assert( 0 <= nremovedblocks && nremovedblocks <= nsdpblocks );
767  assert( nlpcons >= 0 );
768  assert( noldlpcons >= nlpcons );
769  assert( nlpcons == 0 || lplhs != NULL );
770  assert( nlpcons == 0 || lprhs != NULL );
771  assert( nlpcons == 0 || rownactivevars != NULL );
772  assert( lpnnonz >= 0 );
773  assert( nlpcons == 0 || lprow != NULL );
774  assert( nlpcons == 0 || lpcol != NULL );
775  assert( nlpcons == 0 || lpval != NULL );
776  assert( startZnblocknonz == NULL || startZrow != NULL );
777  assert( startZnblocknonz == NULL || startZcol != NULL );
778  assert( startZnblocknonz == NULL || startZval != NULL );
779  assert( startXnblocknonz == NULL || startXrow != NULL );
780  assert( startXnblocknonz == NULL || startXcol != NULL );
781  assert( startXnblocknonz == NULL || startXval != NULL );
782 
783  sdpisolver->niterations = 0;
784  sdpisolver->nsdpcalls = 0;
785  sdpisolver->feasorig = FALSE;
786 
787  /* immediately exit if the time limit is negative */
788  if ( timelimit <= 0.0 )
789  {
790  sdpisolver->solved = FALSE;
791  sdpisolver->timelimit = TRUE;
792  return SCIP_OKAY;
793  }
794  else
795  sdpisolver->timelimit = FALSE;
796 
797 #ifndef SCIP_NDEBUG
798  checkinput = false;
799 #else
800  checkinput = true;
801 #endif
802 
803  sdpisolver->usedsetting = SCIP_SDPSOLVERSETTING_UNSOLVED;
804 
805  /* 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
806  * same SDP) */
807  if ( penaltyparam < sdpisolver->epsilon )
808  SCIPdebugMessage("Inserting Data into SDPA for SDP (%d) \n", ++sdpisolver->sdpcounter);
809  else
810  SCIPdebugMessage("Inserting Data again into SDPA for SDP (%d) \n", sdpisolver->sdpcounter);
811 
812  /* set the penalty and rbound flags accordingly */
813  sdpisolver->penalty = (penaltyparam < sdpisolver->epsilon) ? FALSE : TRUE;
814  sdpisolver->rbound = rbound;
815 
816  /* allocate memory for inputtosdpamapper, sdpatoinputmapper and the fixed variable information, for the latter this will
817  * later be shrinked if the needed size is known */
818  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->inputtosdpamapper), sdpisolver->nvars, nvars) );
819  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->sdpatoinputmapper), sdpisolver->nactivevars, nvars) );
820  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->fixedvarsval), sdpisolver->nvars - sdpisolver->nactivevars, nvars) ); /*lint !e776*/
821  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->objcoefs), sdpisolver->nactivevars, nvars) ); /*lint !e776*/
822 
823  oldnvars = sdpisolver->nvars; /* we need to save these to realloc the inputtovbmapper and varboundpos-arrays if needed */
824  oldnactivevars = sdpisolver->nactivevars;
825  oldsdpalplength = 2 * sdpisolver->nsdpalpcons + sdpisolver->nvarbounds;
826  sdpisolver->nvars = nvars;
827  sdpisolver->nactivevars = 0;
828  nfixedvars = 0;
829 
830  /* find the fixed variables */
831  sdpisolver->fixedvarsobjcontr = 0.0;
832  for (i = 0; i < nvars; i++)
833  {
834  if ( isFixed(sdpisolver, lb[i], ub[i]) )
835  {
836  sdpisolver->fixedvarsobjcontr += obj[i] * lb[i]; /* this is the value this fixed variable contributes to the objective */
837  sdpisolver->fixedvarsval[nfixedvars] = lb[i]; /* if lb=ub, than this is the value the variable will have in every solution */
838  nfixedvars++;
839  sdpisolver->inputtosdpamapper[i] = -nfixedvars;
840  SCIPdebugMessage("Fixing variable %d locally to %f for SDP %d in SDPA\n", i, lb[i], sdpisolver->sdpcounter);
841  }
842  else
843  {
844  sdpisolver->sdpatoinputmapper[sdpisolver->nactivevars] = i;
845  sdpisolver->objcoefs[sdpisolver->nactivevars] = obj[i];
846  sdpisolver->nactivevars++;
847  sdpisolver->inputtosdpamapper[i] = sdpisolver->nactivevars; /* sdpa starts counting at 1, so we do this after increasing nactivevars */
848 #ifdef SCIP_MORE_DEBUG
849  SCIPdebugMessage("Variable %d becomes variable %d for SDP %d in SDPA\n", i, sdpisolver->inputtosdpamapper[i], sdpisolver->sdpcounter);
850 #endif
851  }
852  }
853  assert( sdpisolver->nactivevars + nfixedvars == sdpisolver->nvars );
854 
855  /* if we want to solve without objective, we reset fixedvarsobjcontr */
856  if ( ! withobj )
857  sdpisolver->fixedvarsobjcontr = 0.0;
858 
859  /* shrink the fixedvars and sdpatoinputmapper arrays to the right size */
860  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->objcoefs), nvars, sdpisolver->nactivevars) );
861  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->fixedvarsval), nvars, nfixedvars) );
862  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->sdpatoinputmapper), nvars, sdpisolver->nactivevars) );
863 
864  /* reallocate memory for blocktoinputmapper and blockindmapper*/
865  if ( nsdpblocks != sdpisolver->nsdpblocks )
866  {
867  if ( sdpisolver->inputtoblockmapper == NULL )
868  {
869  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->inputtoblockmapper), nsdpblocks) );
870  }
871  else
872  {
873  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->inputtoblockmapper), sdpisolver->nsdpblocks, nsdpblocks) );
874  }
875  }
876 
877  /* adjust length of preoptimal solution array */
878  if ( sdpisolver->nactivevars != oldnactivevars && sdpisolver->preoptimalgap >= 0.0 )
879  {
880  if ( oldnactivevars == 0 )
881  {
882  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->preoptimalsol), sdpisolver->nactivevars) );
883  }
884  else
885  {
886  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->preoptimalsol), oldnactivevars, sdpisolver->nactivevars) );
887  }
888  }
889  sdpisolver->preoptimalsolexists = FALSE;
890 
891  sdpisolver->nsdpblocks = nsdpblocks;
892 
893  /* get number of blocks in sdpa for reallocating memory, for this first solve call this is 0 since no memory was allocated before */
894  if ( sdpisolver->sdpa == NULL )
895  {
896  nsdpasdpblocks = 0;
897  }
898  else
899  {
900  nsdpasdpblocks = (sdpisolver->sdpa->getBlockType(sdpisolver->sdpa->getBlockNumber()) == SDPA::LP ?
901  sdpisolver->sdpa->getBlockNumber() - 1 : sdpisolver->sdpa->getBlockNumber());
902  }
903 
904 
905  if ( nsdpblocks - nremovedblocks != nsdpasdpblocks )
906  {
907  if ( sdpisolver->blockindmapper == NULL )
908  {
909  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->blockindmapper), nsdpblocks - nremovedblocks) ); /*lint !e647*/
910  newlyallocated = TRUE;
911  if ( sdpisolver->preoptimalgap >= 0.0 )
912  {
913  /* allocate memory for preoptimal X array with length nsdpblocks + 1 (for LP block) */
914  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->preoptimalsolx), nsdpblocks - nremovedblocks + 1) ); /*lint !e647*/
915  }
916  }
917  else
918  {
919 
920  /* if the number of blocks decreased, we first need to free memory for those blocks before reallocating memory for the outer array */
921  for ( block = nsdpblocks - nremovedblocks; block < nsdpasdpblocks; block++ )
922  {
923  BMSfreeBlockMemoryArrayNull(sdpisolver->blkmem, &(sdpisolver->blockindmapper[block]), sdpisolver->sdpa->getBlockSize(block + 1));
924  }
925  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->blockindmapper),
926  nsdpasdpblocks, nsdpblocks - nremovedblocks) ); /*lint !e647*/
927  newlyallocated = FALSE;
928 
929  if ( sdpisolver->preoptimalgap >= 0.0 )
930  {
931  /* if the number of blocks decreased, we first need to free memory for those blocks before reallocating memory for the outer array */
932  for ( block = nsdpblocks - nremovedblocks; block < nsdpasdpblocks; block++ )
933  {
934  BMSfreeBlockMemoryArrayNull(sdpisolver->blkmem, &(sdpisolver->preoptimalsolx[block]), sdpisolver->sdpa->getBlockSize(block + 1));
935  }
936  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->preoptimalsolx),
937  nsdpasdpblocks, nsdpblocks - nremovedblocks + 1) ); /*lint !e647*/
938  }
939  }
940  }
941  else
942  newlyallocated = FALSE;
943 
944  /* compute blockmapper and blockindmapper (needs to be done before old sdpa is freed to have old memory length available to prevent unnecessary reallocs) */
945  ind = 0;
946  for (block = 0; block < nsdpblocks; block++)
947  {
948  if ( blockindchanges[block] > -1 )
949  {
950  sdpisolver->inputtoblockmapper[block] = ind + 1; /* +1 because SDPA start counting at one */
951 
952  /* realloc memory if necessary */
953  if ( newlyallocated )
954  {
955  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->blockindmapper[ind]), sdpblocksizes[block] - nremovedinds[block]) ); /*lint !e647*/
956  if ( sdpisolver->preoptimalgap >= 0.0 )
957  {
958  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->preoptimalsolx[ind]),
959  (sdpblocksizes[block] - nremovedinds[block]) * (sdpblocksizes[block] - nremovedinds[block])) ); /*lint !e647*/
960  }
961  }
962  else if ( (long long) (sdpblocksizes[block] - nremovedinds[block]) != sdpisolver->sdpa->getBlockSize(ind + 1) )
963  {
964  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->blockindmapper[ind]),
965  (int) sdpisolver->sdpa->getBlockSize(ind + 1), sdpblocksizes[block] - nremovedinds[block]) ); /*lint !e647*/
966  if ( sdpisolver->preoptimalgap >= 0.0 )
967  {
968  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->preoptimalsolx[ind]),
969  (int) sdpisolver->sdpa->getBlockSize(ind + 1) * sdpisolver->sdpa->getBlockSize(ind + 1), (sdpblocksizes[block] - nremovedinds[block]) * (sdpblocksizes[block] - nremovedinds[block])) ); /*lint !e647*/
970  }
971  }
972 
973  blockind = 0;
974  for (i = 0; i < sdpblocksizes[block]; i++)
975  {
976  if ( indchanges[ind][i] > -1 )
977  {
978  sdpisolver->blockindmapper[ind][blockind] = i;
979  assert( i - indchanges[ind][i] == blockind );
980  blockind++;
981  }
982  }
983  assert( blockind == sdpblocksizes[block] - nremovedinds[block] );
984  ind++;
985  }
986  else
987  sdpisolver->inputtoblockmapper[block] = -1;
988  }
989 
990  /* insert data */
991  if ( sdpisolver->sdpa != 0 )
992  {
993  /* if the SDPA solver has already been created, clear the current problem instance */
994  delete sdpisolver->sdpa;
995  sdpisolver->sdpa = new SDPA();
996  }
997  else
998  sdpisolver->sdpa = new SDPA();
999  assert( sdpisolver->sdpa != 0 );
1000 
1001  /* initialize settings (this needs to be done before inserting the problem as the initial point depends on the settings) */
1002  if ( penaltyparam >= sdpisolver->epsilon || startsettings == SCIP_SDPSOLVERSETTING_STABLE || startsettings == SCIP_SDPSOLVERSETTING_PENALTY )
1003  {
1004  sdpisolver->sdpa->setParameterType(SDPA::PARAMETER_STABLE_BUT_SLOW); /* if we already had problems with this problem, there is no reason to try fast */
1005  /* as we want to solve with stable settings, we also update epsilon and the feasibility tolerance, as we skip the default settings, we multpy twice */
1006  sdpisolver->sdpa->setParameterEpsilonStar(GAPTOLCHANGE * GAPTOLCHANGE * sdpisolver->gaptol);
1007  sdpisolver->sdpa->setParameterEpsilonDash(FEASTOLCHANGE * FEASTOLCHANGE * sdpisolver->sdpsolverfeastol);
1008  feastol = FEASTOLCHANGE * FEASTOLCHANGE * sdpisolver->sdpsolverfeastol;
1009  SCIPdebugMessage("Start solving process with stable settings\n");
1010  }
1011  else if ( startsettings == SCIP_SDPSOLVERSETTING_UNSOLVED || startsettings == SCIP_SDPSOLVERSETTING_FAST)
1012  {
1013  sdpisolver->sdpa->setParameterType(SDPA::PARAMETER_UNSTABLE_BUT_FAST);
1014  sdpisolver->sdpa->setParameterEpsilonStar(sdpisolver->gaptol);
1015  sdpisolver->sdpa->setParameterEpsilonDash(sdpisolver->sdpsolverfeastol);
1016  feastol = sdpisolver->sdpsolverfeastol;
1017  SCIPdebugMessage("Start solving process with fast settings\n");
1018  }
1019  else if ( startsettings == SCIP_SDPSOLVERSETTING_MEDIUM )
1020  {
1021  sdpisolver->sdpa->setParameterType(SDPA::PARAMETER_DEFAULT);
1022  /* as we want to solve with stable settings, we also update epsilon and the feasibility tolerance, as we skip the default settings, we multpy once */
1023  sdpisolver->sdpa->setParameterEpsilonStar(GAPTOLCHANGE * sdpisolver->gaptol);
1024  sdpisolver->sdpa->setParameterEpsilonDash(FEASTOLCHANGE * sdpisolver->sdpsolverfeastol);
1025  feastol = FEASTOLCHANGE * sdpisolver->sdpsolverfeastol;
1026  SCIPdebugMessage("Start solving process with medium settings\n");
1027  }
1028  else
1029  {
1030  SCIPdebugMessage("Unknown setting for start-settings: %d!\n", startsettings); \
1031  return SCIP_LPERROR;
1032  }
1033  sdpisolver->sdpa->setParameterLowerBound(-1e20);
1034 
1035 
1036  /* set the objective limit */
1037  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, sdpisolver->objlimit) )
1038  sdpisolver->sdpa->setParameterUpperBound(sdpisolver->objlimit);
1039  else
1040  sdpisolver->sdpa->setParameterUpperBound(1e8);
1041 
1042  /* increase Lambda Star, this seems to help the numerics */
1043  sdpisolver->sdpa->setParameterLambdaStar(sdpisolver->lambdastar);
1044  //sdpisolver->sdpa->setParameterBetaStar(0.01);
1045  //sdpisolver->sdpa->setParameterBetaBar(0.02);
1046 
1047 #ifdef SCIP_MORE_DEBUG
1048  sdpisolver->sdpa->printParameters(stdout);
1049 #endif
1050 
1051  /* compute number of variable bounds and save them in sdpavarbounds and inputtovbmapper */
1052  sdpisolver->nvarbounds = 0;
1053  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &sdpavarbounds, 2 * sdpisolver->nactivevars) ); /*lint !e647*//*lint !e530*/
1054 
1055  if ( sdpisolver->nvars != oldnvars )
1056  {
1057  if ( sdpisolver->inputtovbmapper == NULL )
1058  {
1059  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->inputtovbmapper), 2 * sdpisolver->nvars) ); /*lint !e647*/
1060  }
1061  else
1062  {
1063  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->inputtovbmapper), 2 * oldnvars, 2 * sdpisolver->nvars) ); /*lint !e647*/
1064  }
1065  }
1066  assert( sdpisolver->inputtovbmapper != NULL );
1067 
1068  /* initialize inputtovbmapper with -1 */
1069  for (i = 0; i < 2 * sdpisolver->nvars; i++)
1070  sdpisolver->inputtovbmapper[i] = -1;
1071 
1072  if ( sdpisolver->nactivevars != oldnactivevars )
1073  {
1074  if ( sdpisolver->varboundpos == NULL )
1075  {
1076  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->varboundpos), 2 * sdpisolver->nactivevars) ); /*lint !e647*/
1077  }
1078  else
1079  {
1080  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->varboundpos), 2 * oldnactivevars, 2 * sdpisolver->nactivevars) ); /*lint !e647*/
1081  }
1082  }
1083  assert( sdpisolver->varboundpos != NULL );
1084 
1085  for (i = 0; i < sdpisolver->nactivevars; i++)
1086  {
1087  assert( 0 <= sdpisolver->sdpatoinputmapper[i] && sdpisolver->sdpatoinputmapper[i] < nvars );
1088  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, lb[sdpisolver->sdpatoinputmapper[i]]))
1089  {
1090  sdpavarbounds[sdpisolver->nvarbounds] = lb[sdpisolver->sdpatoinputmapper[i]];
1091  sdpisolver->varboundpos[sdpisolver->nvarbounds] = -(i + 1); /* negative sign means lower bound, i + 1 because sdpa starts counting from one */
1092  sdpisolver->inputtovbmapper[2 * sdpisolver->sdpatoinputmapper[i]] = sdpisolver->nvarbounds;
1093  (sdpisolver->nvarbounds)++;
1094  }
1095  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, ub[sdpisolver->sdpatoinputmapper[i]]) )
1096  {
1097  sdpavarbounds[sdpisolver->nvarbounds] = ub[sdpisolver->sdpatoinputmapper[i]];
1098  sdpisolver->varboundpos[sdpisolver->nvarbounds] = +(i + 1); /* positive sign means upper bound, i + 1 because sdpa starts counting from one */
1099  sdpisolver->inputtovbmapper[2 * sdpisolver->sdpatoinputmapper[i] + 1] = sdpisolver->nvarbounds;
1100  (sdpisolver->nvarbounds)++;
1101  }
1102  }
1103 
1104  if ( noldlpcons > 0 )
1105  {
1106  /* 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 */
1107  if ( sdpisolver->ninputlpcons != noldlpcons )
1108  {
1109  if ( sdpisolver->rowmapper == NULL )
1110  {
1111  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->rowmapper), 2*noldlpcons) ); /*lint !e647*/
1112  }
1113  else
1114  {
1115  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->rowmapper), 2 * sdpisolver->ninputlpcons, 2*noldlpcons) ); /*lint !e647*/
1116  }
1117  }
1118  assert( sdpisolver->rowmapper != NULL );
1119 
1120  /* allocate memory to save which sdpa lp constraints correspond to which input constraint, entry 2i indicates left hand side of ranged-row i, 2i+1 rhs */
1121  if ( sdpisolver->nsdpalpcons != nlpcons )
1122  {
1123  if ( sdpisolver->rowtoinputmapper == NULL )
1124  {
1125  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->rowtoinputmapper), 2 * nlpcons) );
1126  }
1127  else
1128  {
1129  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->rowtoinputmapper), 2 * sdpisolver->nsdpalpcons, 2 * nlpcons) );
1130  }
1131  }
1132  assert( sdpisolver->rowtoinputmapper != NULL );
1133 
1134  sdpisolver->ninputlpcons = noldlpcons;
1135  sdpisolver->nsdpalpcons = nlpcons;
1136 
1137  /* compute the number of LP constraints after splitting the ranged rows and compute the rowmapper */
1138  pos = 1; /* SDPA starts counting the LP-inequalities at one */
1139  newpos = 0; /* the position in the lhs and rhs arrays */
1140  for (i = 0; i < noldlpcons; i++)
1141  {
1142  if ( rownactivevars[i] >= 2 )
1143  {
1144  if ( lplhs[newpos] > - SCIPsdpiSolverInfinity(sdpisolver) )
1145  {
1146  sdpisolver->rowmapper[2*i] = pos; /*lint !e679*/
1147  sdpisolver->rowtoinputmapper[pos - 1] = 2*i;
1148  pos++;
1149  }
1150  else
1151  sdpisolver->rowmapper[2*i] = -1; /*lint !e679*/
1152  if ( lprhs[newpos] < SCIPsdpiSolverInfinity(sdpisolver) )
1153  {
1154  sdpisolver->rowmapper[2*i + 1] = pos; /*lint !e679*/
1155  sdpisolver->rowtoinputmapper[pos - 1] = 2*i + 1;
1156  pos++;
1157  }
1158  else
1159  sdpisolver->rowmapper[2*i + 1] = -1; /*lint !e679*/
1160 
1161  newpos++;
1162  }
1163  else
1164  {
1165  sdpisolver->rowmapper[2*i] = -1; /*lint !e679*/
1166  sdpisolver->rowmapper[2*i + 1] = -1; /*lint !e679*/
1167  }
1168  }
1169  nlpineqs = pos - 1; /* minus one because we started at one as SDPA wants them numbered one to nlpineqs */
1170  assert( nlpineqs <= 2*nlpcons ); /* *2 comes from left- and right-hand-sides */
1171  }
1172  else
1173  nlpineqs = 0;
1174 
1175  /* if we use a penalty formulation, we need the constraint r >= 0 */
1176  if ( penaltyparam >= sdpisolver->epsilon && rbound )
1177  sdpisolver->nvarbounds++;
1178 
1179  if ( sdpisolver->sdpinfo )
1180  sdpisolver->sdpa->setDisplay(stdout);
1181  else
1182  sdpisolver->sdpa->setDisplay(0);
1183 
1184 #ifdef SCIP_MORE_DEBUG
1185  FILE* fpOut = fopen("output.tmp", "w");
1186  if ( ! fpOut )
1187  exit(-1);
1188  sdpisolver->sdpa->setResultFile(fpOut);
1189 #endif
1190 
1191  /* (re)allocate memory for LP block of primal solution for preoptimal sol */
1192  if ( sdpisolver->preoptimalgap >= 0.0 )
1193  {
1194  if ( newlyallocated )
1195  {
1196  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->preoptimalsolx[nsdpblocks - nremovedblocks]),
1197  2 * sdpisolver->nsdpalpcons + sdpisolver->nvarbounds) );
1198  }
1199  else
1200  {
1201  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->preoptimalsolx[nsdpblocks - nremovedblocks]), oldsdpalplength,
1202  2 * sdpisolver->nsdpalpcons + sdpisolver->nvarbounds) );
1203  }
1204  }
1205 
1206  /* initialize blockstruct */
1207  if ( penaltyparam < sdpisolver->epsilon ) /* we initialize this with an exact 0.0 in Solve without penalty */
1208  sdpisolver->sdpa->inputConstraintNumber((long long) sdpisolver->nactivevars);/*lint !e747*/
1209  else
1210  sdpisolver->sdpa->inputConstraintNumber((long long) sdpisolver->nactivevars + 1);/*lint !e747*/ /* the additional variable is r for the penalty formulation */
1211 
1212  /* if there are any lp-cons/variable-bounds, we get an extra block for those, lastrow - nshifts is the number of lp constraints added */
1213  sdpisolver->sdpa->inputBlockNumber((long long) ((nlpineqs + sdpisolver->nvarbounds > 0) ?
1214  nsdpblocks - nremovedblocks + 1 : nsdpblocks - nremovedblocks)); /*lint !e834 !e747 !e776*/
1215 
1216  /* block+1 because SDPA starts counting at 1 */
1217  for (block = 0; block < nsdpblocks; block++)
1218  {
1219  if ( blockindchanges[block] >= 0 )
1220  {
1221  SCIPdebugMessage("adding block %d to SDPA as block %d with size %d\n",
1222  block, block - blockindchanges[block] + 1, sdpblocksizes[block] - nremovedinds[block]); /*lint !e834*/
1223  sdpisolver->sdpa->inputBlockSize((long long) block - blockindchanges[block] + 1,/*lint !e747, !e834*/
1224  (long long) sdpblocksizes[block] - nremovedinds[block]); /*lint !e834, !e776, !e747*/
1225  sdpisolver->sdpa->inputBlockType((long long) block - blockindchanges[block] + 1, SDPA::SDP); /*lint !e834, !e776, !e747*/
1226  }
1227  }
1228  if ( nlpineqs + sdpisolver->nvarbounds > 0 )
1229  {
1230  /* the last block is the lp block, the size has a negative sign */
1231  sdpisolver->sdpa->inputBlockSize((long long) nsdpblocks - nremovedblocks + 1, (long long) -(nlpineqs + sdpisolver->nvarbounds)); /*lint !e834, !e776, !e747*/
1232  sdpisolver->sdpa->inputBlockType((long long) nsdpblocks - nremovedblocks + 1, SDPA::LP); /*lint !e834, !e776, !e747*/
1233  SCIPdebugMessage("adding LP block to SDPA as block %d with size %d\n", nsdpblocks - nremovedblocks + 1,/*lint !e834*/
1234  -(nlpineqs + sdpisolver->nvarbounds)); /*lint !e834*/
1235  }
1236 
1237  sdpisolver->sdpa->initializeUpperTriangleSpace();
1238 
1239  /* set objective values */
1240  for (i = 0; i < sdpisolver->nactivevars; i++)
1241  {
1242  if ( withobj )
1243  {
1244  /* insert objective value, SDPA counts from 1 to n instead of 0 to n-1 */
1245  sdpisolver->sdpa->inputCVec((long long) i + 1, obj[sdpisolver->sdpatoinputmapper[i]]);/*lint !e747*/
1246 #ifdef SCIP_MORE_DEBUG
1247  SCIPdebugMessage("inserting objective %f for variable %d which became variable %d in SDPA\n", obj[sdpisolver->sdpatoinputmapper[i]],
1248  sdpisolver->sdpatoinputmapper[i], i+1);
1249 #endif
1250  }
1251  if ( penaltyparam >= sdpisolver->epsilon )
1252  sdpisolver->sdpa->inputCVec((long long) sdpisolver->nactivevars + 1, penaltyparam);/*lint !e747*/ /* set the objective of the additional var to penaltyparam */
1253  }
1254 
1255  /* if we want to use a starting point we have to tell SDPA to allocate memory for it */
1256  if ( starty != NULL && startZnblocknonz != NULL && startXnblocknonz != NULL && penaltyparam < sdpisolver->epsilon )
1257  sdpisolver->sdpa->setInitPoint(true);
1258  else
1259  sdpisolver->sdpa->setInitPoint(false);
1260 
1261  /* start inserting the non-constant SDP-Constraint-Matrices */
1262  if ( sdpnnonz > 0 )
1263  {
1264  int v;
1265  int blockvar;
1266 
1267  assert( nsdpblocks > 0 );
1268  assert( sdpnblockvarnonz != NULL );
1269  assert( sdpnblockvars != NULL );
1270  assert( sdpcol != NULL );
1271  assert( sdprow != NULL );
1272  assert( sdpval != NULL );
1273  assert( sdpvar != NULL );
1274  assert( indchanges != NULL );
1275  assert( nremovedinds != NULL );
1276 
1277  for (block = 0; block < nsdpblocks; block++)
1278  {
1279  /* if the block has no entries, we skip it */
1280  if ( blockindchanges[block] == -1 )
1281  continue;
1282 #ifdef SCIP_MORE_DEBUG
1283  SCIPdebugMessage(" -> building block %d, which becomes block %d in SDPA (%d)\n", block, block - blockindchanges[block] + 1,sdpisolver->sdpcounter);
1284 #endif
1285  /* iterate over all variables in this block */
1286  for (blockvar = 0; blockvar < sdpnblockvars[block]; blockvar++)
1287  {
1288  v = sdpisolver->inputtosdpamapper[sdpvar[block][blockvar]];
1289 
1290 #ifdef SCIP_MORE_DEBUG
1291  SCIPdebugMessage(" -> adding coefficient matrix for variable %d which becomes variable %d in SDPA (%d)\n",
1292  sdpvar[block][blockvar], v, sdpisolver->sdpcounter);
1293 #endif
1294 
1295  /* check if the variable is active */
1296  if ( v > -1 )
1297  {
1298  for (k = 0; k < sdpnblockvarnonz[block][blockvar]; k++)
1299  {
1300  /* rows and cols with active nonzeros should not be removed */
1301  assert( indchanges[block][sdprow[block][blockvar][k]] > -1 && indchanges[block][sdpcol[block][blockvar][k]] > -1 );
1302 
1303  assert( indchanges[block][sdprow[block][blockvar][k]] <= sdprow[block][blockvar][k]);
1304  assert( indchanges[block][sdpcol[block][blockvar][k]] <= sdpcol[block][blockvar][k]);
1305 
1306  assert( 0 <= sdprow[block][blockvar][k] && sdprow[block][blockvar][k] < sdpblocksizes[block] );
1307  assert( 0 <= sdpcol[block][blockvar][k] && sdpcol[block][blockvar][k] < sdpblocksizes[block] );
1308 
1309  /* rows and columns start with one in SDPA, so we have to add 1 to the indices */
1310 #ifdef SCIP_MORE_DEBUG
1311  SCIPdebugMessage(" -> adding nonzero %g at (%d,%d) (%d)\n",
1312  sdpval[block][blockvar][k],
1313  sdpcol[block][blockvar][k] - indchanges[block][sdpcol[block][blockvar][k]] + 1,
1314  sdprow[block][blockvar][k] - indchanges[block][sdprow[block][blockvar][k]] + 1,
1315  sdpisolver->sdpcounter);
1316 #endif
1317 
1318  sdpisolver->sdpa->inputElement((long long) v, (long long) block - blockindchanges[block] + 1, /*lint !e834, !e747*/
1319  (long long) sdpcol[block][blockvar][k] - indchanges[block][sdpcol[block][blockvar][k]] + 1, /*lint !e834, !e747*/
1320  (long long) sdprow[block][blockvar][k] - indchanges[block][sdprow[block][blockvar][k]] + 1, /*lint !e834, !e747*/
1321  sdpval[block][blockvar][k], checkinput); /*lint !e776 !e834*/
1322  }
1323  }
1324  }
1325  /* insert the identity matrix if we are using a penalty formulation */
1326  if ( penaltyparam >= sdpisolver->epsilon )
1327  {
1328 #ifdef SCIP_MORE_DEBUG
1329  SCIPdebugMessage(" -> adding coefficient matrix for penalty variable r in SDPA (%d)\n", sdpisolver->sdpcounter);
1330 #endif
1331  for (i = 0; i < sdpblocksizes[block] - nremovedinds[block]; i++)
1332  {
1333 #ifdef SCIP_MORE_DEBUG
1334  SCIPdebugMessage(" -> adding nonzero 1.0 at (%d,%d) (%d)\n", i + 1, i + 1, sdpisolver->sdpcounter);
1335 #endif
1336 
1337  sdpisolver->sdpa->inputElement((long long) sdpisolver->nactivevars + 1, (long long) block - blockindchanges[block] + 1, /*lint !e747, !e776, !e834*/
1338  (long long) i + 1, (long long) i + 1, 1.0, checkinput);/*lint !e747*/
1339  }
1340  }
1341  }
1342  }
1343 
1344  /* start inserting the constant matrix */
1345  if ( sdpconstnnonz > 0 )
1346  {
1347  assert( nsdpblocks > 0 );
1348  assert( sdpconstnblocknonz!= NULL );
1349  assert( sdpconstcol != NULL );
1350  assert( sdpconstrow != NULL );
1351  assert( sdpconstval != NULL );
1352 
1353  for (block = 0; block < nsdpblocks; block++)
1354  {
1355  if ( blockindchanges[block] == -1 )
1356  continue;
1357 #ifdef SCIP_MORE_DEBUG
1358  SCIPdebugMessage(" -> building block %d (%d)\n", block + 1, sdpisolver->sdpcounter);
1359 #endif
1360  for (k = 0; k < sdpconstnblocknonz[block]; k++)
1361  {
1362  /* rows and cols with active nonzeros should not be removed */
1363  assert( indchanges[block][sdpconstrow[block][k]] > -1 && indchanges[block][sdpconstcol[block][k]] > -1 );
1364 
1365  assert( indchanges[block][sdpconstrow[block][k]] <= sdpconstrow[block][k]);
1366  assert( indchanges[block][sdpconstcol[block][k]] <= sdpconstcol[block][k]);
1367 
1368  assert (0 <= sdpconstrow[block][k] && sdpconstrow[block][k] < sdpblocksizes[block]);
1369  assert (0 <= sdpconstcol[block][k] && sdpconstcol[block][k] < sdpblocksizes[block]);
1370 
1371  /* rows and columns start with one in SDPA, so we have to add 1 to the indices, the constant matrix is given as variable 0 */
1372 #ifdef SCIP_MORE_DEBUG
1373  SCIPdebugMessage(" -> adding constant nonzero %g at (%d,%d) (%d)\n", sdpconstval[block][k],
1374  sdpconstcol[block][k] - indchanges[block][sdpconstcol[block][k]] + 1,
1375  sdpconstrow[block][k] - indchanges[block][sdpconstrow[block][k]] + 1,
1376  sdpisolver->sdpcounter);
1377 #endif
1378  sdpisolver->sdpa->inputElement((long long) 0, (long long) block - blockindchanges[block] + 1, /*lint !e747, !e776, !e834*/
1379  (long long) sdpconstcol[block][k] - indchanges[block][sdpconstcol[block][k]] + 1, /*lint !e747, !e776, !e834*/
1380  (long long) sdpconstrow[block][k] - indchanges[block][sdpconstrow[block][k]] + 1, /*lint !e747, !e776, !e834*/
1381  sdpconstval[block][k], checkinput);
1382  }
1383  }
1384  }
1385 
1386 #ifdef SCIP_MORE_DEBUG
1387  SCIPdebugMessage(" -> building LP-block %d (%d)\n", nsdpblocks - nremovedblocks + 1, sdpisolver->sdpcounter);
1388 #endif
1389  /* inserting LP nonzeros */
1390  lastrow = -1;
1391  for (i = 0; i < lpnnonz; i++)
1392  {
1393  assert( 0 <= lprow[i] && lprow[i] < noldlpcons );
1394  assert( 0 <= lpcol[i] && lpcol[i] < nvars );
1395  assert( REALABS(lpval[i]) > sdpisolver->epsilon );
1396 
1397  /* if the variable is active and the constraint is more than a bound, we add it */
1398  if ( sdpisolver->inputtosdpamapper[lpcol[i]] > 0 )
1399  {
1400  /* as this is an active variable, there should be at least one in the constraint */
1401  assert( rownactivevars[lprow[i]] > 0 );
1402  if ( rownactivevars[lprow[i]] > 1 )
1403  {
1404  if ( lprow[i] > lastrow ) /* we update the lpcons-counter */
1405  {
1406  lastrow = lprow[i];
1407  /* if we use a penalty formulation, add the r * Identity entry */
1408  if ( penaltyparam >= sdpisolver->epsilon )
1409  {
1410  /* check for the lhs-inequality */
1411  if ( sdpisolver->rowmapper[2*lastrow] > -1 ) /*lint !e679*/
1412  {
1413 #ifdef SCIP_MORE_DEBUG
1414  SCIPdebugMessage(" -> adding nonzero 1.0 at (%d,%d) for penalty variable r in SDPA (%d)\n",
1415  sdpisolver->rowmapper[2*lastrow], sdpisolver->rowmapper[2*lastrow], sdpisolver->sdpcounter);
1416 #endif
1417  /* LP nonzeros are added as diagonal entries of the last block (coming after the last SDP-block, with
1418  * blocks starting at 1, as are rows), the r-variable is variable nactivevars + 1 */
1419  sdpisolver->sdpa->inputElement((long long) sdpisolver->nactivevars + 1, (long long) nsdpblocks - nremovedblocks + 1, /*lint !e747, !e776, !e834*/
1420  (long long) sdpisolver->rowmapper[2*lastrow], (long long) sdpisolver->rowmapper[2*lastrow], 1.0, checkinput); /*lint !e679, !e747, !e834*/
1421  }
1422 
1423  /* check for the rhs-inequality */
1424  if ( sdpisolver->rowmapper[2*lastrow + 1] > -1 ) /*lint !e679*/
1425  {
1426 #ifdef SCIP_MORE_DEBUG
1427  SCIPdebugMessage(" -> adding nonzero 1.0 at (%d,%d) for penalty variable r in SDPA (%d)\n",
1428  sdpisolver->rowmapper[2*lastrow + 1], sdpisolver->rowmapper[2*lastrow + 1], sdpisolver->sdpcounter);
1429 #endif
1430  /* LP nonzeros are added as diagonal entries of the last block (coming after the last SDP-block, with
1431  * blocks starting at 1, as are rows), the r-variable is variable nactivevars + 1 */
1432  sdpisolver->sdpa->inputElement((long long) sdpisolver->nactivevars + 1, (long long) nsdpblocks - nremovedblocks + 1, /*lint !e747, !e776, !e834*/
1433  (long long) sdpisolver->rowmapper[2*lastrow + 1], (long long) sdpisolver->rowmapper[2*lastrow + 1], 1.0, checkinput); /*lint !e679, !e747, !e834*/
1434  }
1435  }
1436  }
1437  /* add the lp-nonzero to the lhs-inequality if it exists: */
1438  if ( sdpisolver->rowmapper[2*lastrow] > -1 ) /*lint !e679*/
1439  {
1440 #ifdef SCIP_MORE_DEBUG
1441  SCIPdebugMessage(" -> adding nonzero %g at (%d,%d) for variable %d which became variable %d in SDPA (%d)\n",
1442  lpval[i], sdpisolver->rowmapper[2*lastrow], sdpisolver->rowmapper[2*lastrow], lpcol[i], sdpisolver->inputtosdpamapper[lpcol[i]], sdpisolver->sdpcounter);
1443 #endif
1444  /* LP nonzeros are added as diagonal entries of the last block (coming after the last SDP-block, with blocks starting at 1, as are rows) */
1445  sdpisolver->sdpa->inputElement((long long) sdpisolver->inputtosdpamapper[lpcol[i]], (long long) nsdpblocks - nremovedblocks + 1, /*lint !e747, !e776, !e834*/
1446  (long long) sdpisolver->rowmapper[2*lastrow], (long long) sdpisolver->rowmapper[2*lastrow], lpval[i], checkinput); /*lint !e679, !e747, !e834*/
1447  }
1448  /* add the lp-nonzero to the rhs-inequality if it exists: */
1449  if ( sdpisolver->rowmapper[2*lastrow + 1] > -1 ) /*lint !e679*/
1450  {
1451 #ifdef SCIP_MORE_DEBUG
1452  SCIPdebugMessage(" -> adding nonzero %g at (%d,%d) for variable %d which became variable %d in SDPA (%d)\n",
1453  -1 * lpval[i], sdpisolver->rowmapper[2*lastrow + 1], sdpisolver->rowmapper[2*lastrow + 1], lpcol[i], sdpisolver->inputtosdpamapper[lpcol[i]], sdpisolver->sdpcounter);
1454 #endif
1455  /* LP nonzeros are added as diagonal entries of the last block (coming after the last SDP-block, with blocks starting at 1, as are rows),
1456  * the -1 comes from the fact that this is a <=-constraint, while SDPA works with >= */
1457  sdpisolver->sdpa->inputElement((long long) sdpisolver->inputtosdpamapper[lpcol[i]], (long long) nsdpblocks - nremovedblocks + 1, /*lint !e747, !e776, !e834*/
1458  (long long) sdpisolver->rowmapper[2*lastrow + 1], (long long) sdpisolver->rowmapper[2*lastrow + 1], -1 * lpval[i], checkinput); /*lint !e679, !e747, !e834*/
1459  }
1460  }
1461  }
1462  }
1463 
1464  /* inserting LP left- and right-hand-sides for active constraints */
1465  lpconsind = 1; /* this is the same order we used when computing the rowmapper, so we insert at the right positions */
1466  for (i = 0; i < nlpcons; i++)
1467  {
1468  /* check for left-hand side */
1469  if ( lplhs[i] > - SCIPsdpiSolverInfinity(sdpisolver) )
1470  {
1471 #ifdef SCIP_MORE_DEBUG
1472  SCIPdebugMessage(" -> adding lhs %g at (%d,%d) (%d)\n", lplhs[i], lpconsind, lpconsind, sdpisolver->sdpcounter);
1473 #endif
1474  /* LP constraints are added as diagonal entries of the last block, left-hand-side is added as variable zero */
1475  sdpisolver->sdpa->inputElement((long long) 0, (long long) nsdpblocks - nremovedblocks + 1, (long long) lpconsind, /*lint !e747, !e776, !e834*/
1476  (long long) lpconsind, lplhs[i], checkinput);/*lint !e747*/
1477  lpconsind++;
1478  }
1479 
1480  /* check for right-hand side */
1481  if ( lprhs[i] < SCIPsdpiSolverInfinity(sdpisolver) )
1482  {
1483 #ifdef SCIP_MORE_DEBUG
1484  SCIPdebugMessage(" -> adding lhs (originally rhs) %g at (%d,%d) (%d)\n", -1 * lprhs[i], lpconsind, lpconsind, sdpisolver->sdpcounter);
1485 #endif
1486  /* LP constraints are added as diagonal entries of the last block, right-hand side is added as variable zero, the -1 comes from
1487  * the fact, that SDPA uses >=, while the rhs is a <=-constraint */
1488  sdpisolver->sdpa->inputElement((long long) 0, (long long) nsdpblocks - nremovedblocks + 1, (long long) lpconsind, /*lint !e747, !e776, !e834*/
1489  (long long) lpconsind, -1 * lprhs[i], checkinput);/*lint !e747*/
1490  lpconsind++;
1491  }
1492  }
1493 
1494  assert( lpconsind == nlpineqs + 1 ); /* plus one because we started at one as SDPA wants them numbered one to nlpineqs */
1495 
1496  /* print each LP-constraint as one formatted constraint in addition to the single entries inserted into SDPA */
1497 #ifdef SCIP_MORE_DEBUG
1498  lastrow = -1;
1499  ind = -1; /* this is increased once before the first usage */
1500  for (i = 0; i < lpnnonz; i++)
1501  {
1502  /* if the variable is active and the constraint is more than a bound, we added it */
1503  if ( sdpisolver->inputtosdpamapper[lpcol[i]] > 0 )
1504  {
1505  if ( rownactivevars[lprow[i]] > 1 )
1506  {
1507  if ( lprow[i] > lastrow ) /* we finished the old row */
1508  {
1509  if ( lastrow >= 0 )
1510  {
1511  if ( lprhs[ind] < SCIPsdpiSolverInfinity(sdpisolver) )
1512  SCIPmessagePrintInfo(sdpisolver->messagehdlr, " <= %f\n", lprhs[ind]);
1513  else
1514  SCIPmessagePrintInfo(sdpisolver->messagehdlr, "\n");
1515  }
1516  lastrow = lprow[i];
1517  ind++;
1518  if ( lplhs[ind] > - SCIPsdpiSolverInfinity(sdpisolver) )
1519  SCIPmessagePrintInfo(sdpisolver->messagehdlr, "%f <= ", lplhs[ind]);
1520  }
1521  SCIPmessagePrintInfo(sdpisolver->messagehdlr, "+ %f <x%d> ", lpval[i], lpcol[i]);
1522  }
1523  }
1524  }
1525  if ( lastrow >= 0 )
1526  {
1527  if ( lprhs[ind] < SCIPsdpiSolverInfinity(sdpisolver) )
1528  SCIPmessagePrintInfo(sdpisolver->messagehdlr, " <= %f\n", lprhs[ind]);
1529  else
1530  SCIPmessagePrintInfo(sdpisolver->messagehdlr, "\n");
1531  }
1532  assert( ind == nlpcons - 1 ); /* -1 because we start indexing at zero and do not increase after the last row */
1533 #endif
1534 
1535  /* insert variable bounds, these are also added as LP-constraints and therefore diagonal entries of the LP block
1536  * if we work with the penalty formulation, we get an extra entry for r >= 0, but this we will add afterwards */
1537  for (i = 0; i < ((penaltyparam < sdpisolver->epsilon) || (! rbound) ? sdpisolver->nvarbounds : sdpisolver->nvarbounds - 1); i++)
1538  {
1539  assert( 0 < abs(sdpisolver->varboundpos[i]) && abs(sdpisolver->varboundpos[i] <= sdpisolver->nactivevars) ); /* the indices are already those for SDPA */
1540 
1541  /* for lower bound */
1542  if ( sdpisolver->varboundpos[i] < 0 )
1543  {
1544  /* add it as an lp-constraint for this variable (- because we saved -n for the lower bound), at the position
1545  * (nactivelpcons + 1) + varbound-index, because we have >= the variable has coefficient +1 */
1546  sdpisolver->sdpa->inputElement((long long) -sdpisolver->varboundpos[i], (long long) nsdpblocks - nremovedblocks + 1, /*lint !e747, !e776, !e834*/
1547  (long long) nlpineqs + 1 + i, (long long) nlpineqs + 1 + i, 1.0, checkinput);/*lint !e747*/
1548 
1549  if ( REALABS(sdpavarbounds[i]) > sdpisolver->epsilon )
1550  {
1551  /* the bound is added as the rhs and therefore variable zero */
1552 #ifdef SCIP_MORE_DEBUG
1553  SCIPdebugMessage(" -> adding lower bound %g at (%d,%d) for variable %d which became variable %d in SDPA (%d)\n",
1554  sdpavarbounds[i], nlpineqs + 1 + i, nlpineqs + 1 + i, sdpisolver->sdpatoinputmapper[-sdpisolver->varboundpos[i] - 1],
1555  -sdpisolver->varboundpos[i], sdpisolver->sdpcounter);
1556 #endif
1557  sdpisolver->sdpa->inputElement((long long) 0, (long long) nsdpblocks - nremovedblocks + 1, (long long) nlpineqs + 1 + i, /*lint !e747, !e776, !e834*/
1558  (long long) nlpineqs + 1 + i, sdpavarbounds[i], checkinput);/*lint !e747*/
1559  }
1560  else
1561  {
1562  /* as the bound is zero, we don't need to add a right hand side */
1563 #ifdef SCIP_MORE_DEBUG
1564  SCIPdebugMessage(" -> adding lower bound 0 at (%d,%d) for variable %d which became variable %d in SDPA (%d)\n",
1565  nlpineqs + 1 + i, nlpineqs + 1 + i, sdpisolver->sdpatoinputmapper[-sdpisolver->varboundpos[i] - 1],
1566  -sdpisolver->varboundpos[i], sdpisolver->sdpcounter);
1567 #endif
1568  }
1569  }
1570  else
1571  {
1572  /* this is an upper bound */
1573 
1574  /* add it as an lp-constraint for this variable, at the position nactivelpcons + varbound-index, because we have >= but we
1575  * want <= for the upper bound, we have to multiply by -1 and therefore the variable has coefficient -1 */
1576  sdpisolver->sdpa->inputElement((long long) sdpisolver->varboundpos[i], (long long) nsdpblocks - nremovedblocks + 1, /*lint !e747, !e776, !e834*/
1577  (long long) nlpineqs + 1 + i, (long long) nlpineqs + 1 + i, -1.0, checkinput);/*lint !e747*/
1578 
1579  if ( REALABS(sdpavarbounds[i]) > sdpisolver->epsilon )
1580  {
1581  /* the bound is added as the rhs and therefore variable zero, we multiply by -1 for <= */
1582 #ifdef SCIP_MORE_DEBUG
1583  SCIPdebugMessage(" -> adding upper bound %g at (%d,%d) for variable %d which became variable %d in SDPA (%d)\n",
1584  sdpavarbounds[i], nlpineqs + 1 + i, nlpineqs + 1 + i, sdpisolver->sdpatoinputmapper[sdpisolver->varboundpos[i] - 1],
1585  sdpisolver->varboundpos[i], sdpisolver->sdpcounter);
1586 #endif
1587  sdpisolver->sdpa->inputElement((long long) 0, (long long) nsdpblocks - nremovedblocks + 1, (long long) nlpineqs + 1 + i, /*lint !e747, !e776, !e834*/
1588  (long long) nlpineqs + 1 + i, -sdpavarbounds[i], checkinput);/*lint !e747*/
1589  }
1590  else
1591  {
1592  /* as the bound is zero, we don't need to add a right hand side */
1593 #ifdef SCIP_MORE_DEBUG
1594  SCIPdebugMessage(" -> adding upper bound 0 at (%d,%d) for variable %d which became variable %d in SDPA (%d)\n",
1595  0, nlpineqs + 1 + i, nlpineqs + 1 + i, sdpisolver->sdpatoinputmapper[sdpisolver->varboundpos[i] - 1],
1596  sdpisolver->varboundpos[i]);
1597 #endif
1598  }
1599  }
1600  }
1601 
1602  if ( penaltyparam >= sdpisolver->epsilon && rbound )
1603  {
1604  /* we add the variable bound r >= 0 */
1605  sdpisolver->sdpa->inputElement((long long) sdpisolver->nactivevars + 1, (long long) nsdpblocks - nremovedblocks + 1, /*lint !e747, !e776, !e834*/
1606  (long long) nlpineqs + 1 + i, (long long) nlpineqs + 1 + i, 1.0, checkinput);/*lint !e747*/
1607 #ifdef SCIP_MORE_DEBUG
1608  SCIPdebugMessage(" -> adding lower bound r >= 0 at (%d,%d) in SDPA (%d)\n", nlpineqs + 1 + i, nlpineqs + 1 + i, sdpisolver->sdpcounter);
1609 #endif
1610  }
1611 
1612  /* free the arrays used for counting and saving variable bounds and LP-right-hand-sides */
1613  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &sdpavarbounds); /*lint !e647, !e737*/
1614 
1615  /* transform the matrices to a more efficient form */
1616  sdpisolver->sdpa->initializeUpperTriangle();
1617  sdpisolver->sdpa->initializeSolve();
1618 
1619  /* set the starting solution */
1620  if ( starty != NULL && startZnblocknonz != NULL && startXnblocknonz != NULL && penaltyparam < sdpisolver->epsilon )
1621  {
1622  int sdpaind;
1623  int varboundind;
1624 
1625  /* set dual vector */
1626  for (i = 1; i <= sdpisolver->nactivevars; i++)
1627  sdpisolver->sdpa->inputInitXVec((long long) i, starty[sdpisolver->sdpatoinputmapper[i - 1]]);/*lint !e747*/
1628 
1629  /* set SDP-blocks of dual matrix */
1630  for (b = 0; b < nsdpblocks; b++)
1631  {
1632  if ( blockindchanges[b] > -1)
1633  {
1634  for (i = 0; i < startZnblocknonz[b]; i++)
1635  {
1636  if ( indchanges[b][startZrow[b][i]] > -1 && indchanges[b][startZcol[b][i]] > -1 ) /* the row/col may have been fixed to zero in the meantime */
1637  {
1638  sdpisolver->sdpa->inputInitXMat((long long) b + 1 - blockindchanges[b], (long long) startZrow[b][i] + 1 - indchanges[b][startZrow[b][i]],
1639  (long long) startZcol[b][i] + 1 - indchanges[b][startZcol[b][i]], startZval[b][i]);
1640  }
1641  }
1642  }
1643  }
1644 
1645  /* set LP-block of dual matrix */
1646  for (i = 0; i < startZnblocknonz[nsdpblocks]; i++)
1647  {
1648  assert( startZrow[nsdpblocks][i] == startZcol[nsdpblocks][i] );
1649 
1650  if ( startZrow[nsdpblocks][i] < 2 * sdpisolver->ninputlpcons ) /* linear constraint */
1651  {
1652  sdpaind = sdpisolver->rowmapper[startZrow[nsdpblocks][i]];
1653  if ( sdpaind > -1 )
1654  sdpisolver->sdpa->inputInitXMat((long long) nsdpblocks + 1, sdpaind, sdpaind, startZval[nsdpblocks][i]);
1655  }
1656  else /* varbound */
1657  {
1658  varboundind = sdpisolver->inputtovbmapper[startZrow[nsdpblocks][i] - 2 * sdpisolver->ninputlpcons];
1659  if ( varboundind > -1 ) /* rhs */
1660  {
1661  sdpisolver->sdpa->inputInitXMat((long long) nsdpblocks + 1, nlpineqs + varboundind + 1,
1662  nlpineqs + varboundind + 1, startZval[nsdpblocks][i]);
1663  }
1664  }
1665  }
1666 
1667  /*set SDP-blocks of primal matrix */
1668  for (b = 0; b < nsdpblocks; b++)
1669  {
1670  if ( blockindchanges[b] > -1)
1671  {
1672  for (i = 0; i < startXnblocknonz[b]; i++)
1673  {
1674  if ( indchanges[b][startXrow[b][i]] > -1 && indchanges[b][startXcol[b][i]] > -1 ) /* the row/col may have been fixed to zero in the meantime */
1675  {
1676  sdpisolver->sdpa->inputInitYMat((long long) b + 1 - blockindchanges[b], (long long) startXrow[b][i] + 1 - indchanges[b][startXrow[b][i]],
1677  (long long) startXcol[b][i] + 1 - indchanges[b][startXcol[b][i]], startXval[b][i]);
1678  }
1679  }
1680  }
1681  }
1682 
1683  /* set LP-block of primal matrix */
1684  for (i = 0; i < startXnblocknonz[nsdpblocks]; i++)
1685  {
1686  assert( startXrow[nsdpblocks][i] == startXcol[nsdpblocks][i] );
1687 
1688  if ( startXrow[nsdpblocks][i] < 2 * sdpisolver->ninputlpcons ) /* linear constraint */
1689  {
1690  sdpaind = sdpisolver->rowmapper[startXrow[nsdpblocks][i]];
1691  if ( sdpaind > -1 )
1692  sdpisolver->sdpa->inputInitYMat((long long) nsdpblocks + 1, sdpaind, sdpaind, startXval[nsdpblocks][i]);
1693  }
1694  else /* varbound */
1695  {
1696  varboundind = sdpisolver->inputtovbmapper[startXrow[nsdpblocks][i] - 2 * sdpisolver->ninputlpcons];
1697  if ( varboundind > -1 ) /*lhs */
1698  {
1699  sdpisolver->sdpa->inputInitYMat((long long) nsdpblocks + 1, nlpineqs + varboundind + 1,
1700  nlpineqs + varboundind + 1, startXval[nsdpblocks][i]);
1701  }
1702  }
1703  }
1704  }
1705  else if ( penaltyparam >= sdpisolver->epsilon )
1706  SCIPdebugMessage("Skipping insertion of starting point for penalty formulation.\n");
1707 
1708 #ifdef SCIP_DEBUG_PRINTTOFILE
1709  /* if necessary, dump input data and initial point */
1710  sdpisolver->sdpa->writeInputSparse(const_cast<char*>("sdpa.dat-s"), const_cast<char*>("%+8.3e"));
1711  sdpisolver->sdpa->writeInitSparse(const_cast<char*>("sdpa.ini-s"), const_cast<char*>("%+8.3e"));
1712 #endif
1713 
1714  SCIPdebugMessage("Calling SDPA solve (SDP: %d)\n", sdpisolver->sdpcounter);
1715 
1716  /* check if we want to save a preoptimal solution for warmstarting purposes */
1717  if ( sdpisolver->preoptimalgap >= 0.0 && (startsettings == SCIP_SDPSOLVERSETTING_UNSOLVED || startsettings == SCIP_SDPSOLVERSETTING_FAST) )
1718  {
1719  SCIP_Real* sdpasol;
1720  int sdpablocksize;
1721 
1722  /* first solve up to gaptol */
1723  sdpisolver->sdpa->setParameterEpsilonStar(sdpisolver->preoptimalgap);
1724  sdpisolver->sdpa->setParameterEpsilonDash(sdpisolver->preoptimalgap);
1725  sdpisolver->sdpa->solve();
1726 
1727  /* save preoptimal solution (only if solving succeeded) */
1728  if ( SCIPsdpiSolverIsAcceptable(sdpisolver) )
1729  {
1730  SCIPdebugMessage("Saving preoptimal solution for warmstarting purposes\n");
1731  sdpasol = sdpisolver->sdpa->getResultXVec();
1732 
1733  /* copy dual solution vector */
1734  for (i = 0; i < sdpisolver->nactivevars; i++)
1735  sdpisolver->preoptimalsol[i] = sdpasol[i];
1736 
1737  /* copy primal matrix */
1738  for (b = 0; b < sdpisolver->sdpa->getBlockNumber(); b++)
1739  {
1740  sdpasol = sdpisolver->sdpa->getResultYMat(b + 1);
1741  sdpablocksize = sdpisolver->sdpa->getBlockSize(b + 1);
1742  if ( sdpisolver->sdpa->getBlockType(b + 1) == SDPA::LP )
1743  {
1744  /* only the diagonal entries need to be saved */
1745  for (i = 0; i < sdpablocksize; i++)
1746  sdpisolver->preoptimalsolx[b][i] = sdpasol[i];
1747  }
1748  else
1749  {
1750  /* TODO: think about saving this in sparse format or at least only the upper triangular matrix */
1751  for (i = 0; i < sdpablocksize * sdpablocksize; i++)
1752  sdpisolver->preoptimalsolx[b][i] = sdpasol[i];
1753  }
1754  }
1755 
1756  sdpisolver->preoptimalsolexists = TRUE;
1757  }
1758  else
1759  {
1760  SCIPdebugMessage("Solving to gaptol failed! No preoptimal solution available.\n");
1761  }
1762 
1763  /* add number of iterations */
1764  sdpisolver->niterations += (int) sdpisolver->sdpa->getIteration();
1765 
1766  /* copy current iterate and resolve with real tolerance */
1767  sdpisolver->sdpa->setInitPoint(true);
1768  sdpisolver->sdpa->copyCurrentToInit();
1769  sdpisolver->sdpa->setParameterEpsilonStar(sdpisolver->gaptol);
1770  sdpisolver->sdpa->setParameterEpsilonDash(sdpisolver->sdpsolverfeastol);
1771  sdpisolver->sdpa->solve();
1772  }
1773  else
1774  sdpisolver->sdpa->solve();
1775 
1776  sdpisolver->solved = TRUE;
1777 
1778  /* update number of SDP-iterations and -calls */
1779  sdpisolver->niterations += (int) sdpisolver->sdpa->getIteration();
1780  sdpisolver->nsdpcalls += 1;
1781 
1782 #ifdef SCIP_DEBUG
1783  /* print the phase value , i.e. whether solving was successfull */
1784  sdpisolver->sdpa->getPhaseString((char*)phase_string);
1785  SCIPdebugMessage("SDPA solving finished with status %s (primal and dual here are switched in contrast to our formulation)\n", phase_string);
1786 #endif
1787 
1788  /* remember settings */
1789  if ( SCIPsdpiSolverIsAcceptable(sdpisolver) && penaltyparam < sdpisolver->epsilon )
1790  sdpisolver->usedsetting = SCIP_SDPSOLVERSETTING_FAST;
1791  else if ( penaltyparam >= sdpisolver->epsilon )
1792  sdpisolver->usedsetting = SCIP_SDPSOLVERSETTING_PENALTY;
1793 
1794  /* if the problem has been stably solved but did not reach the required feasibility tolerance, even though the solver
1795  * reports feasibility, resolve it with adjusted tolerance */
1796  SCIP_CALL( checkFeastolAndResolve(sdpisolver, penaltyparam, nvars, lb, ub, nsdpblocks, sdpblocksizes, sdpnblockvars, sdpconstnnonz,
1797  sdpconstnblocknonz, sdpconstrow, sdpconstcol, sdpconstval, sdpnnonz, sdpnblockvarnonz, sdpvar, sdprow, sdpcol, sdpval, indchanges,
1798  nremovedinds, blockindchanges, nlpcons, noldlpcons, lplhs, lprhs, rownactivevars, lpnnonz, lprow, lpcol, lpval, &feastol) );
1799 
1800  /* check whether problem has been stably solved, if it wasn't and we didn't yet use the default parametersettings (for the penalty formulation we do so), try
1801  * again with more stable parameters */
1802  if ( ! SCIPsdpiSolverIsAcceptable(sdpisolver) && penaltyparam < sdpisolver->epsilon &&
1803  (startsettings == SCIP_SDPSOLVERSETTING_UNSOLVED || startsettings == SCIP_SDPSOLVERSETTING_FAST) )
1804  {
1805  SCIPdebugMessage("Numerical troubles -- solving SDP %d again ...\n", sdpisolver->sdpcounter);
1806 
1807  /* initialize settings */
1808  sdpisolver->sdpa->setParameterType(SDPA::PARAMETER_DEFAULT);
1809  sdpisolver->sdpa->setParameterEpsilonStar(GAPTOLCHANGE * sdpisolver->gaptol);
1810  sdpisolver->sdpa->setParameterEpsilonDash(FEASTOLCHANGE * sdpisolver->sdpsolverfeastol);
1811  sdpisolver->sdpa->setParameterLowerBound(-1e20);
1812  /* set the objective limit */
1813  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, sdpisolver->objlimit) )
1814  sdpisolver->sdpa->setParameterUpperBound(sdpisolver->objlimit);
1815  else
1816  sdpisolver->sdpa->setParameterUpperBound(1e8);
1817 
1818  /* increase Lambda Star, this seems to help the numerics */
1819  sdpisolver->sdpa->setParameterLambdaStar(sdpisolver->lambdastar);
1820 
1821 #ifdef SCIP_MORE_DEBUG
1822  sdpisolver->sdpa->printParameters(stdout);
1823 #endif
1824  sdpisolver->sdpa->setInitPoint(false);
1825 #ifdef SDPA_RESETPARAMS
1826  sdpisolver->sdpa->resetParameters();
1827 #else
1828  sdpisolver->sdpa->initializeSolve();
1829 #endif
1830  sdpisolver->sdpa->solve();
1831  sdpisolver->solved = TRUE;
1832 
1833  /* update number of SDP-iterations and -calls */
1834  sdpisolver->niterations += (int) sdpisolver->sdpa->getIteration();
1835  sdpisolver->nsdpcalls += 1;
1836 
1837  /* remember setting */
1838  if ( SCIPsdpiSolverIsAcceptable(sdpisolver) )
1839  sdpisolver->usedsetting = SCIP_SDPSOLVERSETTING_MEDIUM;
1840 
1841 #ifdef SCIP_DEBUG
1842  /* print the phase value , i.e. whether solving was successfull */
1843  sdpisolver->sdpa->getPhaseString((char*)phase_string);
1844  SCIPdebugMessage("SDPA solving finished with status %s (primal and dual here are switched in contrast to our formulation)\n", phase_string);
1845 #endif
1846 
1847  /* if the problem has been stably solved but did not reach the required feasibility tolerance, even though the solver
1848  * reports feasibility, resolve it with adjusted tolerance */
1849  SCIP_CALL( checkFeastolAndResolve(sdpisolver, penaltyparam, nvars, lb, ub, nsdpblocks, sdpblocksizes, sdpnblockvars, sdpconstnnonz,
1850  sdpconstnblocknonz, sdpconstrow, sdpconstcol, sdpconstval, sdpnnonz, sdpnblockvarnonz, sdpvar, sdprow, sdpcol, sdpval, indchanges,
1851  nremovedinds, blockindchanges, nlpcons, noldlpcons, lplhs, lprhs, rownactivevars, lpnnonz, lprow, lpcol, lpval, &feastol) );
1852  }
1853 
1854  /* if we still didn't converge, and did not yet use the stable settings, set the parameters even more conservativly */
1855  if ( (! SCIPsdpiSolverIsAcceptable(sdpisolver)) && penaltyparam < sdpisolver->epsilon &&
1856  (startsettings == SCIP_SDPSOLVERSETTING_UNSOLVED || startsettings == SCIP_SDPSOLVERSETTING_FAST || startsettings == SCIP_SDPSOLVERSETTING_MEDIUM) )
1857  {
1858  SCIPdebugMessage("Numerical troubles -- solving SDP %d again^2 ...\n", sdpisolver->sdpcounter);
1859 
1860  /* initialize settings */
1861  sdpisolver->sdpa->setParameterType(SDPA::PARAMETER_STABLE_BUT_SLOW);
1862  sdpisolver->sdpa->setParameterEpsilonStar(GAPTOLCHANGE * GAPTOLCHANGE * sdpisolver->gaptol);
1863  sdpisolver->sdpa->setParameterEpsilonDash(FEASTOLCHANGE * FEASTOLCHANGE * sdpisolver->sdpsolverfeastol);
1864  sdpisolver->sdpa->setParameterLowerBound(-1e20);
1865  /* set the objective limit */
1866  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, sdpisolver->objlimit) )
1867  sdpisolver->sdpa->setParameterUpperBound(sdpisolver->objlimit);
1868  else
1869  sdpisolver->sdpa->setParameterUpperBound(1e8);
1870 
1871  /* increase Lambda Star, this seems to help the numerics */
1872  sdpisolver->sdpa->setParameterLambdaStar(sdpisolver->lambdastar);
1873 
1874 #ifdef SCIP_MORE_DEBUG
1875 sdpisolver->sdpa->printParameters(stdout);
1876 #endif
1877  sdpisolver->sdpa->setInitPoint(false);
1878 #ifdef SDPA_RESETPARAMS
1879  sdpisolver->sdpa->resetParameters();
1880 #else
1881  sdpisolver->sdpa->initializeSolve();
1882 #endif
1883  sdpisolver->sdpa->solve();
1884  sdpisolver->solved = TRUE;
1885 
1886  /* update number of SDP-iterations and -calls */
1887  sdpisolver->niterations += (int) sdpisolver->sdpa->getIteration();
1888  sdpisolver->nsdpcalls += 1;
1889 
1890  /* remember setting */
1891  if ( SCIPsdpiSolverIsAcceptable(sdpisolver) )
1892  sdpisolver->usedsetting = SCIP_SDPSOLVERSETTING_STABLE;
1893 
1894 #ifdef SCIP_DEBUG
1895  /* print the phase value , i.e. whether solving was successfull */
1896  sdpisolver->sdpa->getPhaseString((char*)phase_string);
1897  SCIPdebugMessage("SDPA solving finished with status %s (primal and dual here are switched in constrast to our formulation)\n", phase_string);
1898 #endif
1899 
1900  /* if the problem has been stably solved but did not reach the required feasibility tolerance, even though the solver
1901  * reports feasibility, resolve it with adjusted tolerance */
1902  SCIP_CALL( checkFeastolAndResolve(sdpisolver, penaltyparam, nvars, lb, ub, nsdpblocks, sdpblocksizes, sdpnblockvars, sdpconstnnonz,
1903  sdpconstnblocknonz, sdpconstrow, sdpconstcol, sdpconstval, sdpnnonz, sdpnblockvarnonz, sdpvar, sdprow, sdpcol, sdpval, indchanges,
1904  nremovedinds, blockindchanges, nlpcons, noldlpcons, lplhs, lprhs, rownactivevars, lpnnonz, lprow, lpcol, lpval, &feastol) );
1905  }
1906 
1907 #ifdef SCIP_MORE_DEBUG
1908  (void) fclose(fpOut);
1909 #endif
1910 
1911  /* if we solved a penalty formulation, check if the solution is feasible for the original problem (which is the case iff r < feastol) */
1912  if ( penaltyparam >= sdpisolver->epsilon )
1913  {
1914  SCIP_Real* sdpasol;
1915  SCIP_Real* X;
1916  int nblockssdpa;
1917  int nrow;
1918  SCIP_Real trace = 0.0;
1919 
1920  /* in the second case we have r as an additional variable */
1921  assert( (sdpisolver->nactivevars + 1 == sdpisolver->sdpa->getConstraintNumber()) ); /*lint !e776*/
1922 
1923  sdpasol = sdpisolver->sdpa->getResultXVec();
1924 
1925  /* we get r as the last variable in SDPA */
1926  assert( feasorig != NULL );
1927  *feasorig = (sdpasol[sdpisolver->nactivevars] < sdpisolver->feastol); /*lint !e413*/
1928 
1929  /* only set sdpisolver->feasorig to true if we solved with objective, because only in this case we want to compute
1930  * the objective value by hand since it is numerically more stable then the result returned by SDPA */
1931  if ( withobj )
1932  sdpisolver->feasorig = *feasorig;
1933 
1934  /* if r > 0 or we are in debug mode, also check the primal bound */
1935 #ifdef NDEBUG
1936  if ( ! *feasorig && penaltybound != NULL )
1937  {
1938 #endif
1939 
1940  SCIPdebugMessage("Solution not feasible in original problem, r = %f\n", sdpasol[sdpisolver->nactivevars]);
1941 
1942  /* compute Tr(X) */
1943 
1944  /* iterate over all blocks (SDPA starts counting at one and includes the LP block) */
1945  nblockssdpa = (int) sdpisolver->sdpa->getBlockNumber();
1946  for (b = 1; b <= nblockssdpa; b++)
1947  {
1948  /* get the block from SDPA */
1949  X = sdpisolver->sdpa->getResultYMat((long long) b);/*lint !e747*/
1950  nrow = (int) sdpisolver->sdpa->getBlockSize((long long) b);/*lint !e747*/
1951  assert( nrow >= 0 );
1952 
1953  /* if it is the LP-block, we omit the variable bounds as the penalty variable is not added to them */
1954  if ( sdpisolver->sdpa->getBlockType((long long) b) == SDPA::LP )/*lint !e747*/
1955  {
1956  /* iterate over all diagonal entries (until we reach the varbound part), adding them to the trace */
1957  for (i = 0; i < nrow - sdpisolver->nvarbounds; i++)
1958  trace += X[i]; /* get entry (i+1,i+1) for the diagonal matrix X */
1959  }
1960  else
1961  {
1962  /* iterate over all diagonal entries and add them to the trace */
1963  for (i = 0; i < nrow; i++)
1964  trace += X[i + i*nrow];/*lint !e679*/ /* get entry (i+1,i+1) in X */
1965  }
1966  }
1967 
1968  /* if the relative gap is smaller than the tolerance, we return equality */
1969  if ( (penaltyparam - trace) / penaltyparam < PENALTYBOUNDTOL )/*lint !e414*/
1970  {
1971  if ( penaltybound != NULL )
1972  *penaltybound = TRUE;
1973  SCIPdebugMessage("Tr(X) = %f == %f = Gamma, penalty formulation not exact, Gamma should be increased or problem is infeasible\n",
1974  trace, penaltyparam);
1975  }
1976  else if ( penaltybound != NULL )
1977  *penaltybound = FALSE;
1978 
1979 #ifdef NDEBUG
1980  }
1981 #endif
1982  }
1983  return SCIP_OKAY;
1984 }
1985 
1991 /*
1992  * Solution Information Methods
1993  */
1994 
1999 SCIP_Bool SCIPsdpiSolverWasSolved(
2000  SCIP_SDPISOLVER* sdpisolver
2001  )
2002 {/*lint !e1784*/
2003  assert( sdpisolver != NULL );
2004  return sdpisolver->solved;
2005 }
2006 
2014  SCIP_SDPISOLVER* sdpisolver
2015  )
2016 {/*lint !e1784*/
2017  SDPA::PhaseType phasetype;
2018 
2019  assert( sdpisolver != NULL );
2020  assert( sdpisolver->sdpa != NULL);
2021  CHECK_IF_SOLVED_BOOL( sdpisolver );
2022 
2023  phasetype = sdpisolver->sdpa->getPhaseValue();
2024 
2025  if ( phasetype == SDPA::noINFO || phasetype == SDPA::pFEAS || phasetype == SDPA::dFEAS || phasetype == SDPA::pdINF )
2026  return FALSE;
2027 
2028  return TRUE;
2029 }
2030 
2032 SCIP_RETCODE SCIPsdpiSolverGetSolFeasibility(
2033  SCIP_SDPISOLVER* sdpisolver,
2034  SCIP_Bool* primalfeasible,
2035  SCIP_Bool* dualfeasible
2036  )
2037 {/*lint !e1784*/
2038  SDPA::PhaseType phasetype;
2039 
2040  assert( sdpisolver != NULL );
2041  assert( sdpisolver->sdpa != NULL );
2042  assert( primalfeasible != NULL );
2043  assert( dualfeasible != NULL );
2044  CHECK_IF_SOLVED( sdpisolver );
2045 
2046  phasetype = sdpisolver->sdpa->getPhaseValue();
2047 
2048  switch ( phasetype )/*lint --e{788}*/
2049  {
2050  case SDPA::pdOPT:
2051  *primalfeasible = TRUE;
2052  *dualfeasible = TRUE;
2053  break;
2054  case SDPA::pdFEAS:
2055  *primalfeasible = TRUE;
2056  *dualfeasible = TRUE;
2057  break;
2058  case SDPA::pFEAS_dINF:
2059  *primalfeasible = TRUE;
2060  *dualfeasible = FALSE;
2061  break;
2062  case SDPA::pINF_dFEAS:
2063  *primalfeasible = FALSE;
2064  *dualfeasible = TRUE;
2065  break;
2066  case SDPA::pUNBD:
2067  *primalfeasible = TRUE;
2068  *dualfeasible = FALSE;
2069  SCIPdebugMessage("SDPA stopped because dual objective became smaller than lower bound\n");
2070  break;
2071  case SDPA::dUNBD:
2072  *primalfeasible = FALSE;
2073  *dualfeasible = TRUE;
2074  SCIPdebugMessage("SDPA stopped because primal objective became bigger than upper bound\n");
2075  break;
2076  default: /* contains noInfo, pFeas, dFeas, pdInf */
2077  SCIPerrorMessage("SDPA doesn't know if primal and dual solutions are feasible\n");
2078  return SCIP_LPERROR;
2079  }
2080 
2081  return SCIP_OKAY;
2082 }
2083 
2088  SCIP_SDPISOLVER* sdpisolver
2089  )
2090 {/*lint !e1784*/
2091  SDPA::PhaseType phasetype;
2092 
2093  assert( sdpisolver != NULL );
2094  assert( sdpisolver->sdpa != NULL );
2095  CHECK_IF_SOLVED_BOOL( sdpisolver );
2096 
2097  phasetype = sdpisolver->sdpa->getPhaseValue();
2098 
2099  if ( phasetype == SDPA::noINFO || phasetype == SDPA::pFEAS || phasetype == SDPA::pdINF )
2100  {
2101  SCIPdebugMessage("SDPA doesn't know if primal problem is unbounded");
2102  return FALSE;
2103  }
2104  else if ( phasetype == SDPA::pFEAS_dINF )
2105  return TRUE;
2106  else if ( phasetype == SDPA::pUNBD )
2107  {
2108  SCIPdebugMessage("SDPA was stopped because primal objective became bigger than upper bound");
2109  return TRUE;
2110  }
2111 
2112  return FALSE;
2113 }
2114 
2119  SCIP_SDPISOLVER* sdpisolver
2120  )
2121 {/*lint !e1784*/
2122  SDPA::PhaseType phasetype;
2123 
2124  assert( sdpisolver != NULL );
2125  assert( sdpisolver->sdpa != NULL );
2126  CHECK_IF_SOLVED_BOOL( sdpisolver );
2127 
2128  phasetype = sdpisolver->sdpa->getPhaseValue();
2129 
2130  if ( phasetype == SDPA::noINFO || phasetype == SDPA::dFEAS || phasetype == SDPA::pdINF )
2131  {
2132  SCIPdebugMessage("SDPA doesn't know if primal problem is infeasible");
2133  return FALSE;
2134  }
2135  else if ( phasetype == SDPA::pINF_dFEAS )
2136  return TRUE;
2137  else if ( phasetype == SDPA::dUNBD )
2138  {
2139  SCIPdebugMessage("SDPA was stopped because dual objective became smaller than lower bound");
2140  return TRUE;
2141  }
2142 
2143  return FALSE;
2144 }
2145 
2150  SCIP_SDPISOLVER* sdpisolver
2151  )
2152 {/*lint !e1784*/
2153  SDPA::PhaseType phasetype;
2154 
2155  assert( sdpisolver != NULL );
2156  assert( sdpisolver->sdpa != NULL );
2157  CHECK_IF_SOLVED_BOOL( sdpisolver );
2158 
2159  phasetype = sdpisolver->sdpa->getPhaseValue();
2160 
2161  if ( phasetype == SDPA::noINFO || phasetype == SDPA::dFEAS || phasetype == SDPA::pdINF )
2162  {
2163  SCIPdebugMessage("SDPA doesn't know if primal problem is feasible");
2164  return FALSE;
2165  }
2166  else if ( phasetype == SDPA::pFEAS_dINF || phasetype == SDPA::pdOPT || phasetype == SDPA::pFEAS || phasetype == SDPA::pdFEAS )
2167  return TRUE;
2168  else if ( phasetype == SDPA::dUNBD )
2169  {
2170  SCIPdebugMessage("SDPA was stopped because dual objective became smaller than lower bound");
2171  return TRUE;
2172  }
2173 
2174  return FALSE;
2175 }
2176 
2181  SCIP_SDPISOLVER* sdpisolver
2182  )
2183 {/*lint !e1784*/
2184  SDPA::PhaseType phasetype;
2185 
2186  assert( sdpisolver != NULL );
2187  assert( sdpisolver->sdpa != NULL);
2188  CHECK_IF_SOLVED_BOOL( sdpisolver );
2189 
2190  phasetype = sdpisolver->sdpa->getPhaseValue();
2191 
2192  if ( phasetype == SDPA::noINFO || phasetype == SDPA::dFEAS || phasetype == SDPA::pdINF )
2193  {
2194  SCIPdebugMessage("SDPA doesn't know if dual problem is unbounded");
2195  return FALSE;
2196  }
2197  else if ( phasetype == SDPA::pINF_dFEAS )
2198  return TRUE;
2199  else if ( phasetype == SDPA::dUNBD )
2200  {
2201  SCIPdebugMessage("SDPA was stopped because dual objective became smaller than lower bound");
2202  return TRUE;
2203  }
2204 
2205  return FALSE;
2206 }
2207 
2212  SCIP_SDPISOLVER* sdpisolver
2213  )
2214 {/*lint !e1784*/
2215  SDPA::PhaseType phasetype;
2216 
2217  assert( sdpisolver != NULL );
2218  assert( sdpisolver->sdpa != NULL);
2219  CHECK_IF_SOLVED_BOOL( sdpisolver );
2220 
2221  phasetype = sdpisolver->sdpa->getPhaseValue();
2222 
2223  if ( phasetype == SDPA::noINFO || phasetype == SDPA::pFEAS || phasetype == SDPA::pdINF )
2224  {
2225  SCIPdebugMessage("SDPA doesn't know if dual problem is infeasible");
2226  return FALSE;
2227  }
2228  else if ( phasetype == SDPA::pFEAS_dINF )
2229  return TRUE;
2230  else if ( phasetype == SDPA::pUNBD )
2231  {
2232  SCIPdebugMessage("SDPA was stopped because primal objective became bigger than upper bound");
2233  return TRUE;
2234  }
2235 
2236  return FALSE;
2237 }
2238 
2243  SCIP_SDPISOLVER* sdpisolver
2244  )
2245 {/*lint !e1784*/
2246  SDPA::PhaseType phasetype;
2247 
2248  assert( sdpisolver != NULL );
2249  assert( sdpisolver->sdpa != NULL);
2250  CHECK_IF_SOLVED_BOOL( sdpisolver );
2251 
2252  phasetype = sdpisolver->sdpa->getPhaseValue();
2253 
2254  if ( phasetype == SDPA::noINFO || phasetype == SDPA::dFEAS || phasetype == SDPA::pdINF )
2255  {
2256  SCIPdebugMessage("SDPA doesn't know if primal problem is feasible");
2257  return FALSE;
2258  }
2259  else if ( phasetype == SDPA::pINF_dFEAS || phasetype == SDPA::pdOPT || phasetype == SDPA::dFEAS || phasetype == SDPA::pdFEAS )
2260  return TRUE;
2261  else if ( phasetype == SDPA::dUNBD )
2262  {
2263  SCIPdebugMessage("SDPA was stopped because dual objective became smaller than lower bound");
2264  return TRUE;
2265  }
2266 
2267  return FALSE;
2268 }
2269 
2271 SCIP_Bool SCIPsdpiSolverIsConverged(
2272  SCIP_SDPISOLVER* sdpisolver
2273  )
2274 {/*lint !e1784*/
2275  SDPA::PhaseType phasetype;
2276 
2277  assert( sdpisolver != NULL );
2278  assert( sdpisolver->sdpa != NULL );
2279  CHECK_IF_SOLVED_BOOL( sdpisolver );
2280 
2281  phasetype = sdpisolver->sdpa->getPhaseValue();
2282 
2283  if ( phasetype == SDPA::pdOPT )
2284  return TRUE;
2285 
2286  return FALSE;
2287 }
2288 
2290 SCIP_Bool SCIPsdpiSolverIsObjlimExc(
2291  SCIP_SDPISOLVER* sdpisolver
2292  )
2293 {/*lint !e1784*/
2294  SDPA::PhaseType phasetype;
2295 
2296  assert( sdpisolver != NULL );
2297  assert( sdpisolver->sdpa != NULL );
2298  CHECK_IF_SOLVED_BOOL( sdpisolver );
2299 
2300  phasetype = sdpisolver->sdpa->getPhaseValue();
2301 
2302  if ( phasetype == SDPA::pUNBD )
2303  return TRUE;
2304 
2305  return FALSE;
2306 }
2307 
2309 SCIP_Bool SCIPsdpiSolverIsIterlimExc(
2310  SCIP_SDPISOLVER* sdpisolver
2311  )
2312 {/*lint !e1784*/
2313  SDPA::PhaseType phasetype;
2314 
2315  assert( sdpisolver != NULL );
2316  assert( sdpisolver->sdpa != NULL);
2317  CHECK_IF_SOLVED_BOOL( sdpisolver );
2318 
2319  phasetype = sdpisolver->sdpa->getPhaseValue();
2320 
2321  if ( phasetype == SDPA::noINFO || phasetype == SDPA::pFEAS || phasetype == SDPA::dFEAS || phasetype == SDPA::pdFEAS )
2322  {
2323  if ( sdpisolver->sdpa->getParameterMaxIteration() == sdpisolver->sdpa->getIteration() )
2324  return TRUE;
2325  }
2326 
2327  return FALSE;
2328 }
2329 
2331 SCIP_Bool SCIPsdpiSolverIsTimelimExc(
2332  SCIP_SDPISOLVER* sdpisolver
2333  )
2334 {/*lint !e1784*/
2335  assert( sdpisolver != NULL );
2336 
2337  return sdpisolver->timelimit;
2338 }
2339 
2352  SCIP_SDPISOLVER* sdpisolver
2353  )
2354 {/*lint !e1784*/
2355  SDPA::PhaseType phasetype;
2356 
2357  assert( sdpisolver != NULL );
2358  assert( sdpisolver->sdpa != NULL );
2359 
2360  if ( sdpisolver->sdpa == NULL || (! sdpisolver->solved) )
2361  return -1;
2362 
2363  phasetype = sdpisolver->sdpa->getPhaseValue();
2364 
2365  if ( phasetype == SDPA::pdOPT || phasetype == SDPA::pFEAS_dINF || phasetype == SDPA::pINF_dFEAS )
2366  return 0;
2367  if ( phasetype == SDPA::pdINF )
2368  return 1;
2369  if ( phasetype == SDPA::pUNBD )
2370  return 3;
2371  if ( phasetype == SDPA::noINFO || phasetype == SDPA::pFEAS || phasetype == SDPA::dFEAS || phasetype == SDPA::pdFEAS )
2372  return 4;
2373  else /* should include dUNBD */
2374  return 7;
2375 }
2376 
2378 SCIP_Bool SCIPsdpiSolverIsOptimal(
2379  SCIP_SDPISOLVER* sdpisolver
2380  )
2381 {/*lint !e1784*/
2382  SDPA::PhaseType phasetype;
2383 
2384  assert( sdpisolver != NULL );
2385  assert( sdpisolver->sdpa != NULL );
2386 
2387  if ( ! sdpisolver->solved )
2388  return FALSE;
2389 
2390  phasetype = sdpisolver->sdpa->getPhaseValue();
2391 
2392  if ( phasetype == SDPA::pdOPT )
2393  return TRUE;
2394 
2395  return FALSE;
2396 }
2397 
2401 SCIP_Bool SCIPsdpiSolverIsAcceptable(
2402  SCIP_SDPISOLVER* sdpisolver
2403  )
2404 {/*lint !e1784*/
2405  SDPA::PhaseType phasetype;
2406 
2407  assert( sdpisolver != NULL );
2408  assert( sdpisolver->sdpa != NULL );
2409 
2410  if ( sdpisolver->timelimit )
2411  return FALSE;
2412 
2413  if ( ! sdpisolver->solved )
2414  return FALSE;
2415 
2416  phasetype = sdpisolver->sdpa->getPhaseValue();
2417 
2418  /* we are happy if we converged, or we reached the objective limit (pUNBD) or we could show that our problem is
2419  * infeasible [except for numerics], or unbounded */
2420  if ( SCIPsdpiSolverIsConverged(sdpisolver) || phasetype == SDPA::pUNBD || phasetype == SDPA::pINF_dFEAS || phasetype == SDPA::pFEAS_dINF )
2421  return TRUE;
2422 
2423  return FALSE;
2424 }
2425 
2427 SCIP_RETCODE SCIPsdpiSolverIgnoreInstability(
2428  SCIP_SDPISOLVER* sdpisolver,
2429  SCIP_Bool* success
2430  )
2431 {/*lint !e1784*/
2432  SCIPdebugMessage("Not implemented yet\n");
2433 
2434  return SCIP_LPERROR;
2435 }/*lint !e715*/
2436 
2438 SCIP_RETCODE SCIPsdpiSolverGetObjval(
2439  SCIP_SDPISOLVER* sdpisolver,
2440  SCIP_Real* objval
2441  )
2442 {/*lint !e1784*/
2443  assert( sdpisolver != NULL );
2444  assert( sdpisolver->sdpa != NULL );
2445  assert( objval != NULL );
2446  CHECK_IF_SOLVED( sdpisolver );
2447 
2448  if ( sdpisolver->penalty && ( ! sdpisolver->feasorig ) )
2449  {
2450  *objval = sdpisolver->sdpa->getPrimalObj();
2451 #ifndef NDEBUG
2452  SCIP_Real primalval = sdpisolver->sdpa->getDualObj();
2453  SCIP_Real gap = (REALABS(*objval - primalval) / (0.5 * (REALABS(primalval) + REALABS(*objval)))); /* duality gap used in SDPA */
2454  if ( gap > sdpisolver->gaptol )
2455  {
2456  SCIPdebugMessage("Attention: got objective value (before adding values of fixed variables) of %f in SCIPsdpiSolverGetSol, "
2457  "but primal objective is %f with duality gap %f!\n", *objval, primalval, gap );
2458  }
2459 #endif
2460  }
2461  else
2462  {
2463  SCIP_Real* sdpasol;
2464  int v;
2465 
2466  /* since the objective value given by SDPA sometimes differs slightly from the correct value for the given solution,
2467  * we get the solution from SDPA and compute the correct objective value */
2468  assert( (sdpisolver->penalty && sdpisolver->nactivevars + 1 == sdpisolver->sdpa->getConstraintNumber()) || /*lint !e776*/
2469  sdpisolver->nactivevars == sdpisolver->sdpa->getConstraintNumber() ); /* in the second case we have r as an additional variable */
2470  sdpasol = sdpisolver->sdpa->getResultXVec();
2471 
2472  *objval = 0.0;
2473  for (v = 0; v < sdpisolver->nactivevars; v++)
2474  *objval += sdpasol[v] * sdpisolver->objcoefs[v];
2475  }
2476 
2477  /* as we didn't add the fixed (lb = ub) variables to sdpa, we have to add their contributions to the objective by hand */
2478  *objval += sdpisolver->fixedvarsobjcontr;
2479 
2480  return SCIP_OKAY;
2481 }
2482 
2487 SCIP_RETCODE SCIPsdpiSolverGetSol(
2488  SCIP_SDPISOLVER* sdpisolver,
2489  SCIP_Real* objval,
2490  SCIP_Real* dualsol,
2491  int* dualsollength
2493  )
2494 {/*lint !e1784*/
2495  SCIP_Real* sdpasol;
2496  int v;
2497 
2498  assert( sdpisolver != NULL );
2499  assert( sdpisolver->sdpa != NULL );
2500  assert( dualsollength != NULL );
2501  CHECK_IF_SOLVED( sdpisolver );
2502 
2503  if ( objval != NULL )
2504  {
2505  if ( sdpisolver->penalty && ( ! sdpisolver->feasorig ) )
2506  {
2507  *objval = sdpisolver->sdpa->getPrimalObj();
2508 #ifndef NDEBUG
2509  SCIP_Real primalval = sdpisolver->sdpa->getDualObj();
2510  SCIP_Real gap = (REALABS(*objval - primalval) / (0.5 * (REALABS(primalval) + REALABS(*objval)))); /* duality gap used in SDPA */
2511  if ( gap > sdpisolver->gaptol )
2512  {
2513  SCIPdebugMessage("Attention: got objective value (before adding values of fixed variables) of %f in SCIPsdpiSolverGetSol, "
2514  "but primal objective is %f with duality gap %f!\n", *objval, primalval, gap );
2515  }
2516 #endif
2517  }
2518  else
2519  {
2520  /* since the objective value given by SDPA sometimes differs slightly from the correct value for the given solution,
2521  * we get the solution from SDPA and compute the correct objective value */
2522  assert( (sdpisolver->penalty && sdpisolver->nactivevars + 1 == sdpisolver->sdpa->getConstraintNumber()) || /*lint !e776*/
2523  sdpisolver->nactivevars == sdpisolver->sdpa->getConstraintNumber() ); /* in the second case we have r as an additional variable */
2524  sdpasol = sdpisolver->sdpa->getResultXVec();
2525 
2526  *objval = 0.0;
2527  for (v = 0; v < sdpisolver->nactivevars; v++)
2528  *objval += sdpasol[v] * sdpisolver->objcoefs[v];
2529  }
2530 
2531  /* as we didn't add the fixed (lb = ub) variables to sdpa, we have to add their contributions to the objective by hand */
2532  *objval += sdpisolver->fixedvarsobjcontr;
2533  }
2534 
2535  if ( *dualsollength > 0 )
2536  {
2537  assert( dualsol != NULL );
2538  if ( *dualsollength < sdpisolver->nvars )
2539  {
2540  SCIPdebugMessage("The given array in SCIPsdpiSolverGetSol only had length %d, but %d was needed", *dualsollength, sdpisolver->nvars);
2541  *dualsollength = sdpisolver->nvars;
2542 
2543  return SCIP_OKAY;
2544  }
2545 
2546  /* get the solution from sdpa */
2547  assert( (sdpisolver->penalty && sdpisolver->nactivevars + 1 == sdpisolver->sdpa->getConstraintNumber()) || /*lint !e776*/
2548  sdpisolver->nactivevars == sdpisolver->sdpa->getConstraintNumber() ); /* in the second case we have r as an additional variable */
2549  sdpasol = sdpisolver->sdpa->getResultXVec();
2550  /* insert the entries into dualsol, for non-fixed vars we copy those from sdpa, the rest are the saved entries from inserting (they equal lb=ub) */
2551  for (v = 0; v < sdpisolver->nvars; v++)
2552  {
2553  if ( sdpisolver->inputtosdpamapper[v] > 0 )
2554  {
2555  /* minus one because the inputtosdpamapper gives the sdpa indices which start at one, but the array starts at 0 */
2556  dualsol[v] = sdpasol[sdpisolver->inputtosdpamapper[v] - 1];
2557  }
2558  else
2559  {
2560  /* this is the value that was saved when inserting, as this variable has lb=ub */
2561  assert( -sdpisolver->inputtosdpamapper[v] <= sdpisolver->nvars - sdpisolver->nactivevars );
2562  dualsol[v] = sdpisolver->fixedvarsval[(-1 * sdpisolver->inputtosdpamapper[v]) - 1]; /*lint !e679*/
2563  }
2564  }
2565  }
2566  return SCIP_OKAY;
2567 }
2568 
2571  SCIP_SDPISOLVER* sdpisolver,
2572  int nblocks,
2573  int* startXnblocknonz
2575  )
2576 {
2577  int b;
2578  int sdpablock;
2579  int sdpaind;
2580  int i;
2581  int c;
2582  int r;
2583  int blocksize;
2584 
2585  assert( sdpisolver != NULL );
2586  assert( nblocks > 0 );
2587  assert( startXnblocknonz != NULL );
2588  CHECK_IF_SOLVED( sdpisolver );
2589 
2590  if ( ! sdpisolver->preoptimalsolexists )
2591  {
2592  SCIPdebugMessage("Failed to retrieve preoptimal solution for warmstarting purposes. \n");
2593  startXnblocknonz[0] = -1;
2594  return SCIP_OKAY;
2595  }
2596 
2597  if ( nblocks != sdpisolver->nsdpblocks + 1 )
2598  {
2599  SCIPerrorMessage("SCIPsdpiSolverGetPreoptimalPrimalNonzeros expected nblocks = %d but got %d\n", sdpisolver->nsdpblocks + 1, nblocks);
2600  return SCIP_LPERROR;
2601  }
2602 
2603  /* iterate over all SDP-blocks, get the solution and count the nonzeros */
2604  for (b = 0; b < sdpisolver->nsdpblocks; b++)
2605  {
2606  sdpablock = sdpisolver->inputtoblockmapper[b];
2607 
2608  startXnblocknonz[b] = 0;
2609 
2610  if ( sdpablock != -1 )
2611  {
2612  blocksize = sdpisolver->sdpa->getBlockSize(sdpablock);
2613 
2614  /* iterate once over the upper triangular part of the matrix (saving the corresponding entries in the lower triangular part for the SDPI) */
2615  for (r = 0; r < blocksize; r++)
2616  {
2617  for (c = r; c < blocksize; c++)
2618  {
2619  sdpaind = r + blocksize * c;
2620 
2621  if ( REALABS(sdpisolver->preoptimalsolx[sdpablock - 1][sdpaind]) > sdpisolver->epsilon )
2622  startXnblocknonz[b]++;
2623  }
2624  }
2625  }
2626  }
2627 
2628  /* compute the entry for the LP-block */
2629  startXnblocknonz[nblocks - 1] = 0;
2630  sdpablock = sdpisolver->sdpa->getBlockNumber();
2631 
2632  if ( sdpisolver->sdpa->getBlockType(sdpablock) == SDPA::LP )
2633  {
2634  blocksize = sdpisolver->sdpa->getBlockSize(sdpablock);
2635 
2636  for (i = 0; i < blocksize; i++)
2637  {
2638  if ( REALABS(sdpisolver->preoptimalsolx[sdpablock - 1][i]) > sdpisolver->epsilon )
2639  startXnblocknonz[b]++;
2640  }
2641  }
2642 
2643  return SCIP_OKAY;
2644 }
2645 
2646 
2654 SCIP_RETCODE SCIPsdpiSolverGetPreoptimalSol(
2655  SCIP_SDPISOLVER* sdpisolver,
2656  SCIP_Bool* success,
2657  SCIP_Real* dualsol,
2658  int* dualsollength,
2660  int nblocks,
2661  int* startXnblocknonz,
2663  int** startXrow,
2664  int** startXcol,
2665  SCIP_Real** startXval
2666  )
2667 {
2668  int v;
2669  int b;
2670  int r;
2671  int c;
2672  int sdpaind;
2673  int sdpablock;
2674  int blocksize;
2675  int blocknnonz;
2676  SCIP_Bool msgthrown = FALSE;
2677 
2678  assert( sdpisolver != NULL );
2679  assert( success != NULL );
2680  assert( dualsol != NULL );
2681  assert( dualsollength != NULL );
2682  assert( *dualsollength >= 0 );
2683  assert( startXnblocknonz != NULL || nblocks == -1 );
2684  assert( startXrow != NULL || nblocks == -1 );
2685  assert( startXcol != NULL || nblocks == -1 );
2686  assert( startXval != NULL || nblocks == -1 );
2687 
2688  if ( ! sdpisolver->preoptimalsolexists )
2689  {
2690  SCIPdebugMessage("Failed to retrieve preoptimal solution for warmstarting purposes. \n");
2691  *success = FALSE;
2692  return SCIP_OKAY;
2693  }
2694 
2695  if ( *dualsollength < sdpisolver->nvars )
2696  {
2697  SCIPdebugMessage("Insufficient memory in SCIPsdpiSolverGetPreoptimalSol: needed %d, given %d\n", sdpisolver->nvars, *dualsollength);
2698  *success = FALSE;
2699  *dualsollength = sdpisolver->nvars;
2700  return SCIP_OKAY;
2701  }
2702 
2703  for (v = 0; v < sdpisolver->nvars; v++)
2704  {
2705  if (sdpisolver->inputtosdpamapper[v] > 0)
2706  {
2707  /* minus one because the inputtosdpamapper gives the dsdp indices which start at one, but the array starts at 0 */
2708  dualsol[v] = sdpisolver->preoptimalsol[sdpisolver->inputtosdpamapper[v] - 1];
2709  }
2710  else
2711  {
2712  /* this is the value that was saved when inserting, as this variable has lb=ub */
2713  dualsol[v] = sdpisolver->fixedvarsval[(-1 * sdpisolver->inputtosdpamapper[v]) - 1]; /*lint !e679*/
2714  }
2715  }
2716 
2717  *dualsollength = sdpisolver->nvars;
2718 
2719  if ( nblocks > -1 )
2720  {
2721  assert( startXnblocknonz != NULL );
2722  assert( startXrow != NULL );
2723  assert( startXcol != NULL );
2724  assert( startXval != NULL );
2725 
2726  /* iterate over all SDP-blocks and get the solution */
2727  for (b = 0; b < sdpisolver->nsdpblocks; b++)
2728  {
2729  assert( startXrow[b] != NULL );
2730  assert( startXcol[b] != NULL );
2731  assert( startXval[b] != NULL );
2732 
2733  sdpablock = sdpisolver->inputtoblockmapper[b];
2734 
2735  blocknnonz = 0;
2736 
2737  if ( sdpablock != -1 )
2738  {
2739  /* since we reset the preoptimalsolution for every solve, the blocksize should have stayed the same */
2740  blocksize = sdpisolver->sdpa->getBlockSize(sdpablock);
2741  blocknnonz = 0;
2742 
2743  /* iterate once over the upper triangular part of the matrix (saving the corresponding entries in the lower triangular part for the SDPI) */
2744  for (r = 0; r < blocksize; r++)
2745  {
2746  for (c = r; c < blocksize; c++)
2747  {
2748  sdpaind = r + blocksize * c;
2749 
2750  if ( REALABS(sdpisolver->preoptimalsolx[sdpablock - 1][sdpaind]) > sdpisolver->epsilon )
2751  {
2752  if ( blocknnonz < startXnblocknonz[b] )
2753  {
2754  startXrow[b][blocknnonz] = sdpisolver->blockindmapper[b][c];
2755  startXcol[b][blocknnonz] = sdpisolver->blockindmapper[b][r];
2756  startXval[b][blocknnonz] = sdpisolver->preoptimalsolx[sdpablock - 1][sdpaind]; /* -1 because sdpa starts counting at 1 */
2757  blocknnonz++;
2758  }
2759  else
2760  {
2761  if ( ! msgthrown )
2762  {
2763  SCIPdebugMessage("Unsufficient arraylength %d for block %d in SCIPsdpiSolverGetPrimalMatrix!\n", startXnblocknonz[b], b);
2764  msgthrown = TRUE;
2765  }
2766  }
2767  }
2768  }
2769  }
2770 
2771  startXnblocknonz[b] = blocknnonz;
2772  }
2773  else
2774  startXnblocknonz[b] = 0;
2775  }
2776 
2777  /* compute entries for the LP-block */
2778  blocknnonz = 0;
2779 
2780  /* since we reset the preoptimalsolution for every solve, the number of blocks should have stayed the same */
2781  sdpablock = sdpisolver->sdpa->getBlockNumber();
2782 
2783  if ( sdpisolver->sdpa->getBlockType(sdpablock) == SDPA::LP )
2784  {
2785  int i;
2786 
2787  /* since we reset the preoptimalsolution for every solve, the blocksize should have stayed the same */
2788  blocksize = sdpisolver->sdpa->getBlockSize(sdpablock);
2789 
2790  /* iterate over LP constraints */
2791  for (i = 0; i < blocksize - sdpisolver->nvarbounds; i++)
2792  {
2793  if ( REALABS(sdpisolver->preoptimalsolx[sdpablock - 1][i]) > sdpisolver->epsilon )
2794  {
2795  if ( blocknnonz < startXnblocknonz[b] )
2796  {
2797  startXrow[b][blocknnonz] = sdpisolver->rowtoinputmapper[i];
2798  startXcol[b][blocknnonz] = sdpisolver->rowtoinputmapper[i];
2799  startXval[b][blocknnonz] = sdpisolver->preoptimalsolx[sdpablock - 1][i]; /* -1 because sdpa starts counting at 1 */
2800  blocknnonz++;
2801  }
2802  else
2803  {
2804  blocknnonz++;
2805  if ( ! msgthrown )
2806  {
2807  SCIPdebugMessage("Unsufficient arraylength %d for LP block in SCIPsdpiSolverGetPrimalMatrix!\n", startXnblocknonz[b]);
2808  msgthrown = TRUE;
2809  }
2810  }
2811  }
2812  }
2813 
2814  /* iterate over varbounds */
2815  for (i = blocksize - sdpisolver->nvarbounds; i < blocksize; i++)
2816  {
2817  if ( REALABS(sdpisolver->preoptimalsolx[sdpablock - 1][i]) > sdpisolver->epsilon )
2818  {
2819  if ( blocknnonz < startXnblocknonz[b] )
2820  {
2821  int inputpos;
2822  int vbpos;
2823 
2824  vbpos = i - (blocksize - sdpisolver->nvarbounds); /* position in varboundpos array */
2825 
2826  /* inputpos is 2 * nlprows (for lhs and rhs) + 2 * inputvar for lb and 2 * inputvar + 1 for ub */
2827  if ( sdpisolver->varboundpos[vbpos] > 0 ) /* rhs */
2828  inputpos = 2 * sdpisolver->ninputlpcons + 2 * sdpisolver->sdpatoinputmapper[sdpisolver->varboundpos[vbpos] - 1] + 1;
2829  else
2830  inputpos = 2 * sdpisolver->ninputlpcons + 2 * sdpisolver->sdpatoinputmapper[-1 * sdpisolver->varboundpos[vbpos] - 1];
2831  startXrow[b][blocknnonz] = inputpos;
2832  startXcol[b][blocknnonz] = inputpos;
2833  startXval[b][blocknnonz] = sdpisolver->preoptimalsolx[sdpablock - 1][i]; /* -1 because sdpa starts counting at 1 */
2834  blocknnonz++;
2835  }
2836  else
2837  {
2838  blocknnonz++;
2839  if ( ! msgthrown )
2840  {
2841  SCIPdebugMessage("Insufficient arraylength %d for LP block & varbounds in SCIPsdpiSolverGetPrimalMatrix!\n", startXnblocknonz[b]);
2842  msgthrown = TRUE;
2843  }
2844  }
2845  }
2846  }
2847  startXnblocknonz[b] = blocknnonz;
2848  }
2849  else
2850  startXnblocknonz[b] = 0;
2851  }
2852 
2853  *success = TRUE;
2854 
2855  return SCIP_OKAY;
2856 }
2857 
2866  SCIP_SDPISOLVER* sdpisolver,
2867  SCIP_Real* lbvars,
2868  SCIP_Real* ubvars,
2869  int* arraylength
2871  )
2872 {/*lint !e1784*/
2873  int i;
2874  SCIP_Real* X; /* block of primal solution matrix corresponding to the LP-part */
2875  int lpblockind;
2876  int nlpcons;
2877 
2878  assert( sdpisolver != NULL );
2879  assert( sdpisolver->sdpa != NULL );
2880  assert( lbvars != NULL );
2881  assert( ubvars != NULL );
2882  assert( arraylength != NULL );
2883  assert( *arraylength >= 0 );
2884  CHECK_IF_SOLVED( sdpisolver );
2885 
2886  /* check if the arrays are long enough */
2887  if ( *arraylength < sdpisolver->nvars )
2888  {
2889  *arraylength = sdpisolver->nvars;
2890  SCIPdebugMessage("Insufficient length of array in SCIPsdpiSolverGetPrimalBoundVars (gave %d, needed %d)\n", *arraylength, sdpisolver->nvars);
2891  return SCIP_OKAY;
2892  }
2893 
2894  /* initialize the return-arrays with zero */
2895  for (i = 0; i < sdpisolver->nvars; i++)
2896  {
2897  lbvars[i] = 0.0;
2898  ubvars[i] = 0.0;
2899  }
2900 
2901  /* if no variable bounds were added, we return the zero vector (we do this separately, because in this case there might be no LP-block) */
2902  if ( sdpisolver->nvarbounds == 0 )
2903  {
2904  SCIPdebugMessage("Asked for PrimalBoundVars, but there were no variable bounds in sdpa, returning zero vector !");
2905  return SCIP_OKAY;
2906  }
2907 
2908  /* get the block of primal solution matrix corresponding to the LP-part from sdpa */
2909  lpblockind = (int) sdpisolver->sdpa->getBlockNumber(); /* the LP block is the last one and sdpa counts from one */
2910  if ( ! (sdpisolver->sdpa->getBlockType((long long) lpblockind) == SDPA::LP) )/*lint !e747*/
2911  {
2912  /* if the last block is not an LP-block, no variable bounds existed */
2913  *arraylength = 0;
2914 
2915  return SCIP_OKAY;
2916  }
2917  nlpcons = (int) sdpisolver->sdpa->getBlockSize((long long) lpblockind);/*lint !e747*/
2918  assert( nlpcons >= 0 );
2919 
2920  X = sdpisolver->sdpa->getResultYMat((long long) lpblockind);/*lint !e747*/
2921 
2922  /* iterate over all variable bounds and insert the corresponding primal variables in the right positions of the return-arrays */
2923  assert( sdpisolver->nvarbounds <= 2 * sdpisolver->nvars || (sdpisolver->nvarbounds <= 2 * sdpisolver->nvars + 1 && sdpisolver->penalty ) );
2924  /* if we solved a penalty formulation, the last variable bound belongs to the penalty variable, which we aren't interested in here */
2925  for (i = 0; i < ((sdpisolver->penalty) ? sdpisolver->nvarbounds - 1 : sdpisolver->nvarbounds); i++)
2926  {
2927  if ( sdpisolver->varboundpos[i] < 0 )
2928  {
2929  /* this is a lower bound */
2930  /* the last nvarbounds entries correspond to the varbounds */
2931  lbvars[sdpisolver->sdpatoinputmapper[-1 * sdpisolver->varboundpos[i] -1]] = X[nlpcons - sdpisolver->nvarbounds + i]; /*lint !e679, !e834 */
2932  }
2933  else
2934  {
2935  /* this is an upper bound */
2936  /* the last nvarbounds entries correspond to the varbounds */
2937  ubvars[sdpisolver->sdpatoinputmapper[+1 * sdpisolver->varboundpos[i] - 1]] = X[nlpcons - sdpisolver->nvarbounds + i]; /*lint !e679, !e834 */
2938  }
2939  }
2940 
2941  return SCIP_OKAY;
2942 }
2943 
2945 SCIP_RETCODE SCIPsdpiSolverGetPrimalNonzeros(
2946  SCIP_SDPISOLVER* sdpisolver,
2947  int nblocks,
2948  int* startXnblocknonz
2949  )
2950 {
2951  SCIP_Real* X;
2952  int b;
2953  int sdpablock;
2954  int sdpaind;
2955  int i;
2956  int r;
2957  int c;
2958  int blocksize;
2959 
2960  assert( sdpisolver != NULL );
2961  assert( nblocks > 0 );
2962  assert( startXnblocknonz != NULL );
2963  CHECK_IF_SOLVED( sdpisolver );
2964 
2965  if ( nblocks != sdpisolver->nsdpblocks + 1 )
2966  {
2967  SCIPerrorMessage("SCIPsdpiSolverGetPrimalNonzeros expected nblocks = %d but got %d\n", sdpisolver->nsdpblocks + 1, nblocks);
2968  return SCIP_LPERROR;
2969  }
2970 
2971  /* iterate over all SDP-blocks, get the solution and count the nonzeros */
2972  for (b = 0; b < sdpisolver->nsdpblocks; b++)
2973  {
2974  sdpablock = sdpisolver->inputtoblockmapper[b];
2975 
2976  startXnblocknonz[b] = 0;
2977 
2978  if ( sdpablock != -1 )
2979  {
2980  X = sdpisolver->sdpa->getResultXMat(sdpablock);
2981  blocksize = sdpisolver->sdpa->getBlockSize(sdpablock);
2982 
2983  /* iterate once over the upper triangular part of the matrix (saving the corresponding entries in the lower triangular part for the SDPI) */
2984  for (r = 0; r < blocksize; r++)
2985  {
2986  for (c = r; c < blocksize; c++)
2987  {
2988  sdpaind = r + blocksize * c;
2989 
2990  if ( REALABS(X[sdpaind]) > sdpisolver->epsilon )
2991  startXnblocknonz[b]++;
2992  }
2993  }
2994  }
2995  }
2996 
2997  /* compute the entry for the LP-block */
2998  startXnblocknonz[nblocks - 1] = 0;
2999  sdpablock = sdpisolver->sdpa->getBlockNumber();
3000 
3001  if ( sdpisolver->sdpa->getBlockType(sdpablock) == SDPA::LP )
3002  {
3003  X = sdpisolver->sdpa->getResultXMat(sdpablock);
3004  blocksize = sdpisolver->sdpa->getBlockSize(sdpablock);
3005 
3006  for (i = 0; i < blocksize; i++)
3007  {
3008  if ( REALABS(X[i]) > sdpisolver->epsilon )
3009  startXnblocknonz[b]++;
3010  }
3011  }
3012 
3013  return SCIP_OKAY;
3014 }
3015 
3022 SCIP_RETCODE SCIPsdpiSolverGetPrimalMatrix(
3023  SCIP_SDPISOLVER* sdpisolver,
3024  int nblocks,
3025  int* startXnblocknonz,
3027  int** startXrow,
3028  int** startXcol,
3029  SCIP_Real** startXval
3030  )
3031 {
3032  SCIP_Real* X;
3033  int b;
3034  int r;
3035  int c;
3036  int sdpaind;
3037  int sdpablock;
3038  int blocksize;
3039  int blocknnonz;
3040  SCIP_Bool msgthrown = FALSE;
3041 
3042  assert( sdpisolver != NULL );
3043  assert( nblocks > 0 );
3044  assert( startXnblocknonz != NULL );
3045  assert( startXrow != NULL );
3046  assert( startXcol != NULL );
3047  assert( startXval != NULL );
3048  CHECK_IF_SOLVED( sdpisolver );
3049 
3050  if ( nblocks != sdpisolver->nsdpblocks + 1 )
3051  {
3052  SCIPerrorMessage("SCIPsdpiSolverGetPrimalNonzeros expected nblocks = %d but got %d\n", sdpisolver->nsdpblocks + 1, nblocks);
3053  return SCIP_LPERROR;
3054  }
3055 
3056  /* iterate over all SDP-blocks and get the solution */
3057  for (b = 0; b < sdpisolver->nsdpblocks; b++)
3058  {
3059  sdpablock = sdpisolver->inputtoblockmapper[b];
3060 
3061  blocknnonz = 0;
3062 
3063  if ( sdpablock != -1 )
3064  {
3065  X = sdpisolver->sdpa->getResultYMat(sdpablock);
3066  blocksize = sdpisolver->sdpa->getBlockSize(sdpablock);
3067  blocknnonz = 0;
3068 
3069  /* iterate once over the upper triangular part of the matrix (saving the corresponding entries in the lower triangular part for the SDPI) */
3070  for (r = 0; r < blocksize; r++)
3071  {
3072  for (c = r; c < blocksize; c++)
3073  {
3074  sdpaind = r + blocksize * c;
3075 
3076  if ( REALABS(X[sdpaind]) > sdpisolver->epsilon )
3077  {
3078  if ( blocknnonz < startXnblocknonz[b] )
3079  {
3080  startXrow[b][blocknnonz] = sdpisolver->blockindmapper[b][c];
3081  startXcol[b][blocknnonz] = sdpisolver->blockindmapper[b][r];
3082  startXval[b][blocknnonz] = X[sdpaind];
3083  blocknnonz++;
3084  }
3085  else
3086  {
3087  if ( ! msgthrown )
3088  {
3089  SCIPdebugMessage("Insufficient arraylength %d for block %d in SCIPsdpiSolverGetPrimalMatrix!\n", startXnblocknonz[b], b);
3090  msgthrown = TRUE;
3091  }
3092  }
3093  }
3094  }
3095  }
3096 
3097  startXnblocknonz[b] = blocknnonz;
3098  }
3099  else
3100  startXnblocknonz[b] = 0;
3101  }
3102 
3103  /* compute entries for the LP-block */
3104  blocknnonz = 0;
3105  sdpablock = sdpisolver->sdpa->getBlockNumber();
3106 
3107  if ( sdpisolver->sdpa->getBlockType(sdpablock) == SDPA::LP )
3108  {
3109  int i;
3110 
3111  X = sdpisolver->sdpa->getResultXMat(sdpablock);
3112  blocksize = sdpisolver->sdpa->getBlockSize(sdpablock);
3113 
3114  /* iterate over LP constraints */
3115  for (i = 0; i < blocksize - sdpisolver->nvarbounds; i++)
3116  {
3117  if ( REALABS(X[i]) > sdpisolver->epsilon )
3118  {
3119  if ( blocknnonz < startXnblocknonz[b] )
3120  {
3121  startXrow[b][blocknnonz] = sdpisolver->rowtoinputmapper[i];
3122  startXcol[b][blocknnonz] = sdpisolver->rowtoinputmapper[i];
3123  startXval[b][blocknnonz] = X[i];
3124  blocknnonz++;
3125  }
3126  else
3127  {
3128  blocknnonz++;
3129  if ( ! msgthrown )
3130  {
3131  SCIPdebugMessage("Unsufficient arraylength %d for LP block in SCIPsdpiSolverGetPrimalMatrix!\n", startXnblocknonz[b]);
3132  msgthrown = TRUE;
3133  }
3134  }
3135  }
3136  }
3137 
3138  /* iterate over varbounds */
3139  for (i = blocksize - sdpisolver->nvarbounds; i < blocksize; i++)
3140  {
3141  if ( REALABS(X[i]) > sdpisolver->epsilon )
3142  {
3143  if ( blocknnonz < startXnblocknonz[b] )
3144  {
3145  int inputpos;
3146  int vbpos;
3147 
3148  vbpos = i - (blocksize - sdpisolver->nvarbounds); /* position in varboundpos array */
3149 
3150  /* inputpos is 2 * nlprows (for lhs and rhs) + 2 * inputvar for lb and 2 * inputvar + 1 for ub */
3151  if ( sdpisolver->varboundpos[vbpos] > 0 ) /* rhs */
3152  inputpos = 2 * sdpisolver->ninputlpcons + 2 * sdpisolver->sdpatoinputmapper[sdpisolver->varboundpos[vbpos] - 1] + 1;
3153  else
3154  inputpos = 2 * sdpisolver->ninputlpcons + 2 * sdpisolver->sdpatoinputmapper[-1 * sdpisolver->varboundpos[vbpos] - 1];
3155  startXrow[b][blocknnonz] = inputpos;
3156  startXcol[b][blocknnonz] = inputpos;
3157  startXval[b][blocknnonz] = X[i];
3158  blocknnonz++;
3159  }
3160  else
3161  {
3162  blocknnonz++;
3163  if ( ! msgthrown )
3164  {
3165  SCIPdebugMessage("Unsufficient arraylength %d for LP block & varbounds in SCIPsdpiSolverGetPrimalMatrix!\n", startXnblocknonz[b]);
3166  msgthrown = TRUE;
3167  }
3168  }
3169  }
3170  }
3171  startXnblocknonz[b] = blocknnonz;
3172  }
3173  else
3174  startXnblocknonz[b] = 0;
3175 
3176  return SCIP_OKAY;
3177 }
3178 
3181  SCIP_SDPISOLVER* sdpisolver
3182  )
3183 {
3184  SCIP_Real* X;
3185  SCIP_Real maxentry;
3186  int nblocks;
3187  int blocksize;
3188  int arraylength;
3189  int b;
3190  int i;
3191 
3192  assert( sdpisolver != NULL );
3193  assert( sdpisolver->sdpa != NULL );
3194 
3195  nblocks = (int) sdpisolver->sdpa->getBlockNumber();
3196  maxentry = 0.0;
3197 
3198  /* iterate over all blocks */
3199  for (b = 0; b < nblocks; b++)
3200  {
3201  /* get the length of the X-array, if it is an LP block, the array has length n, otherwise n*(n+1)/2 */
3202  blocksize = (int) sdpisolver->sdpa->getBlockSize((long long) b + 1);
3203  arraylength = sdpisolver->sdpa->getBlockType((long long) b + 1) == SDPA::LP ? blocksize : (blocksize * (blocksize + 1) / 2);
3204 
3205  /* iterate over all entries in this block */
3206  X = sdpisolver->sdpa->getResultYMat((long long) b + 1);/*lint !e747*/
3207  for (i = 0; i < arraylength; i++)
3208  {
3209  if ( X[i] > maxentry )
3210  maxentry = X[i];
3211  }
3212  }
3213 
3214  return maxentry;
3215 }
3216 
3218 SCIP_RETCODE SCIPsdpiSolverGetIterations(
3219  SCIP_SDPISOLVER* sdpisolver,
3220  int* iterations
3221  )
3222 {/*lint !e1784*/
3223  assert( sdpisolver != NULL );
3224  assert( sdpisolver->sdpa != NULL );
3225  assert( iterations != NULL );
3226 
3227  *iterations = sdpisolver->niterations;
3228 
3229  return SCIP_OKAY;
3230 }
3231 
3233 SCIP_RETCODE SCIPsdpiSolverGetSdpCalls(
3234  SCIP_SDPISOLVER* sdpisolver,
3235  int* calls
3236  )
3237 {/*lint !e1784*/
3238  assert( sdpisolver != NULL );
3239  assert( sdpisolver->sdpa != NULL );
3240  assert( calls != NULL );
3241 
3242  *calls = sdpisolver->nsdpcalls;
3243 
3244  return SCIP_OKAY;
3245 }
3246 
3248 SCIP_RETCODE SCIPsdpiSolverSettingsUsed(
3249  SCIP_SDPISOLVER* sdpisolver,
3250  SCIP_SDPSOLVERSETTING* usedsetting
3251  )
3252 {/*lint !e1784*/
3253  assert( sdpisolver != NULL );
3254  assert( usedsetting != NULL );
3255  CHECK_IF_SOLVED(sdpisolver);
3256 
3257  *usedsetting = sdpisolver->usedsetting;
3258 
3259  return SCIP_OKAY;
3260 }
3261 
3267 /*
3268  * Numerical Methods
3269  */
3270 
3275 SCIP_Real SCIPsdpiSolverInfinity(
3276  SCIP_SDPISOLVER* sdpisolver
3277  )
3278 { /*lint --e{715}*/
3279  return 1E+20; /* default infinity from SCIP */
3280 }
3281 
3283 SCIP_Bool SCIPsdpiSolverIsInfinity(
3284  SCIP_SDPISOLVER* sdpisolver,
3285  SCIP_Real val
3286  )
3287 {/*lint !e1784*/
3288  return ( val <= -SCIPsdpiSolverInfinity(sdpisolver) || val >= SCIPsdpiSolverInfinity(sdpisolver) );
3289 }
3290 
3292 SCIP_RETCODE SCIPsdpiSolverGetRealpar(
3293  SCIP_SDPISOLVER* sdpisolver,
3294  SCIP_SDPPARAM type,
3295  SCIP_Real* dval
3296  )
3297 {
3298  assert( sdpisolver != NULL );
3299  assert( dval != NULL );
3300 
3301  switch( type )/*lint --e{788}*/
3302  {
3303  case SCIP_SDPPAR_EPSILON:
3304  *dval = sdpisolver->epsilon;
3305  break;
3306  case SCIP_SDPPAR_GAPTOL:
3307  *dval = sdpisolver->gaptol;
3308  break;
3309  case SCIP_SDPPAR_FEASTOL:
3310  *dval = sdpisolver->feastol;
3311  break;
3313  *dval = sdpisolver->sdpsolverfeastol;
3314  break;
3316  *dval = 0.0;
3317  SCIPdebugMessage("Parameter SCIP_SDPPAR_PENALTYPARAM not used by SDPA"); /* this parameter is only used by DSDP */
3318  break;
3319  case SCIP_SDPPAR_OBJLIMIT:
3320  *dval = sdpisolver->objlimit;
3321  break;
3323  *dval = sdpisolver->lambdastar;
3324  break;
3326  *dval = sdpisolver->preoptimalgap;
3327  break;
3328  default:
3329  return SCIP_PARAMETERUNKNOWN;
3330  }
3331 
3332  return SCIP_OKAY;
3333 }
3334 
3336 SCIP_RETCODE SCIPsdpiSolverSetRealpar(
3337  SCIP_SDPISOLVER* sdpisolver,
3338  SCIP_SDPPARAM type,
3339  SCIP_Real dval
3340  )
3341 {/*lint !e1784*/
3342  assert( sdpisolver != NULL );
3343 
3344  switch( type )/*lint --e{788}*/
3345  {
3346  case SCIP_SDPPAR_EPSILON:
3347  sdpisolver->epsilon = dval;
3348  SCIPdebugMessage("Setting sdpisolver epsilon to %f.\n", dval);
3349  break;
3350  case SCIP_SDPPAR_GAPTOL:
3351  sdpisolver->gaptol = dval;
3352  SCIPdebugMessage("Setting sdpisolver gaptol to %f.\n", dval);
3353  break;
3354  case SCIP_SDPPAR_FEASTOL:
3355  sdpisolver->feastol = dval;
3356  SCIPdebugMessage("Setting sdpisolver feastol to %f.\n", dval);
3357  break;
3359  sdpisolver->sdpsolverfeastol = dval;
3360  SCIPdebugMessage("Setting sdpisolver sdpsolverfeastol to %f.\n", dval);
3361  break;
3363  SCIPdebugMessage("Parameter SCIP_SDPPAR_PENALTYPARAM not used by SDPA"); /* this parameter is only used by DSDP */
3364  break;
3365  case SCIP_SDPPAR_OBJLIMIT:
3366  SCIPdebugMessage("Setting sdpisolver objlimit to %f.\n", dval);
3367  sdpisolver->objlimit = dval;
3368  break;
3370  SCIPdebugMessage("Setting sdpisolver lambdastar parameter to %f.\n", dval);
3371  sdpisolver->lambdastar = dval;
3372  break;
3374  SCIPdebugMessage("Setting sdpisolver preoptgap to %f.\n", dval);
3375  sdpisolver->preoptimalgap = dval;
3376  break;
3377  default:
3378  return SCIP_PARAMETERUNKNOWN;
3379  }
3380 
3381  return SCIP_OKAY;
3382 }
3383 
3385 SCIP_RETCODE SCIPsdpiSolverGetIntpar(
3386  SCIP_SDPISOLVER* sdpisolver,
3387  SCIP_SDPPARAM type,
3388  int* ival
3389  )
3390 {/*lint !e1784*/
3391  assert( sdpisolver != NULL );
3392 
3393  switch( type )/*lint --e{788}*/
3394  {
3395  case SCIP_SDPPAR_SDPINFO:
3396  *ival = (int) sdpisolver->sdpinfo;
3397  SCIPdebugMessage("Getting sdpisolver information output (%d).\n", *ival);
3398  break;
3399  default:
3400  return SCIP_PARAMETERUNKNOWN;
3401  }
3402 
3403  return SCIP_OKAY;
3404 }
3405 
3407 SCIP_RETCODE SCIPsdpiSolverSetIntpar(
3408  SCIP_SDPISOLVER* sdpisolver,
3409  SCIP_SDPPARAM type,
3410  int ival
3411  )
3412 {/*lint !e1784*/
3413  assert( sdpisolver != NULL );
3414 
3415  switch( type )/*lint --e{788}*/
3416  {
3417  case SCIP_SDPPAR_SDPINFO:
3418  sdpisolver->sdpinfo = (SCIP_Bool) ival;
3419  SCIPdebugMessage("Setting sdpisolver information output (%d).\n", ival);
3420  break;
3421  default:
3422  return SCIP_PARAMETERUNKNOWN;
3423  }
3424 
3425  return SCIP_OKAY;
3426 }
3427 
3429 SCIP_RETCODE SCIPsdpiSolverComputeLambdastar(
3430  SCIP_SDPISOLVER* sdpisolver,
3431  SCIP_Real maxguess
3432  )
3433 {/*lint !e1784*/
3434  SCIP_Real compval;
3435 
3436  assert( sdpisolver != NULL );
3437 
3438  /* we set the value to min{max{MIN_LAMBDASTAR, LAMBDASTAR_FACTOR * MAX_GUESS}, MAX_LAMBDASTAR}, where MAX_GUESS is the maximum of the guesses
3439  * of the SDP-Blocks, if the define LAMBDASTAR_TWOPOINTS is set, we instead choose either LAMBDASTAR_LOW or HIGH depending on LAMBASTAR_THRESHOLD */
3440 
3441 #ifdef LAMBDASTAR_TWOPOINTS
3442  if ( maxguess < LAMBDASTAR_THRESHOLD )
3443  compval = LAMBDASTAR_LOW;
3444  else
3445  compval = LAMBDASTAR_HIGH;
3446 #else
3447  compval = LAMBDASTAR_FACTOR * maxguess;
3448 #endif
3449 
3450  if ( compval < MIN_LAMBDASTAR )
3451  {
3452  sdpisolver->lambdastar = MIN_LAMBDASTAR;
3453  SCIPdebugMessage("Setting lambdastar to %f.\n", MIN_LAMBDASTAR);
3454  }
3455  else if ( compval > MAX_LAMBDASTAR )
3456  {
3457  sdpisolver->lambdastar = MAX_LAMBDASTAR;
3458  SCIPdebugMessage("Setting lambdastar to %f.\n", MAX_LAMBDASTAR);
3459  }
3460  else
3461  {
3462  sdpisolver->lambdastar = compval;
3463  SCIPdebugMessage("Setting lambdastar to %f.\n", compval);
3464  }
3465 
3466  return SCIP_OKAY;
3467 }
3468 
3471  SCIP_SDPISOLVER* sdpisolver,
3472  SCIP_Real maxcoeff,
3473  SCIP_Real* penaltyparam
3474  )
3475 {/*lint !e1784*/
3476  SCIP_Real compval;
3477 
3478  assert( sdpisolver != NULL );
3479  assert( penaltyparam != NULL );
3480 
3481  compval = PENALTYPARAM_FACTOR * maxcoeff;
3482 
3483  if ( compval < MIN_PENALTYPARAM )
3484  {
3485  SCIPdebugMessage("Setting penaltyparameter to %f.\n", MIN_PENALTYPARAM);
3486  *penaltyparam = MIN_PENALTYPARAM;
3487  }
3488  else if ( compval > MAX_PENALTYPARAM )
3489  {
3490  SCIPdebugMessage("Setting penaltyparameter to %f.\n", MAX_PENALTYPARAM);
3491  *penaltyparam = MAX_PENALTYPARAM;
3492  }
3493  else
3494  {
3495  SCIPdebugMessage("Setting penaltyparameter to %f.\n", compval);
3496  *penaltyparam = compval;
3497  }
3498  return SCIP_OKAY;
3499 }
3500 
3503  SCIP_SDPISOLVER* sdpisolver,
3504  SCIP_Real penaltyparam,
3505  SCIP_Real* maxpenaltyparam
3506  )
3507 {/*lint !e1784*/
3508  SCIP_Real compval;
3509 
3510  assert( sdpisolver != NULL );
3511  assert( maxpenaltyparam != NULL );
3512 
3513  compval = penaltyparam * MAXPENALTYPARAM_FACTOR;
3514 
3515  if ( compval < MAX_MAXPENALTYPARAM )
3516  {
3517  *maxpenaltyparam = compval;
3518  SCIPdebugMessage("Setting maximum penaltyparameter to %f.\n", compval);
3519  }
3520  else
3521  {
3522  *maxpenaltyparam = MAX_MAXPENALTYPARAM;
3523  SCIPdebugMessage("Setting penaltyparameter to %f.\n", MAX_MAXPENALTYPARAM);
3524  }
3525 
3526  return SCIP_OKAY;
3527 }
3528 
3534 /*
3535  * File Interface Methods
3536  */
3537 
3542 SCIP_RETCODE SCIPsdpiSolverReadSDP(
3543  SCIP_SDPISOLVER* sdpisolver,
3544  const char* fname
3545  )
3546 { /*lint --e{715}*/
3547  SCIPdebugMessage("Not implemented yet\n");
3548  return SCIP_LPERROR;
3549 }
3550 
3552 SCIP_RETCODE SCIPsdpiSolverWriteSDP(
3553  SCIP_SDPISOLVER* sdpisolver,
3554  const char* fname
3555  )
3556 {/*lint !e1784*/
3557  assert( fname != NULL );
3558 
3559  sdpisolver->sdpa->writeInputSparse(const_cast<char*>(fname), const_cast<char*>("%8.3f"));
3560 
3561  return SCIP_OKAY;
3562 }
3563 
const char * SCIPsdpiSolverGetSolverName(void)
#define MIN_PENALTYPARAM
#define FEASTOLCHANGE
static SCIP_RETCODE checkFeastolAndResolve(SCIP_SDPISOLVER *sdpisolver, SCIP_Real penaltyparam, 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 *feastol)
SCIP_RETCODE SCIPsdpiSolverSetRealpar(SCIP_SDPISOLVER *sdpisolver, SCIP_SDPPARAM type, SCIP_Real dval)
SCIP_RETCODE SCIPsdpiSolverFree(SCIP_SDPISOLVER **sdpisolver)
SCIP_Real SCIPsdpiSolverInfinity(SCIP_SDPISOLVER *sdpisolver)
void * SCIPsdpiSolverGetSolverPointer(SCIP_SDPISOLVER *sdpisolver)
#define LAMBDASTAR_LOW
#define LAMBDASTAR_HIGH
#define INFEASFEASTOLCHANGE
SCIP_RETCODE SCIPsdpiSolverIgnoreInstability(SCIP_SDPISOLVER *sdpisolver, SCIP_Bool *success)
enum SCIP_SDPSolverSetting SCIP_SDPSOLVERSETTING
Definition: type_sdpi.h:80
SCIP_Bool SCIPsdpiSolverIsPrimalUnbounded(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 *starty, int *startZnblocknonz, int **startZrow, int **startZcol, SCIP_Real **startZval, int *startXnblocknonz, int **startXrow, int **startXcol, SCIP_Real **startXval, SCIP_SDPSOLVERSETTING startsettings, SCIP_Real timelimit, SCIP_Bool *feasorig, SCIP_Bool *penaltybound)
#define MAX_LAMBDASTAR
SCIP_RETCODE SCIPsdpiSolverGetObjval(SCIP_SDPISOLVER *sdpisolver, SCIP_Real *objval)
#define PENALTYPARAM_FACTOR
const char * SCIPsdpiSolverGetSolverDesc(void)
SCIP_Bool SCIPsdpiSolverIsInfinity(SCIP_SDPISOLVER *sdpisolver, SCIP_Real val)
interface methods for specific SDP-solvers
SCIP_RETCODE SCIPsdpiSolverResetCounter(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverGetRealpar(SCIP_SDPISOLVER *sdpisolver, SCIP_SDPPARAM type, SCIP_Real *dval)
SCIP_Bool SCIPsdpiSolverIsObjlimExc(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverGetSol(SCIP_SDPISOLVER *sdpisolver, SCIP_Real *objval, SCIP_Real *dualsol, int *dualsollength)
#define MAXPENALTYPARAM_FACTOR
SCIP_RETCODE SCIPsdpiSolverGetPrimalMatrix(SCIP_SDPISOLVER *sdpisolver, int nblocks, int *startXnblocknonz, int **startXrow, int **startXcol, SCIP_Real **startXval)
SCIP_Bool SCIPsdpiSolverFeasibilityKnown(SCIP_SDPISOLVER *sdpisolver)
#define MAX_MAXPENALTYPARAM
SCIP_RETCODE SCIPsdpiSolverComputeLambdastar(SCIP_SDPISOLVER *sdpisolver, SCIP_Real maxguess)
SCIP_Real SCIPsdpiSolverGetDefaultSdpiSolverFeastol(void)
SCIP_Bool SCIPsdpiSolverIsPrimalFeasible(SCIP_SDPISOLVER *sdpisolver)
#define LAMBDASTAR_THRESHOLD
SCIP_Bool SCIPsdpiSolverDoesWarmstartNeedPrimal(void)
SCIP_RETCODE SCIPsdpiSolverSettingsUsed(SCIP_SDPISOLVER *sdpisolver, SCIP_SDPSOLVERSETTING *usedsetting)
SCIP_RETCODE SCIPsdpiSolverGetIntpar(SCIP_SDPISOLVER *sdpisolver, SCIP_SDPPARAM type, int *ival)
SCIP_Bool SCIPsdpiSolverWasSolved(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpSolcheckerCheck(BMS_BUFMEM *bufmem, int nvars, SCIP_Real *lb, SCIP_Real *ub, int nsdpblocks, int *sdpblocksizes, int *sdpnblockvars, int sdpconstnnonz, int *sdpconstnblocknonz, int **sdpconstrow, int **sdpconstcol, SCIP_Real **sdpconstval, int sdpnnonz, int **sdpnblockvarnonz, int **sdpvar, int ***sdprow, int ***sdpcol, SCIP_Real ***sdpval, int **indchanges, int *nremovedinds, int *blockindchanges, int nlpcons, int noldlpcons, SCIP_Real *lplhs, SCIP_Real *lprhs, int *rownactivevars, int lpnnonz, int *lprow, int *lpcol, SCIP_Real *lpval, SCIP_Real *solvector, SCIP_Real feastol, SCIP_Real epsilon, SCIP_Bool *infeasible)
Definition: sdpsolchecker.c:58
SCIP_RETCODE SCIPsdpiSolverCreate(SCIP_SDPISOLVER **sdpisolver, SCIP_MESSAGEHDLR *messagehdlr, BMS_BLKMEM *blkmem, BMS_BUFMEM *bufmem)
#define LAMBDASTAR_FACTOR
#define CHECK_IF_SOLVED_BOOL(sdpisolver)
checks a given SDP solution for feasibility
SCIP_Real SCIPsdpiSolverGetDefaultSdpiSolverGaptol(void)
static SCIP_Bool isFixed(SCIP_SDPISOLVER *sdpisolver, SCIP_Real lb, SCIP_Real ub)
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)
#define GAPTOLCHANGE
int SCIPsdpiSolverGetDefaultSdpiSolverNpenaltyIncreases(void)
#define MIN_LAMBDASTAR
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 *lprownactivevars, int lpnnonz, int *lprow, int *lpcol, SCIP_Real *lpval, SCIP_Real *starty, int *startZnblocknonz, int **startZrow, int **startZcol, SCIP_Real **startZval, int *startXnblocknonz, int **startXrow, int **startXcol, SCIP_Real **startXval, SCIP_SDPSOLVERSETTING startsettings, SCIP_Real timelimit)
SCIP_RETCODE SCIPsdpiSolverIncreaseCounter(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverGetSolFeasibility(SCIP_SDPISOLVER *sdpisolver, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
#define PENALTYBOUNDTOL
SCIP_RETCODE SCIPsdpiSolverWriteSDP(SCIP_SDPISOLVER *sdpisolver, const char *fname)
SCIP_Bool SCIPsdpiSolverIsAcceptable(SCIP_SDPISOLVER *sdpisolver)
SCIP_Bool SCIPsdpiSolverIsOptimal(SCIP_SDPISOLVER *sdpisolver)
#define CHECK_IF_SOLVED(sdpisolver)
SCIP_RETCODE SCIPsdpiSolverGetSdpCalls(SCIP_SDPISOLVER *sdpisolver, int *calls)
SCIP_RETCODE SCIPsdpiSolverComputeMaxPenaltyparam(SCIP_SDPISOLVER *sdpisolver, SCIP_Real penaltyparam, SCIP_Real *maxpenaltyparam)
SCIP_RETCODE SCIPsdpiSolverGetPrimalBoundVars(SCIP_SDPISOLVER *sdpisolver, SCIP_Real *lbvars, SCIP_Real *ubvars, int *arraylength)
SCIP_Bool SCIPsdpiSolverIsDualInfeasible(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverSetIntpar(SCIP_SDPISOLVER *sdpisolver, SCIP_SDPPARAM type, int ival)
SCIP_Bool SCIPsdpiSolverIsPrimalInfeasible(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverGetPrimalNonzeros(SCIP_SDPISOLVER *sdpisolver, int nblocks, int *startXnblocknonz)
SCIP_RETCODE SCIPsdpiSolverReadSDP(SCIP_SDPISOLVER *sdpisolver, const char *fname)
struct SCIP_SDPiSolver SCIP_SDPISOLVER
Definition: sdpisolver.h:70
SCIP_RETCODE SCIPsdpiSolverComputePenaltyparam(SCIP_SDPISOLVER *sdpisolver, SCIP_Real maxcoeff, SCIP_Real *penaltyparam)
SCIP_Bool SCIPsdpiSolverIsIterlimExc(SCIP_SDPISOLVER *sdpisolver)
int SCIPsdpiSolverGetInternalStatus(SCIP_SDPISOLVER *sdpisolver)
enum SCIP_SDPParam SCIP_SDPPARAM
Definition: type_sdpi.h:69
SCIP_Bool SCIPsdpiSolverIsDualUnbounded(SCIP_SDPISOLVER *sdpisolver)
#define INFEASMINFEASTOL
SCIP_Bool SCIPsdpiSolverIsTimelimExc(SCIP_SDPISOLVER *sdpisolver)
SCIP_Real SCIPsdpiSolverGetMaxPrimalEntry(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverGetPreoptimalPrimalNonzeros(SCIP_SDPISOLVER *sdpisolver, int nblocks, int *startXnblocknonz)
#define BMS_CALL(x)
SCIP_Bool SCIPsdpiSolverIsDualFeasible(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverGetIterations(SCIP_SDPISOLVER *sdpisolver, int *iterations)
SCIP_Bool SCIPsdpiSolverIsConverged(SCIP_SDPISOLVER *sdpisolver)
#define MAX_PENALTYPARAM