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