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