SCIP-SDP  3.0.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
sdpisolver_sdpa.cpp
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of SCIPSDP - a solving framework for mixed-integer */
4 /* semidefinite programs based on SCIP. */
5 /* */
6 /* Copyright (C) 2011-2013 Discrete Optimization, TU Darmstadt */
7 /* EDOM, FAU Erlangen-Nürnberg */
8 /* 2014-2017 Discrete Optimization, TU Darmstadt */
9 /* */
10 /* */
11 /* This program is free software; you can redistribute it and/or */
12 /* modify it under the terms of the GNU Lesser General Public License */
13 /* as published by the Free Software Foundation; either version 3 */
14 /* of the License, or (at your option) any later version. */
15 /* */
16 /* This program is distributed in the hope that it will be useful, */
17 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
18 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
19 /* GNU Lesser General Public License for more details. */
20 /* */
21 /* You should have received a copy of the GNU Lesser General Public License */
22 /* along with this program; if not, write to the Free Software */
23 /* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.*/
24 /* */
25 /* */
26 /* Based on SCIP - Solving Constraint Integer Programs */
27 /* Copyright (C) 2002-2017 Zuse Institute Berlin */
28 /* SCIP is distributed under the terms of the SCIP Academic Licence, */
29 /* see file COPYING in the SCIP distribution. */
30 /* */
31 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
32 
33 /* #define SCIP_DEBUG*/
34 /* #define SCIP_MORE_DEBUG *//* shows all added nonzero entries */
35 /* #define SCIP_DEBUG_PRINTTOFILE *//* prints each problem inserted into SDPA to the file sdpa.dat-s and the starting point to sdpa.ini-s */
36 
37 /* #define SDPA_RESETPARAMS */ /* this can be used together with an update to the SDPA source code to prevent memory leaks when using SCIP-SDP with SDPA */
38 
45 /* turn off lint warnings for whole file: */
46 /*lint --e{750,788,818}*/
47 
48 #include <assert.h>
49 
50 #include "sdpi/sdpisolver.h"
51 
52 /* turn off warnings for sdpa (doesn't seem to work) */
53 #pragma GCC diagnostic ignored "-Wstrict-prototypes"
54 #include "sdpa_call.h" /* SDPA callable library interface */
55 #pragma GCC diagnostic warning "-Wstrict-prototypes"
56 
57 #include "blockmemshell/memory.h" /* for memory allocation */
58 #include "scip/def.h" /* for SCIP_Real, _Bool, ... */
59 #include "scip/pub_misc.h" /* for sorting */
60 #include "sdpi/sdpsolchecker.h" /* to check solution with regards to feasibility tolerance */
61 
62 /* local defines */
63 #define GAPTOLCHANGE 1
64 #define FEASTOLCHANGE 1
65 #define PENALTYBOUNDTOL 1E-3
68 #define INFEASFEASTOLCHANGE 0.1
69 #define INFEASMINFEASTOL 1E-9
71 #define MIN_LAMBDASTAR 1e0
72 #define MAX_LAMBDASTAR 1e8
73 #define LAMBDASTAR_FACTOR 1e0
74 #define LAMBDASTAR_TWOPOINTS TRUE
75 #define LAMBDASTAR_THRESHOLD 1e1
76 #define LAMBDASTAR_LOW 1.5
77 #define LAMBDASTAR_HIGH 1e5
79 #define MIN_PENALTYPARAM 1e5
80 #define MAX_PENALTYPARAM 1e12
81 #define PENALTYPARAM_FACTOR 1e1
82 #define MAX_MAXPENALTYPARAM 1e15
83 #define MAXPENALTYPARAM_FACTOR 1e6
86 #define BMS_CALL(x) do \
87  { \
88  if( NULL == (x) ) \
89  { \
90  SCIPerrorMessage("No memory in function call.\n"); \
91  return SCIP_NOMEMORY; \
92  } \
93  } \
94  while( FALSE )
95 
97 #define CHECK_IF_SOLVED(sdpisolver) do \
98  { \
99  if (!(sdpisolver->solved)) \
100  { \
101  SCIPerrorMessage("Tried to access solution information for SDP %d ahead of solving!\n", sdpisolver->sdpcounter); \
102  return SCIP_LPERROR; \
103  } \
104  } \
105  while( FALSE )
106 
108 #define CHECK_IF_SOLVED_BOOL(sdpisolver) do \
109  { \
110  if (!(sdpisolver->solved)) \
111  { \
112  SCIPerrorMessage("Tried to access solution information for SDP %d ahead of solving!\n", sdpisolver->sdpcounter); \
113  return FALSE; \
114  } \
115  } \
116  while( FALSE )
117 
118 
120 struct SCIP_SDPiSolver
121 {
122  SCIP_MESSAGEHDLR* messagehdlr;
123  BMS_BLKMEM* blkmem;
124  BMS_BUFMEM* bufmem;
125  SDPA* sdpa;
126  int nvars;
127  int nactivevars;
128  int* inputtosdpamapper;
131  int* sdpatoinputmapper;
132  SCIP_Real* fixedvarsval;
133  SCIP_Real fixedvarsobjcontr;
134  int nvarbounds;
135  int* varboundpos;
137  SCIP_Bool solved;
138  SCIP_Bool timelimit;
139  int sdpcounter;
140  int niterations;
141  int nsdpcalls;
142  SCIP_Real epsilon;
143  SCIP_Real gaptol;
144  SCIP_Real feastol;
145  SCIP_Real sdpsolverfeastol;
146  SCIP_Real objlimit;
147  SCIP_Bool sdpinfo;
148  SCIP_Bool penalty;
149  SCIP_Bool rbound;
150  SCIP_SDPSOLVERSETTING usedsetting;
151  SCIP_Real lambdastar;
152 };
153 
154 
155 /*
156  * Local Functions
157  */
158 
159 #ifndef NDEBUG
160 
161 static
162 SCIP_Bool isFixed(
163  SCIP_SDPISOLVER* sdpisolver,
164  SCIP_Real lb,
165  SCIP_Real ub
166  )
167 {
168  assert( sdpisolver != NULL );
169  assert( lb < ub + sdpisolver->feastol );
170 
171  return (ub-lb <= sdpisolver->epsilon);
172 }
173 #else
174 #define isFixed(sdpisolver,lb,ub) (ub-lb <= sdpisolver->epsilon)
175 #endif
176 
179 static
180 SCIP_RETCODE checkFeastolAndResolve(
181  SCIP_SDPISOLVER* sdpisolver,
182  SCIP_Real penaltyparam,
183  int nvars,
184  SCIP_Real* lb,
185  SCIP_Real* ub,
186  int nsdpblocks,
187  int* sdpblocksizes,
188  int* sdpnblockvars,
189  int sdpconstnnonz,
190  int* sdpconstnblocknonz,
192  int** sdpconstrow,
193  int** sdpconstcol,
194  SCIP_Real** sdpconstval,
195  int sdpnnonz,
196  int** sdpnblockvarnonz,
198  int** sdpvar,
200  int*** sdprow,
201  int*** sdpcol,
202  SCIP_Real*** sdpval,
203  int** indchanges,
205  int* nremovedinds,
206  int* blockindchanges,
207  int nlpcons,
208  int noldlpcons,
209  SCIP_Real* lplhs,
210  SCIP_Real* lprhs,
211  int* rownactivevars,
212  int lpnnonz,
213  int* lprow,
214  int* lpcol,
215  SCIP_Real* lpval,
216  SCIP_Real* feastol
217  )
218 {
219 #ifdef SCIP_DEBUG
220  char phase_string[15];
221 #endif
222 
223  assert( feastol != NULL );
224 
225  while ( SCIPsdpiSolverIsAcceptable(sdpisolver) && SCIPsdpiSolverIsDualFeasible(sdpisolver) && penaltyparam < sdpisolver->epsilon && *feastol >= INFEASMINFEASTOL )
226  {
227  SCIP_Real* solvector;
228  int nvarspointer;
229  SCIP_Bool infeasible;
230 
231  /* get current solution */
232  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &solvector, nvars) );
233  nvarspointer = nvars;
234  SCIP_CALL( SCIPsdpiSolverGetSol(sdpisolver, NULL, solvector, &nvarspointer) );
235  assert( nvarspointer == nvars );
236 
237  /* check the solution for feasibility with regards to our tolerance */
238  SCIP_CALL( SCIPsdpSolcheckerCheck(sdpisolver->bufmem, nvars, lb, ub, nsdpblocks, sdpblocksizes, sdpnblockvars, sdpconstnnonz,
239  sdpconstnblocknonz, sdpconstrow, sdpconstcol, sdpconstval, sdpnnonz, sdpnblockvarnonz, sdpvar, sdprow, sdpcol, sdpval,
240  indchanges, nremovedinds, blockindchanges, nlpcons, noldlpcons, lplhs, lprhs, rownactivevars, lpnnonz, lprow, lpcol, lpval,
241  solvector, sdpisolver->feastol, sdpisolver->epsilon, &infeasible) );
242 
243  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &solvector);
244 
245  if ( infeasible )
246  {
247  SCIPdebugMessage("Solution feasible for SDPA but outside feasibility tolerance, changing SDPA feasibility tolerance from %f to %f\n",
248  *feastol, *feastol * INFEASFEASTOLCHANGE);
249  *feastol *= INFEASFEASTOLCHANGE;
250 
251  if ( *feastol >= INFEASMINFEASTOL )
252  {
253  /* update settings */
254  sdpisolver->sdpa->setParameterEpsilonDash(*feastol);
255 
256 #ifdef SCIP_MORE_DEBUG
257  sdpisolver->sdpa->printParameters(stdout);
258 #endif
259  sdpisolver->sdpa->setInitPoint(false);
260 #ifdef SDPA_RESETPARAMS
261  sdpisolver->sdpa->resetParameters();
262 #else
263  sdpisolver->sdpa->initializeSolve();
264 #endif
265  sdpisolver->sdpa->solve();
266 
267  /* update number of SDP-iterations and -calls */
268  sdpisolver->niterations += (int) sdpisolver->sdpa->getIteration();
269  sdpisolver->nsdpcalls += 1;
270 
271 #ifdef SCIP_DEBUG
272  /* print the phase value , i.e. whether solving was successfull */
273  sdpisolver->sdpa->getPhaseString((char*)phase_string);
274  SCIPdebugMessage("SDPA solving finished with status %s (primal and dual here are switched in contrast to our formulation)\n", phase_string);
275 #endif
276  }
277  else
278  {
279  sdpisolver->solved = FALSE;
280  SCIPmessagePrintInfo(sdpisolver->messagehdlr, "SDPA failed to reach required feasibility tolerance! \n");
281  }
282  }
283  else
284  break;
285  }
286  return SCIP_OKAY;
287 }
288 
289 /*
290  * Miscellaneous Methods
291  */
292 
298 const char* SCIPsdpiSolverGetSolverName(
299  void
300  )
301 {/*lint !e1784*/
302  return "SDPA"; /* version number can only be printed to file/stdout */
303 }
304 
306 const char* SCIPsdpiSolverGetSolverDesc(
307  void
308  )
309 {/*lint !e1784*/
310  return "Primal-dual Interior Point Solver for SDPs developed by K. Fujisawa et al. (sdpa.sourceforge.net)";
311 }
312 
320  SCIP_SDPISOLVER* sdpisolver
321  )
322 {/*lint !e1784*/
323  assert( sdpisolver != NULL );
324  return (void*) sdpisolver->sdpa;
325 }
326 
329  void
330  )
331 {
332  return 1E-6;
333 }
334 
337  void
338  )
339 {
340  return 2;
341 }
342 
346 /*
347  * SDPI Creation and Destruction Methods
348  */
349 
354 SCIP_RETCODE SCIPsdpiSolverCreate(
355  SCIP_SDPISOLVER** sdpisolver,
356  SCIP_MESSAGEHDLR* messagehdlr,
357  BMS_BLKMEM* blkmem,
358  BMS_BUFMEM* bufmem
359  )
360 {/*lint !e1784*/
361  assert( sdpisolver != NULL );
362  assert( blkmem != NULL );
363  assert( bufmem != NULL );
364 
365  SCIPdebugMessage("Calling SCIPsdpiCreate \n");
366 
367  BMS_CALL( BMSallocBlockMemory(blkmem, sdpisolver) );
368 
369  (*sdpisolver)->messagehdlr = messagehdlr;
370  (*sdpisolver)->blkmem = blkmem;
371  (*sdpisolver)->bufmem = bufmem;
372 
373  /* this will be properly initialized then calling solve */
374  (*sdpisolver)->sdpa = NULL;
375 
376  (*sdpisolver)->nvars = 0;
377  (*sdpisolver)->nactivevars = 0;
378  (*sdpisolver)->inputtosdpamapper = NULL;
379  (*sdpisolver)->sdpatoinputmapper = NULL;
380  (*sdpisolver)->fixedvarsval = NULL;
381  (*sdpisolver)->fixedvarsobjcontr = 0.0;
382  (*sdpisolver)->nvarbounds = 0;
383  (*sdpisolver)->varboundpos = NULL;
384  (*sdpisolver)->solved = FALSE;
385  (*sdpisolver)->timelimit = FALSE;
386  (*sdpisolver)->sdpcounter = 0;
387  (*sdpisolver)->niterations = 0;
388  (*sdpisolver)->nsdpcalls = 0;
389 
390  (*sdpisolver)->epsilon = 1e-9;
391  (*sdpisolver)->gaptol = 1e-4;
392  (*sdpisolver)->feastol = 1e-6;
393  (*sdpisolver)->sdpsolverfeastol = 1e-6;
394  (*sdpisolver)->objlimit = SCIPsdpiSolverInfinity(*sdpisolver);
395  (*sdpisolver)->sdpinfo = FALSE;
396  (*sdpisolver)->usedsetting = SCIP_SDPSOLVERSETTING_UNSOLVED;
397 
398  return SCIP_OKAY;
399 }
400 
402 SCIP_RETCODE SCIPsdpiSolverFree(
403  SCIP_SDPISOLVER** sdpisolver
404  )
405 {/*lint !e1784*/
406  assert( sdpisolver != NULL );
407  assert( *sdpisolver != NULL );
408 
409  SCIPdebugMessage("Freeing SDPISolver\n");
410 
411  /* free SDPA object using destructor and free memory via blockmemshell */
412  if ( (*sdpisolver)->sdpa != NULL)
413  delete (*sdpisolver)->sdpa;
414 
415  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->varboundpos, 2 * (*sdpisolver)->nactivevars); /*lint !e647*/
416 
417  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->inputtosdpamapper, (*sdpisolver)->nvars);/*lint !e737*/
418 
419  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->sdpatoinputmapper, (*sdpisolver)->nactivevars);/*lint !e737*/
420 
421  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->fixedvarsval, (*sdpisolver)->nvars - (*sdpisolver)->nactivevars); /*lint !e776*/
422 
423  BMSfreeBlockMemory((*sdpisolver)->blkmem, sdpisolver);
424 
425  return SCIP_OKAY;
426 }
427 
429 SCIP_RETCODE SCIPsdpiSolverIncreaseCounter(
430  SCIP_SDPISOLVER* sdpisolver
431  )
432 {/*lint !e1784*/
433  assert( sdpisolver != NULL );
434 
435  sdpisolver->sdpcounter++;
436 
437  return SCIP_OKAY;
438 }
439 
441 SCIP_RETCODE SCIPsdpiSolverResetCounter(
442  SCIP_SDPISOLVER* sdpisolver
443  )
444 {/*lint !e1784*/
445  assert( sdpisolver != NULL );
446 
447  SCIPdebugMessage("Resetting counter of SDP-Interface from %d to 0.\n", sdpisolver->sdpcounter);
448  sdpisolver->sdpcounter = 0;
449 
450  return SCIP_OKAY;
451 }
452 
456 /*
457  * Solving Methods
458  */
459 
475 SCIP_RETCODE SCIPsdpiSolverLoadAndSolve(
476  SCIP_SDPISOLVER* sdpisolver,
477  int nvars,
478  SCIP_Real* obj,
479  SCIP_Real* lb,
480  SCIP_Real* ub,
481  int nsdpblocks,
482  int* sdpblocksizes,
483  int* sdpnblockvars,
484  int sdpconstnnonz,
485  int* sdpconstnblocknonz,
487  int** sdpconstrow,
488  int** sdpconstcol,
489  SCIP_Real** sdpconstval,
490  int sdpnnonz,
491  int** sdpnblockvarnonz,
493  int** sdpvar,
495  int*** sdprow,
496  int*** sdpcol,
497  SCIP_Real*** sdpval,
498  int** indchanges,
500  int* nremovedinds,
501  int* blockindchanges,
502  int nremovedblocks,
503  int nlpcons,
504  int noldlpcons,
505  SCIP_Real* lplhs,
506  SCIP_Real* lprhs,
507  int* lprownactivevars,
508  int lpnnonz,
509  int* lprow,
510  int* lpcol,
511  SCIP_Real* lpval,
512  SCIP_Real* start,
513  SCIP_SDPSOLVERSETTING startsettings,
515  SCIP_Real timelimit
516  )
517 {/*lint !e1784*/
518  return SCIPsdpiSolverLoadAndSolveWithPenalty(sdpisolver, 0.0, TRUE, FALSE, nvars, obj, lb, ub, nsdpblocks, sdpblocksizes, sdpnblockvars, sdpconstnnonz,
519  sdpconstnblocknonz, sdpconstrow, sdpconstcol, sdpconstval, sdpnnonz, sdpnblockvarnonz, sdpvar, sdprow, sdpcol, sdpval, indchanges,
520  nremovedinds, blockindchanges, nremovedblocks, nlpcons, noldlpcons, lplhs, lprhs, lprownactivevars, lpnnonz, lprow, lpcol, lpval, start,
521  startsettings, timelimit, NULL, NULL);
522 }
523 
544  SCIP_SDPISOLVER* sdpisolver,
545  SCIP_Real penaltyparam,
546  SCIP_Bool withobj,
547  SCIP_Bool rbound,
548  int nvars,
549  SCIP_Real* obj,
550  SCIP_Real* lb,
551  SCIP_Real* ub,
552  int nsdpblocks,
553  int* sdpblocksizes,
554  int* sdpnblockvars,
555  int sdpconstnnonz,
556  int* sdpconstnblocknonz,
558  int** sdpconstrow,
559  int** sdpconstcol,
560  SCIP_Real** sdpconstval,
561  int sdpnnonz,
562  int** sdpnblockvarnonz,
564  int** sdpvar,
566  int*** sdprow,
567  int*** sdpcol,
568  SCIP_Real*** sdpval,
569  int** indchanges,
571  int* nremovedinds,
572  int* blockindchanges,
573  int nremovedblocks,
574  int nlpcons,
575  int noldlpcons,
576  SCIP_Real* lplhs,
577  SCIP_Real* lprhs,
578  int* rownactivevars,
579  int lpnnonz,
580  int* lprow,
581  int* lpcol,
582  SCIP_Real* lpval,
583  SCIP_Real* start,
584  SCIP_SDPSOLVERSETTING startsettings,
586  SCIP_Real timelimit,
587  SCIP_Bool* feasorig,
589  SCIP_Bool* penaltybound
591  )
592 {/*lint !e1784*/
593  SCIP_Real feastol;
594  SCIP_Real* sdpavarbounds;
595  int i;
596  int k;
597  int block;
598  int nfixedvars;
599  bool checkinput; /* should the input be checked for consistency in SDPA ? */
600  int lpconsind;
601  int lastrow;
602  int* rowmapper; /* maps the lhs- and rhs-inequalities of the old LP-cons to their constraint numbers in DSDP */
603  int nlpineqs;
604  int pos;
605  int newpos;
606  int oldnactivevars;
607 #ifdef SCIP_MORE_DEBUG
608  int ind;
609 #endif
610 
611 #ifdef SCIP_DEBUG
612  char phase_string[15];
613 #endif
614 
615  assert( sdpisolver != NULL );
616  assert( penaltyparam > -1 * sdpisolver->epsilon );
617  assert( penaltyparam < sdpisolver->epsilon || ( feasorig != NULL ) );
618  assert( nvars > 0 );
619  assert( obj != NULL );
620  assert( lb != NULL );
621  assert( ub != NULL );
622  assert( nsdpblocks >= 0 );
623  assert( nsdpblocks == 0 || sdpblocksizes != NULL );
624  assert( nsdpblocks == 0 || sdpnblockvars != NULL );
625  assert( sdpconstnnonz >= 0 );
626  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstnblocknonz != NULL );
627  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstrow != NULL );
628  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstcol != NULL );
629  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstval != NULL );
630  assert( sdpnnonz >= 0 );
631  assert( nsdpblocks == 0 || sdpnblockvarnonz != NULL );
632  assert( nsdpblocks == 0 || sdpvar != NULL );
633  assert( nsdpblocks == 0 || sdprow != NULL );
634  assert( nsdpblocks == 0 || sdpcol != NULL );
635  assert( nsdpblocks == 0 || sdpval != NULL );
636  assert( nsdpblocks == 0 || indchanges != NULL );
637  assert( nsdpblocks == 0 || nremovedinds != NULL );
638  assert( nsdpblocks == 0 || blockindchanges != NULL );
639  assert( 0 <= nremovedblocks && nremovedblocks <= nsdpblocks );
640  assert( nlpcons >= 0 );
641  assert( noldlpcons >= nlpcons );
642  assert( nlpcons == 0 || lplhs != NULL );
643  assert( nlpcons == 0 || lprhs != NULL );
644  assert( nlpcons == 0 || rownactivevars != NULL );
645  assert( lpnnonz >= 0 );
646  assert( nlpcons == 0 || lprow != NULL );
647  assert( nlpcons == 0 || lpcol != NULL );
648  assert( nlpcons == 0 || lpval != NULL );
649 
650  sdpisolver->niterations = 0;
651  sdpisolver->nsdpcalls = 0;
652 
653  /* immediately exit if the time limit is negative */
654  if ( timelimit <= 0.0 )
655  {
656  sdpisolver->solved = FALSE;
657  sdpisolver->timelimit = TRUE;
658  return SCIP_OKAY;
659  }
660  else
661  sdpisolver->timelimit = FALSE;
662 
663 #ifndef SCIP_NDEBUG
664  checkinput = false;
665 #else
666  checkinput = true;
667 #endif
668 
669  sdpisolver->usedsetting = SCIP_SDPSOLVERSETTING_UNSOLVED;
670 
671  /* 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
672  * same SDP) */
673  if ( penaltyparam < sdpisolver->epsilon )
674  SCIPdebugMessage("Inserting Data into SDPA for SDP (%d) \n", ++sdpisolver->sdpcounter);
675  else
676  SCIPdebugMessage("Inserting Data again into SDPA for SDP (%d) \n", sdpisolver->sdpcounter);
677 
678  /* set the penalty and rbound flags accordingly */
679  sdpisolver->penalty = (penaltyparam < sdpisolver->epsilon) ? FALSE : TRUE;
680  sdpisolver->rbound = rbound;
681 
682  /* allocate memory for inputtosdpamapper, sdpatoinputmapper and the fixed variable information, for the latter this will
683  * later be shrinked if the needed size is known */
684  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->inputtosdpamapper), sdpisolver->nvars, nvars) );
685  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->sdpatoinputmapper), sdpisolver->nactivevars, nvars) );
686  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->fixedvarsval), sdpisolver->nvars - sdpisolver->nactivevars, nvars) ); /*lint !e776*/
687 
688  oldnactivevars = sdpisolver->nactivevars; /* we need to save this to realloc the varboundpos-array if needed */
689  sdpisolver->nvars = nvars;
690  sdpisolver->nactivevars = 0;
691  nfixedvars = 0;
692 
693  /* find the fixed variables */
694  sdpisolver->fixedvarsobjcontr = 0.0;
695  for (i = 0; i < nvars; i++)
696  {
697  if ( isFixed(sdpisolver, lb[i], ub[i]) )
698  {
699  sdpisolver->fixedvarsobjcontr += obj[i] * lb[i]; /* this is the value this fixed variable contributes to the objective */
700  sdpisolver->fixedvarsval[nfixedvars] = lb[i]; /* if lb=ub, than this is the value the variable will have in every solution */
701  nfixedvars++;
702  sdpisolver->inputtosdpamapper[i] = -nfixedvars;
703  SCIPdebugMessage("Fixing variable %d locally to %f for SDP %d in SDPA\n", i, lb[i], sdpisolver->sdpcounter);
704  }
705  else
706  {
707  sdpisolver->sdpatoinputmapper[sdpisolver->nactivevars] = i;
708  sdpisolver->nactivevars++;
709  sdpisolver->inputtosdpamapper[i] = sdpisolver->nactivevars; /* sdpa starts counting at 1, so we do this after increasing nactivevars */
710 #ifdef SCIP_MORE_DEBUG
711  SCIPdebugMessage("Variable %d becomes variable %d for SDP %d in SDPA\n", i, sdpisolver->inputtosdpamapper[i], sdpisolver->sdpcounter);
712 #endif
713  }
714  }
715  assert( sdpisolver->nactivevars + nfixedvars == sdpisolver->nvars );
716 
717  /* if we want to solve without objective, we reset fixedvarsobjcontr */
718  if ( ! withobj )
719  sdpisolver->fixedvarsobjcontr = 0.0;
720 
721  /* shrink the fixedvars and sdpatoinputmapper arrays to the right size */
722  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->fixedvarsval), nvars, nfixedvars) );
723  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->sdpatoinputmapper), nvars, sdpisolver->nactivevars) );
724 
725  /* insert data */
726  if ( sdpisolver->sdpa != 0 )
727  {
728  /* if the SDPA solver has already been created, clear the current problem instance */
729  delete sdpisolver->sdpa;
730  sdpisolver->sdpa = new SDPA();
731  }
732  else
733  sdpisolver->sdpa = new SDPA();
734  assert( sdpisolver->sdpa != 0 );
735 
736  /* initialize settings (this needs to be done before inserting the problem as the initial point depends on the settings) */
737  if ( penaltyparam >= sdpisolver->epsilon || startsettings == SCIP_SDPSOLVERSETTING_STABLE || startsettings == SCIP_SDPSOLVERSETTING_PENALTY )
738  {
739  sdpisolver->sdpa->setParameterType(SDPA::PARAMETER_STABLE_BUT_SLOW); /* if we already had problems with this problem, there is no reason to try fast */
740  /* 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 */
741  sdpisolver->sdpa->setParameterEpsilonStar(GAPTOLCHANGE * GAPTOLCHANGE * sdpisolver->gaptol);
742  sdpisolver->sdpa->setParameterEpsilonDash(FEASTOLCHANGE * FEASTOLCHANGE * sdpisolver->sdpsolverfeastol);
743  feastol = FEASTOLCHANGE * FEASTOLCHANGE * sdpisolver->sdpsolverfeastol;
744  SCIPdebugMessage("Start solving process with stable settings\n");
745  }
746  else if ( startsettings == SCIP_SDPSOLVERSETTING_UNSOLVED || startsettings == SCIP_SDPSOLVERSETTING_FAST)
747  {
748  sdpisolver->sdpa->setParameterType(SDPA::PARAMETER_UNSTABLE_BUT_FAST);
749  sdpisolver->sdpa->setParameterEpsilonStar(sdpisolver->gaptol);
750  sdpisolver->sdpa->setParameterEpsilonDash(sdpisolver->sdpsolverfeastol);
751  feastol = sdpisolver->sdpsolverfeastol;
752  SCIPdebugMessage("Start solving process with fast settings\n");
753  }
754  else if ( startsettings == SCIP_SDPSOLVERSETTING_MEDIUM )
755  {
756  sdpisolver->sdpa->setParameterType(SDPA::PARAMETER_DEFAULT);
757  /* 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 */
758  sdpisolver->sdpa->setParameterEpsilonStar(GAPTOLCHANGE * sdpisolver->gaptol);
759  sdpisolver->sdpa->setParameterEpsilonDash(FEASTOLCHANGE * sdpisolver->sdpsolverfeastol);
760  feastol = FEASTOLCHANGE * sdpisolver->sdpsolverfeastol;
761  SCIPdebugMessage("Start solving process with medium settings\n");
762  }
763  else
764  {
765  SCIPdebugMessage("Unknown setting for start-settings: %d!\n", startsettings); \
766  return SCIP_LPERROR;
767  }
768  sdpisolver->sdpa->setParameterLowerBound(-1e20);
769 
770 
771  /* set the objective limit */
772  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, sdpisolver->objlimit) )
773  sdpisolver->sdpa->setParameterUpperBound(sdpisolver->objlimit);
774  else
775  sdpisolver->sdpa->setParameterUpperBound(1e8);
776 
777  /* increase Lambda Star, this seems to help the numerics */
778  sdpisolver->sdpa->setParameterLambdaStar(sdpisolver->lambdastar);
779 
780 #ifdef SCIP_MORE_DEBUG
781  sdpisolver->sdpa->printParameters(stdout);
782 #endif
783 
784  /* compute number of variable bounds and save them in sdpavarbounds */
785  sdpisolver->nvarbounds = 0;
786  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &sdpavarbounds, 2 * sdpisolver->nactivevars) ); /*lint !e647*//*lint !e530*/
787 
788  if ( sdpisolver->nactivevars != oldnactivevars )
789  {
790  if ( sdpisolver->varboundpos == NULL )
791  {
792  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->varboundpos), 2 * sdpisolver->nactivevars) ); /*lint !e647*/
793  }
794  else
795  {
796  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->varboundpos), 2 * oldnactivevars, 2 * sdpisolver->nactivevars) ); /*lint !e647*/
797  }
798  }
799  assert( sdpisolver->varboundpos != NULL );
800 
801  for (i = 0; i < sdpisolver->nactivevars; i++)
802  {
803  assert( 0 <= sdpisolver->sdpatoinputmapper[i] && sdpisolver->sdpatoinputmapper[i] < nvars );
804  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, lb[sdpisolver->sdpatoinputmapper[i]]))
805  {
806  sdpavarbounds[sdpisolver->nvarbounds] = lb[sdpisolver->sdpatoinputmapper[i]];
807  sdpisolver->varboundpos[sdpisolver->nvarbounds] = -(i + 1); /* negative sign means lower bound, i + 1 because sdpa starts counting from one */
808  (sdpisolver->nvarbounds)++;
809  }
810  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, ub[sdpisolver->sdpatoinputmapper[i]]) )
811  {
812  sdpavarbounds[sdpisolver->nvarbounds] = ub[sdpisolver->sdpatoinputmapper[i]];
813  sdpisolver->varboundpos[sdpisolver->nvarbounds] = +(i + 1); /* positive sign means upper bound, i + 1 because sdpa starts counting from one */
814  (sdpisolver->nvarbounds)++;
815  }
816  }
817 
818  if ( nlpcons > 0 )
819  {
820  /* 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 */
821  BMS_CALL( BMSallocBufferMemoryArray(sdpisolver->bufmem, &rowmapper, 2*noldlpcons) ); /*lint !e647*//*lint !e530*/
822 
823  /* compute the number of LP constraints after splitting the ranged rows and compute the rowmapper */
824  pos = 1; /* SDPA starts counting the LP-inequalities at one */
825  newpos = 0; /* the position in the lhs and rhs arrays */
826  for (i = 0; i < noldlpcons; i++)
827  {
828  if ( rownactivevars[i] >= 2 )
829  {
830  if ( lplhs[newpos] > - SCIPsdpiSolverInfinity(sdpisolver) )
831  {
832  rowmapper[2*i] = pos; /*lint !e679*/
833  pos++;
834  }
835  else
836  rowmapper[2*i] = -1; /*lint !e679*/
837  if ( lprhs[newpos] < SCIPsdpiSolverInfinity(sdpisolver) )
838  {
839  rowmapper[2*i + 1] = pos; /*lint !e679*/
840  pos++;
841  }
842  else
843  rowmapper[2*i + 1] = -1; /*lint !e679*/
844 
845  newpos++;
846  }
847  else
848  {
849  rowmapper[2*i] = -1; /*lint !e679*/
850  rowmapper[2*i + 1] = -1; /*lint !e679*/
851  }
852  }
853  nlpineqs = pos - 1; /* minus one because we started at one as SDPA wants them numbered one to nlpineqs */
854  assert( nlpineqs <= 2*nlpcons ); /* *2 comes from left- and right-hand-sides */
855  }
856  else
857  nlpineqs = 0;
858 
859  /* if we use a penalty formulation, we need the constraint r >= 0 */
860  if ( penaltyparam >= sdpisolver->epsilon && rbound )
861  sdpisolver->nvarbounds++;
862 
863  if ( sdpisolver->sdpinfo )
864  sdpisolver->sdpa->setDisplay(stdout);
865  else
866  sdpisolver->sdpa->setDisplay(0);
867 
868 #ifdef SCIP_MORE_DEBUG
869  FILE* fpOut = fopen("output.tmp", "w");
870  if ( ! fpOut )
871  exit(-1);
872  sdpisolver->sdpa->setResultFile(fpOut);
873 #endif
874 
875  /* initialize blockstruct */
876  if ( penaltyparam < sdpisolver->epsilon ) /* we initialize this with an exact 0.0 in Solve without penalty */
877  sdpisolver->sdpa->inputConstraintNumber((long long) sdpisolver->nactivevars);/*lint !e747*/
878  else
879  sdpisolver->sdpa->inputConstraintNumber((long long) sdpisolver->nactivevars + 1);/*lint !e747*/ /* the additional variable is r for the penalty formulation */
880 
881  /* if there are any lp-cons/variable-bounds, we get an extra block for those, lastrow - nshifts is the number of lp constraints added */
882  sdpisolver->sdpa->inputBlockNumber((long long) ((nlpineqs + sdpisolver->nvarbounds > 0) ?
883  nsdpblocks - nremovedblocks + 1 : nsdpblocks - nremovedblocks)); /*lint !e834 !e747 !e776*/
884 
885  /* block+1 because SDPA starts counting at 1 */
886  for (block = 0; block < nsdpblocks; block++)
887  {
888  if ( blockindchanges[block] >= 0 )
889  {
890  SCIPdebugMessage("adding block %d to SDPA as block %d with size %d\n",
891  block, block - blockindchanges[block] + 1, sdpblocksizes[block] - nremovedinds[block]); /*lint !e834*/
892  sdpisolver->sdpa->inputBlockSize((long long) block - blockindchanges[block] + 1,/*lint !e747, !e834*/
893  (long long) sdpblocksizes[block] - nremovedinds[block]); /*lint !e834, !e776, !e747*/
894  sdpisolver->sdpa->inputBlockType((long long) block - blockindchanges[block] + 1, SDPA::SDP); /*lint !e834, !e776, !e747*/
895  }
896  }
897  if ( nlpineqs + sdpisolver->nvarbounds > 0 )
898  {
899  /* the last block is the lp block, the size has a negative sign */
900  sdpisolver->sdpa->inputBlockSize((long long) nsdpblocks - nremovedblocks + 1, (long long) -(nlpineqs + sdpisolver->nvarbounds)); /*lint !e834, !e776, !e747*/
901  sdpisolver->sdpa->inputBlockType((long long) nsdpblocks - nremovedblocks + 1, SDPA::LP); /*lint !e834, !e776, !e747*/
902  SCIPdebugMessage("adding LP block to SDPA as block %d with size %d\n", nsdpblocks - nremovedblocks + 1,/*lint !e834*/
903  -(nlpineqs + sdpisolver->nvarbounds)); /*lint !e834*/
904  }
905 
906  sdpisolver->sdpa->initializeUpperTriangleSpace();
907 
908  /* set objective values */
909  for (i = 0; i < sdpisolver->nactivevars; i++)
910  {
911  if ( withobj )
912  {
913  /* insert objective value, SDPA counts from 1 to n instead of 0 to n-1 */
914  sdpisolver->sdpa->inputCVec((long long) i + 1, obj[sdpisolver->sdpatoinputmapper[i]]);/*lint !e747*/
915 #ifdef SCIP_MORE_DEBUG
916  SCIPdebugMessage("inserting objective %f for variable %d which became variable %d in SDPA\n", obj[sdpisolver->sdpatoinputmapper[i]],
917  sdpisolver->sdpatoinputmapper[i], i+1);
918 #endif
919  }
920  if ( penaltyparam >= sdpisolver->epsilon )
921  sdpisolver->sdpa->inputCVec((long long) sdpisolver->nactivevars + 1, penaltyparam);/*lint !e747*/ /* set the objective of the additional var to penaltyparam */
922  }
923 
924  /* if we want to use a starting point we have to tell SDPA to allocate memory for it */
925  if ( start != NULL )
926  sdpisolver->sdpa->setInitPoint(true);
927  else
928  sdpisolver->sdpa->setInitPoint(false);
929 
930  /* start inserting the non-constant SDP-Constraint-Matrices */
931  if ( sdpnnonz > 0 )
932  {
933  int v;
934  int blockvar;
935 
936  assert( nsdpblocks > 0 );
937  assert( sdpnblockvarnonz != NULL );
938  assert( sdpnblockvars != NULL );
939  assert( sdpcol != NULL );
940  assert( sdprow != NULL );
941  assert( sdpval != NULL );
942  assert( sdpvar != NULL );
943  assert( indchanges != NULL );
944  assert( nremovedinds != NULL );
945 
946  for (block = 0; block < nsdpblocks; block++)
947  {
948  /* if the block has no entries, we skip it */
949  if ( blockindchanges[block] == -1 )
950  continue;
951 #ifdef SCIP_MORE_DEBUG
952  SCIPdebugMessage(" -> building block %d, which becomes block %d in SDPA (%d)\n", block, block - blockindchanges[block] + 1,sdpisolver->sdpcounter);
953 #endif
954  /* iterate over all variables in this block */
955  for (blockvar = 0; blockvar < sdpnblockvars[block]; blockvar++)
956  {
957  v = sdpisolver->inputtosdpamapper[sdpvar[block][blockvar]];
958 
959 #ifdef SCIP_MORE_DEBUG
960  SCIPdebugMessage(" -> adding coefficient matrix for variable %d which becomes variable %d in SDPA (%d)\n",
961  sdpvar[block][blockvar], v, sdpisolver->sdpcounter);
962 #endif
963 
964  /* check if the variable is active */
965  if ( v > -1 )
966  {
967  for (k = 0; k < sdpnblockvarnonz[block][blockvar]; k++)
968  {
969  /* rows and cols with active nonzeros should not be removed */
970  assert( indchanges[block][sdprow[block][blockvar][k]] > -1 && indchanges[block][sdpcol[block][blockvar][k]] > -1 );
971 
972  assert( indchanges[block][sdprow[block][blockvar][k]] <= sdprow[block][blockvar][k]);
973  assert( indchanges[block][sdpcol[block][blockvar][k]] <= sdpcol[block][blockvar][k]);
974 
975  assert( 0 <= sdprow[block][blockvar][k] && sdprow[block][blockvar][k] < sdpblocksizes[block] );
976  assert( 0 <= sdpcol[block][blockvar][k] && sdpcol[block][blockvar][k] < sdpblocksizes[block] );
977 
978  /* rows and columns start with one in SDPA, so we have to add 1 to the indices */
979 #ifdef SCIP_MORE_DEBUG
980  SCIPdebugMessage(" -> adding nonzero %g at (%d,%d) (%d)\n",
981  sdpval[block][blockvar][k],
982  sdpcol[block][blockvar][k] - indchanges[block][sdpcol[block][blockvar][k]] + 1,
983  sdprow[block][blockvar][k] - indchanges[block][sdprow[block][blockvar][k]] + 1,
984  sdpisolver->sdpcounter);
985 #endif
986 
987  sdpisolver->sdpa->inputElement((long long) v, (long long) block - blockindchanges[block] + 1, /*lint !e834, !e747*/
988  (long long) sdpcol[block][blockvar][k] - indchanges[block][sdpcol[block][blockvar][k]] + 1, /*lint !e834, !e747*/
989  (long long) sdprow[block][blockvar][k] - indchanges[block][sdprow[block][blockvar][k]] + 1, /*lint !e834, !e747*/
990  sdpval[block][blockvar][k], checkinput); /*lint !e776 !e834*/
991  }
992  }
993  }
994  /* insert the identity matrix if we are using a penalty formulation */
995  if ( penaltyparam >= sdpisolver->epsilon )
996  {
997 #ifdef SCIP_MORE_DEBUG
998  SCIPdebugMessage(" -> adding coefficient matrix for penalty variable r in SDPA (%d)\n", sdpisolver->sdpcounter);
999 #endif
1000  for (i = 0; i < sdpblocksizes[block] - nremovedinds[block]; i++)
1001  {
1002 #ifdef SCIP_MORE_DEBUG
1003  SCIPdebugMessage(" -> adding nonzero 1.0 at (%d,%d) (%d)\n", i + 1, i + 1, sdpisolver->sdpcounter);
1004 #endif
1005 
1006  sdpisolver->sdpa->inputElement((long long) sdpisolver->nactivevars + 1, (long long) block - blockindchanges[block] + 1, /*lint !e747, !e776, !e834*/
1007  (long long) i + 1, (long long) i + 1, 1.0, checkinput);/*lint !e747*/
1008  }
1009  }
1010  }
1011  }
1012 
1013  /* start inserting the constant matrix */
1014  if ( sdpconstnnonz > 0 )
1015  {
1016  assert( nsdpblocks > 0 );
1017  assert( sdpconstnblocknonz!= NULL );
1018  assert( sdpconstcol != NULL );
1019  assert( sdpconstrow != NULL );
1020  assert( sdpconstval != NULL );
1021 
1022  for (block = 0; block < nsdpblocks; block++)
1023  {
1024  if ( blockindchanges[block] == -1 )
1025  continue;
1026 #ifdef SCIP_MORE_DEBUG
1027  SCIPdebugMessage(" -> building block %d (%d)\n", block + 1, sdpisolver->sdpcounter);
1028 #endif
1029  for (k = 0; k < sdpconstnblocknonz[block]; k++)
1030  {
1031  /* rows and cols with active nonzeros should not be removed */
1032  assert( indchanges[block][sdpconstrow[block][k]] > -1 && indchanges[block][sdpconstcol[block][k]] > -1 );
1033 
1034  assert( indchanges[block][sdpconstrow[block][k]] <= sdpconstrow[block][k]);
1035  assert( indchanges[block][sdpconstcol[block][k]] <= sdpconstcol[block][k]);
1036 
1037  assert (0 <= sdpconstrow[block][k] && sdpconstrow[block][k] < sdpblocksizes[block]);
1038  assert (0 <= sdpconstcol[block][k] && sdpconstcol[block][k] < sdpblocksizes[block]);
1039 
1040  /* 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 */
1041 #ifdef SCIP_MORE_DEBUG
1042  SCIPdebugMessage(" -> adding constant nonzero %g at (%d,%d) (%d)\n", sdpconstval[block][k],
1043  sdpconstcol[block][k] - indchanges[block][sdpconstcol[block][k]] + 1,
1044  sdpconstrow[block][k] - indchanges[block][sdpconstrow[block][k]] + 1,
1045  sdpisolver->sdpcounter);
1046 #endif
1047  sdpisolver->sdpa->inputElement((long long) 0, (long long) block - blockindchanges[block] + 1, /*lint !e747, !e776, !e834*/
1048  (long long) sdpconstcol[block][k] - indchanges[block][sdpconstcol[block][k]] + 1, /*lint !e747, !e776, !e834*/
1049  (long long) sdpconstrow[block][k] - indchanges[block][sdpconstrow[block][k]] + 1, /*lint !e747, !e776, !e834*/
1050  sdpconstval[block][k], checkinput);
1051  }
1052  }
1053  }
1054 
1055 #ifdef SCIP_MORE_DEBUG
1056  SCIPdebugMessage(" -> building LP-block %d (%d)\n", nsdpblocks - nremovedblocks + 1, sdpisolver->sdpcounter);
1057 #endif
1058  /* inserting LP nonzeros */
1059  lastrow = -1;
1060  for (i = 0; i < lpnnonz; i++)
1061  {
1062  assert( 0 <= lprow[i] && lprow[i] < noldlpcons );
1063  assert( 0 <= lpcol[i] && lpcol[i] < nvars );
1064  assert( REALABS(lpval[i]) > sdpisolver->epsilon );
1065 
1066  /* if the variable is active and the constraint is more than a bound, we add it */
1067  if ( sdpisolver->inputtosdpamapper[lpcol[i]] > 0 )
1068  {
1069  /* as this is an active variable, there should be at least one in the constraint */
1070  assert( rownactivevars[lprow[i]] > 0 );
1071  if ( rownactivevars[lprow[i]] > 1 )
1072  {
1073  if ( lprow[i] > lastrow ) /* we update the lpcons-counter */
1074  {
1075  lastrow = lprow[i];
1076  /* if we use a penalty formulation, add the r * Identity entry */
1077  if ( penaltyparam >= sdpisolver->epsilon )
1078  {
1079  /* check for the lhs-inequality */
1080  if ( rowmapper[2*lastrow] > -1 ) /*lint !e679*/
1081  {
1082 #ifdef SCIP_MORE_DEBUG
1083  SCIPdebugMessage(" -> adding nonzero 1.0 at (%d,%d) for penalty variable r in SDPA (%d)\n",
1084  rowmapper[2*lastrow], rowmapper[2*lastrow], sdpisolver->sdpcounter);
1085 #endif
1086  /* LP nonzeros are added as diagonal entries of the last block (coming after the last SDP-block, with
1087  * blocks starting at 1, as are rows), the r-variable is variable nactivevars + 1 */
1088  sdpisolver->sdpa->inputElement((long long) sdpisolver->nactivevars + 1, (long long) nsdpblocks - nremovedblocks + 1, /*lint !e747, !e776, !e834*/
1089  (long long) rowmapper[2*lastrow], (long long) rowmapper[2*lastrow], 1.0, checkinput); /*lint !e679, !e747, !e834*/
1090  }
1091 
1092  /* check for the rhs-inequality */
1093  if ( rowmapper[2*lastrow + 1] > -1 ) /*lint !e679*/
1094  {
1095 #ifdef SCIP_MORE_DEBUG
1096  SCIPdebugMessage(" -> adding nonzero 1.0 at (%d,%d) for penalty variable r in SDPA (%d)\n",
1097  rowmapper[2*lastrow + 1], rowmapper[2*lastrow + 1], sdpisolver->sdpcounter);
1098 #endif
1099  /* LP nonzeros are added as diagonal entries of the last block (coming after the last SDP-block, with
1100  * blocks starting at 1, as are rows), the r-variable is variable nactivevars + 1 */
1101  sdpisolver->sdpa->inputElement((long long) sdpisolver->nactivevars + 1, (long long) nsdpblocks - nremovedblocks + 1, /*lint !e747, !e776, !e834*/
1102  (long long) rowmapper[2*lastrow + 1], (long long) rowmapper[2*lastrow + 1], 1.0, checkinput); /*lint !e679, !e747, !e834*/
1103  }
1104  }
1105  }
1106  /* add the lp-nonzero to the lhs-inequality if it exists: */
1107  if ( rowmapper[2*lastrow] > -1 ) /*lint !e679*/
1108  {
1109 #ifdef SCIP_MORE_DEBUG
1110  SCIPdebugMessage(" -> adding nonzero %g at (%d,%d) for variable %d which became variable %d in SDPA (%d)\n",
1111  lpval[i], rowmapper[2*lastrow], rowmapper[2*lastrow], lpcol[i], sdpisolver->inputtosdpamapper[lpcol[i]], sdpisolver->sdpcounter);
1112 #endif
1113  /* 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) */
1114  sdpisolver->sdpa->inputElement((long long) sdpisolver->inputtosdpamapper[lpcol[i]], (long long) nsdpblocks - nremovedblocks + 1, /*lint !e747, !e776, !e834*/
1115  (long long) rowmapper[2*lastrow], (long long) rowmapper[2*lastrow], lpval[i], checkinput); /*lint !e679, !e747, !e834*/
1116  }
1117  /* add the lp-nonzero to the rhs-inequality if it exists: */
1118  if ( rowmapper[2*lastrow + 1] > -1 ) /*lint !e679*/
1119  {
1120 #ifdef SCIP_MORE_DEBUG
1121  SCIPdebugMessage(" -> adding nonzero %g at (%d,%d) for variable %d which became variable %d in SDPA (%d)\n",
1122  -1 * lpval[i], rowmapper[2*lastrow + 1], rowmapper[2*lastrow + 1], lpcol[i], sdpisolver->inputtosdpamapper[lpcol[i]], sdpisolver->sdpcounter);
1123 #endif
1124  /* 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),
1125  * the -1 comes from the fact that this is a <=-constraint, while SDPA works with >= */
1126  sdpisolver->sdpa->inputElement((long long) sdpisolver->inputtosdpamapper[lpcol[i]], (long long) nsdpblocks - nremovedblocks + 1, /*lint !e747, !e776, !e834*/
1127  (long long) rowmapper[2*lastrow + 1], (long long) rowmapper[2*lastrow + 1], -1 * lpval[i], checkinput); /*lint !e679, !e747, !e834*/
1128  }
1129  }
1130  }
1131  }
1132 
1133  /* inserting LP left- and right-hand-sides for active constraints */
1134  lpconsind = 1; /* this is the same order we used when computing the rowmapper, so we insert at the right positions */
1135  for (i = 0; i < nlpcons; i++)
1136  {
1137  /* check for left-hand side */
1138  if ( lplhs[i] > - SCIPsdpiSolverInfinity(sdpisolver) )
1139  {
1140 #ifdef SCIP_MORE_DEBUG
1141  SCIPdebugMessage(" -> adding lhs %g at (%d,%d) (%d)\n", lplhs[i], lpconsind, lpconsind, sdpisolver->sdpcounter);
1142 #endif
1143  /* LP constraints are added as diagonal entries of the last block, left-hand-side is added as variable zero */
1144  sdpisolver->sdpa->inputElement((long long) 0, (long long) nsdpblocks - nremovedblocks + 1, (long long) lpconsind, /*lint !e747, !e776, !e834*/
1145  (long long) lpconsind, lplhs[i], checkinput);/*lint !e747*/
1146  lpconsind++;
1147  }
1148 
1149  /* check for right-hand side */
1150  if ( lprhs[i] < SCIPsdpiSolverInfinity(sdpisolver) )
1151  {
1152 #ifdef SCIP_MORE_DEBUG
1153  SCIPdebugMessage(" -> adding lhs (originally rhs) %g at (%d,%d) (%d)\n", -1 * lprhs[i], lpconsind, lpconsind, sdpisolver->sdpcounter);
1154 #endif
1155  /* LP constraints are added as diagonal entries of the last block, right-hand side is added as variable zero, the -1 comes from
1156  * the fact, that SDPA uses >=, while the rhs is a <=-constraint */
1157  sdpisolver->sdpa->inputElement((long long) 0, (long long) nsdpblocks - nremovedblocks + 1, (long long) lpconsind, /*lint !e747, !e776, !e834*/
1158  (long long) lpconsind, -1 * lprhs[i], checkinput);/*lint !e747*/
1159  lpconsind++;
1160  }
1161  }
1162 
1163  assert( lpconsind == nlpineqs + 1 ); /* plus one because we started at one as SDPA wants them numbered one to nlpineqs */
1164 
1165  /* print each LP-constraint as one formatted constraint in addition to the single entries inserted into SDPA */
1166 #ifdef SCIP_MORE_DEBUG
1167  lastrow = -1;
1168  ind = -1; /* this is increased once before the first usage */
1169  for (i = 0; i < lpnnonz; i++)
1170  {
1171  /* if the variable is active and the constraint is more than a bound, we added it */
1172  if ( sdpisolver->inputtosdpamapper[lpcol[i]] > 0 )
1173  {
1174  if ( rownactivevars[lprow[i]] > 1 )
1175  {
1176  if ( lprow[i] > lastrow ) /* we finished the old row */
1177  {
1178  if ( lastrow >= 0 )
1179  {
1180  if ( lprhs[ind] < SCIPsdpiSolverInfinity(sdpisolver) )
1181  SCIPmessagePrintInfo(sdpisolver->messagehdlr, " <= %f\n", lprhs[ind]);
1182  else
1183  SCIPmessagePrintInfo(sdpisolver->messagehdlr, "\n");
1184  }
1185  lastrow = lprow[i];
1186  ind++;
1187  if ( lplhs[ind] > - SCIPsdpiSolverInfinity(sdpisolver) )
1188  SCIPmessagePrintInfo(sdpisolver->messagehdlr, "%f <= ", lplhs[ind]);
1189  }
1190  SCIPmessagePrintInfo(sdpisolver->messagehdlr, "+ %f <x%d> ", lpval[i], lpcol[i]);
1191  }
1192  }
1193  }
1194  if ( lastrow >= 0 )
1195  {
1196  if ( lprhs[ind] < SCIPsdpiSolverInfinity(sdpisolver) )
1197  SCIPmessagePrintInfo(sdpisolver->messagehdlr, " <= %f\n", lprhs[ind]);
1198  else
1199  SCIPmessagePrintInfo(sdpisolver->messagehdlr, "\n");
1200  }
1201  assert( ind == nlpcons - 1 ); /* -1 because we start indexing at zero and do not increase after the last row */
1202 #endif
1203 
1204  /* free the memory for the rowmapper */
1205  if ( nlpcons > 0 )
1206  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &rowmapper);/*lint !e647, !e737*/
1207 
1208  /* insert variable bounds, these are also added as LP-constraints and therefore diagonal entries of the LP block
1209  * if we work with the penalty formulation, we get an extra entry for r >= 0, but this we will add afterwards */
1210  for (i = 0; i < ((penaltyparam < sdpisolver->epsilon) || (! rbound) ? sdpisolver->nvarbounds : sdpisolver->nvarbounds - 1); i++)
1211  {
1212  assert( 0 < abs(sdpisolver->varboundpos[i]) && abs(sdpisolver->varboundpos[i] <= sdpisolver->nactivevars) ); /* the indices are already those for SDPA */
1213 
1214  /* for lower bound */
1215  if ( sdpisolver->varboundpos[i] < 0 )
1216  {
1217  /* add it as an lp-constraint for this variable (- because we saved -n for the lower bound), at the position
1218  * (nactivelpcons + 1) + varbound-index, because we have >= the variable has coefficient +1 */
1219  sdpisolver->sdpa->inputElement((long long) -sdpisolver->varboundpos[i], (long long) nsdpblocks - nremovedblocks + 1, /*lint !e747, !e776, !e834*/
1220  (long long) nlpineqs + 1 + i, (long long) nlpineqs + 1 + i, 1.0, checkinput);/*lint !e747*/
1221 
1222  if ( REALABS(sdpavarbounds[i]) > sdpisolver->epsilon )
1223  {
1224  /* the bound is added as the rhs and therefore variable zero */
1225 #ifdef SCIP_MORE_DEBUG
1226  SCIPdebugMessage(" -> adding lower bound %g at (%d,%d) for variable %d which became variable %d in SDPA (%d)\n",
1227  sdpavarbounds[i], nlpineqs + 1 + i, nlpineqs + 1 + i, sdpisolver->sdpatoinputmapper[-sdpisolver->varboundpos[i] - 1],
1228  -sdpisolver->varboundpos[i], sdpisolver->sdpcounter);
1229 #endif
1230  sdpisolver->sdpa->inputElement((long long) 0, (long long) nsdpblocks - nremovedblocks + 1, (long long) nlpineqs + 1 + i, /*lint !e747, !e776, !e834*/
1231  (long long) nlpineqs + 1 + i, sdpavarbounds[i], checkinput);/*lint !e747*/
1232  }
1233  else
1234  {
1235  /* as the bound is zero, we don't need to add a right hand side */
1236 #ifdef SCIP_MORE_DEBUG
1237  SCIPdebugMessage(" -> adding lower bound 0 at (%d,%d) for variable %d which became variable %d in SDPA (%d)\n",
1238  nlpineqs + 1 + i, nlpineqs + 1 + i, sdpisolver->sdpatoinputmapper[-sdpisolver->varboundpos[i] - 1],
1239  -sdpisolver->varboundpos[i], sdpisolver->sdpcounter);
1240 #endif
1241  }
1242  }
1243  else
1244  {
1245  /* this is an upper bound */
1246 
1247  /* add it as an lp-constraint for this variable, at the position nactivelpcons + varbound-index, because we have >= but we
1248  * want <= for the upper bound, we have to multiply by -1 and therefore the variable has coefficient -1 */
1249  sdpisolver->sdpa->inputElement((long long) sdpisolver->varboundpos[i], (long long) nsdpblocks - nremovedblocks + 1, /*lint !e747, !e776, !e834*/
1250  (long long) nlpineqs + 1 + i, (long long) nlpineqs + 1 + i, -1.0, checkinput);/*lint !e747*/
1251 
1252  if ( REALABS(sdpavarbounds[i]) > sdpisolver->epsilon )
1253  {
1254  /* the bound is added as the rhs and therefore variable zero, we multiply by -1 for <= */
1255 #ifdef SCIP_MORE_DEBUG
1256  SCIPdebugMessage(" -> adding upper bound %g at (%d,%d) for variable %d which became variable %d in SDPA (%d)\n",
1257  sdpavarbounds[i], nlpineqs + 1 + i, nlpineqs + 1 + i, sdpisolver->sdpatoinputmapper[sdpisolver->varboundpos[i] - 1],
1258  sdpisolver->varboundpos[i], sdpisolver->sdpcounter);
1259 #endif
1260  sdpisolver->sdpa->inputElement((long long) 0, (long long) nsdpblocks - nremovedblocks + 1, (long long) nlpineqs + 1 + i, /*lint !e747, !e776, !e834*/
1261  (long long) nlpineqs + 1 + i, -sdpavarbounds[i], checkinput);/*lint !e747*/
1262  }
1263  else
1264  {
1265  /* as the bound is zero, we don't need to add a right hand side */
1266 #ifdef SCIP_MORE_DEBUG
1267  SCIPdebugMessage(" -> adding upper bound 0 at (%d,%d) for variable %d which became variable %d in SDPA (%d)\n",
1268  0, nlpineqs + 1 + i, nlpineqs + 1 + i, sdpisolver->sdpatoinputmapper[sdpisolver->varboundpos[i] - 1],
1269  sdpisolver->varboundpos[i]);
1270 #endif
1271  }
1272  }
1273  }
1274 
1275  if ( penaltyparam >= sdpisolver->epsilon && rbound )
1276  {
1277  /* we add the variable bound r >= 0 */
1278  sdpisolver->sdpa->inputElement((long long) sdpisolver->nactivevars + 1, (long long) nsdpblocks - nremovedblocks + 1, /*lint !e747, !e776, !e834*/
1279  (long long) nlpineqs + 1 + i, (long long) nlpineqs + 1 + i, 1.0, checkinput);/*lint !e747*/
1280 #ifdef SCIP_MORE_DEBUG
1281  SCIPdebugMessage(" -> adding lower bound r >= 0 at (%d,%d) in SDPA (%d)\n", nlpineqs + 1 + i, nlpineqs + 1 + i, sdpisolver->sdpcounter);
1282 #endif
1283  }
1284 
1285  /* free the arrays used for counting and saving variable bounds and LP-right-hand-sides */
1286  BMSfreeBufferMemoryArray(sdpisolver->bufmem, &sdpavarbounds); /*lint !e647, !e737*/
1287 
1288  /* transform the matrices to a more efficient form */
1289  sdpisolver->sdpa->initializeUpperTriangle();
1290  sdpisolver->sdpa->initializeSolve();
1291 
1292  /* set the starting solution */
1293  if ( start != NULL && penaltyparam < sdpisolver->epsilon )
1294  {
1295  SCIPdebugMessage("Starting with a previous solution is not yet tested for the interface, only x-vector is given, not y and Z");
1296  for (i = 1; i <= sdpisolver->nactivevars; i++) /* we iterate over the variables in sdpa */
1297  sdpisolver->sdpa->inputInitXVec((long long) i, start[sdpisolver->sdpatoinputmapper[i] - 1]);/*lint !e747*/
1298  }
1299  else if ( penaltyparam >= sdpisolver->epsilon )
1300  SCIPdebugMessage("Skipping insertion of starting point, as this is not yet supported for penalty formulation.\n");
1301 
1302 #ifdef SCIP_DEBUG_PRINTTOFILE
1303  /* if necessary, dump input data and initial point */
1304  sdpisolver->sdpa->writeInputSparse(const_cast<char*>("sdpa.dat-s"), const_cast<char*>("%+8.3e"));
1305  sdpisolver->sdpa->writeInitSparse(const_cast<char*>("sdpa.ini-s"), const_cast<char*>("%+8.3e"));
1306 #endif
1307 
1308  SCIPdebugMessage("Calling SDPA solve (SDP: %d)\n", sdpisolver->sdpcounter);
1309  sdpisolver->sdpa->solve();
1310  sdpisolver->solved = TRUE;
1311 
1312  /* update number of SDP-iterations and -calls */
1313  sdpisolver->niterations += (int) sdpisolver->sdpa->getIteration();
1314  sdpisolver->nsdpcalls += 1;
1315 
1316 #ifdef SCIP_DEBUG
1317  /* print the phase value , i.e. whether solving was successfull */
1318  sdpisolver->sdpa->getPhaseString((char*)phase_string);
1319  SCIPdebugMessage("SDPA solving finished with status %s (primal and dual here are switched in contrast to our formulation)\n", phase_string);
1320 #endif
1321 
1322  /* remember settings */
1323  if ( SCIPsdpiSolverIsAcceptable(sdpisolver) && penaltyparam < sdpisolver->epsilon )
1324  sdpisolver->usedsetting = SCIP_SDPSOLVERSETTING_FAST;
1325  else if ( penaltyparam >= sdpisolver->epsilon )
1326  sdpisolver->usedsetting = SCIP_SDPSOLVERSETTING_PENALTY;
1327 
1328  /* if the problem has been stably solved but did not reach the required feasibility tolerance, even though the solver
1329  * reports feasibility, resolve it with adjusted tolerance */
1330  SCIP_CALL( checkFeastolAndResolve(sdpisolver, penaltyparam, nvars, lb, ub, nsdpblocks, sdpblocksizes, sdpnblockvars, sdpconstnnonz,
1331  sdpconstnblocknonz, sdpconstrow, sdpconstcol, sdpconstval, sdpnnonz, sdpnblockvarnonz, sdpvar, sdprow, sdpcol, sdpval, indchanges,
1332  nremovedinds, blockindchanges, nlpcons, noldlpcons, lplhs, lprhs, rownactivevars, lpnnonz, lprow, lpcol, lpval, &feastol) );
1333 
1334  /* 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
1335  * again with more stable parameters */
1336  if ( ! SCIPsdpiSolverIsAcceptable(sdpisolver) && penaltyparam < sdpisolver->epsilon &&
1337  (startsettings == SCIP_SDPSOLVERSETTING_UNSOLVED || startsettings == SCIP_SDPSOLVERSETTING_FAST) )
1338  {
1339  SCIPdebugMessage("Numerical troubles -- solving SDP %d again ...\n", sdpisolver->sdpcounter);
1340 
1341  /* initialize settings */
1342  sdpisolver->sdpa->setParameterType(SDPA::PARAMETER_DEFAULT);
1343  sdpisolver->sdpa->setParameterEpsilonStar(GAPTOLCHANGE * sdpisolver->gaptol);
1344  sdpisolver->sdpa->setParameterEpsilonDash(FEASTOLCHANGE * sdpisolver->sdpsolverfeastol);
1345  sdpisolver->sdpa->setParameterLowerBound(-1e20);
1346  /* set the objective limit */
1347  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, sdpisolver->objlimit) )
1348  sdpisolver->sdpa->setParameterUpperBound(sdpisolver->objlimit);
1349  else
1350  sdpisolver->sdpa->setParameterUpperBound(1e8);
1351 
1352  /* increase Lambda Star, this seems to help the numerics */
1353  sdpisolver->sdpa->setParameterLambdaStar(sdpisolver->lambdastar);
1354 
1355 #ifdef SCIP_MORE_DEBUG
1356  sdpisolver->sdpa->printParameters(stdout);
1357 #endif
1358  sdpisolver->sdpa->setInitPoint(false);
1359 #ifdef SDPA_RESETPARAMS
1360  sdpisolver->sdpa->resetParameters();
1361 #else
1362  sdpisolver->sdpa->initializeSolve();
1363 #endif
1364  sdpisolver->sdpa->solve();
1365  sdpisolver->solved = TRUE;
1366 
1367  /* update number of SDP-iterations and -calls */
1368  sdpisolver->niterations += (int) sdpisolver->sdpa->getIteration();
1369  sdpisolver->nsdpcalls += 1;
1370 
1371  /* remember setting */
1372  if ( SCIPsdpiSolverIsAcceptable(sdpisolver) )
1373  sdpisolver->usedsetting = SCIP_SDPSOLVERSETTING_MEDIUM;
1374 
1375 #ifdef SCIP_DEBUG
1376  /* print the phase value , i.e. whether solving was successfull */
1377  sdpisolver->sdpa->getPhaseString((char*)phase_string);
1378  SCIPdebugMessage("SDPA solving finished with status %s (primal and dual here are switched in contrast to our formulation)\n", phase_string);
1379 #endif
1380 
1381  /* if the problem has been stably solved but did not reach the required feasibility tolerance, even though the solver
1382  * reports feasibility, resolve it with adjusted tolerance */
1383  SCIP_CALL( checkFeastolAndResolve(sdpisolver, penaltyparam, nvars, lb, ub, nsdpblocks, sdpblocksizes, sdpnblockvars, sdpconstnnonz,
1384  sdpconstnblocknonz, sdpconstrow, sdpconstcol, sdpconstval, sdpnnonz, sdpnblockvarnonz, sdpvar, sdprow, sdpcol, sdpval, indchanges,
1385  nremovedinds, blockindchanges, nlpcons, noldlpcons, lplhs, lprhs, rownactivevars, lpnnonz, lprow, lpcol, lpval, &feastol) );
1386  }
1387 
1388  /* if we still didn't converge, and did not yet use the stable settings, set the parameters even more conservativly */
1389  if ( (! SCIPsdpiSolverIsAcceptable(sdpisolver)) && penaltyparam < sdpisolver->epsilon &&
1390  (startsettings == SCIP_SDPSOLVERSETTING_UNSOLVED || startsettings == SCIP_SDPSOLVERSETTING_FAST || startsettings == SCIP_SDPSOLVERSETTING_MEDIUM) )
1391  {
1392  SCIPdebugMessage("Numerical troubles -- solving SDP %d again^2 ...\n", sdpisolver->sdpcounter);
1393 
1394  /* initialize settings */
1395  sdpisolver->sdpa->setParameterType(SDPA::PARAMETER_STABLE_BUT_SLOW);
1396  sdpisolver->sdpa->setParameterEpsilonStar(GAPTOLCHANGE * GAPTOLCHANGE * sdpisolver->gaptol);
1397  sdpisolver->sdpa->setParameterEpsilonDash(FEASTOLCHANGE * FEASTOLCHANGE * sdpisolver->sdpsolverfeastol);
1398  sdpisolver->sdpa->setParameterLowerBound(-1e20);
1399  /* set the objective limit */
1400  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, sdpisolver->objlimit) )
1401  sdpisolver->sdpa->setParameterUpperBound(sdpisolver->objlimit);
1402  else
1403  sdpisolver->sdpa->setParameterUpperBound(1e8);
1404 
1405  /* increase Lambda Star, this seems to help the numerics */
1406  sdpisolver->sdpa->setParameterLambdaStar(sdpisolver->lambdastar);
1407 
1408 #ifdef SCIP_MORE_DEBUG
1409 sdpisolver->sdpa->printParameters(stdout);
1410 #endif
1411  sdpisolver->sdpa->setInitPoint(false);
1412 #ifdef SDPA_RESETPARAMS
1413  sdpisolver->sdpa->resetParameters();
1414 #else
1415  sdpisolver->sdpa->initializeSolve();
1416 #endif
1417  sdpisolver->sdpa->solve();
1418  sdpisolver->solved = TRUE;
1419 
1420  /* update number of SDP-iterations and -calls */
1421  sdpisolver->niterations += (int) sdpisolver->sdpa->getIteration();
1422  sdpisolver->nsdpcalls += 1;
1423 
1424  /* remember setting */
1425  if ( SCIPsdpiSolverIsAcceptable(sdpisolver) )
1426  sdpisolver->usedsetting = SCIP_SDPSOLVERSETTING_STABLE;
1427 
1428 #ifdef SCIP_DEBUG
1429  /* print the phase value , i.e. whether solving was successfull */
1430  sdpisolver->sdpa->getPhaseString((char*)phase_string);
1431  SCIPdebugMessage("SDPA solving finished with status %s (primal and dual here are switched in constrast to our formulation)\n", phase_string);
1432 #endif
1433 
1434  /* if the problem has been stably solved but did not reach the required feasibility tolerance, even though the solver
1435  * reports feasibility, resolve it with adjusted tolerance */
1436  SCIP_CALL( checkFeastolAndResolve(sdpisolver, penaltyparam, nvars, lb, ub, nsdpblocks, sdpblocksizes, sdpnblockvars, sdpconstnnonz,
1437  sdpconstnblocknonz, sdpconstrow, sdpconstcol, sdpconstval, sdpnnonz, sdpnblockvarnonz, sdpvar, sdprow, sdpcol, sdpval, indchanges,
1438  nremovedinds, blockindchanges, nlpcons, noldlpcons, lplhs, lprhs, rownactivevars, lpnnonz, lprow, lpcol, lpval, &feastol) );
1439  }
1440 
1441 #ifdef SCIP_MORE_DEBUG
1442  (void) fclose(fpOut);
1443 #endif
1444 
1445  /* if we solved a penalty formulation, check if the solution is feasible for the original problem (which is the case iff r < feastol) */
1446  if ( penaltyparam >= sdpisolver->epsilon )
1447  {
1448  SCIP_Real* sdpasol;
1449  SCIP_Real* X;
1450  int b;
1451  int nblockssdpa;
1452  int nrow;
1453  SCIP_Real trace = 0.0;
1454 
1455  /* in the second case we have r as an additional variable */
1456  assert( (sdpisolver->nactivevars + 1 == sdpisolver->sdpa->getConstraintNumber()) ); /*lint !e776*/
1457 
1458  sdpasol = sdpisolver->sdpa->getResultXVec();
1459 
1460  /* we get r as the last variable in SDPA */
1461  *feasorig = (sdpasol[sdpisolver->nactivevars] < sdpisolver->feastol); /*lint !e413*/
1462 
1463  /* if r > 0 or we are in debug mode, also check the primal bound */
1464 #ifdef NDEBUG
1465  if ( ! *feasorig && penaltybound != NULL )
1466  {
1467 #endif
1468 
1469  SCIPdebugMessage("Solution not feasible in original problem, r = %f\n", sdpasol[sdpisolver->nactivevars]);
1470 
1471  /* compute Tr(X) */
1472 
1473  /* iterate over all blocks (SDPA starts counting at one and includes the LP block) */
1474  nblockssdpa = (int) sdpisolver->sdpa->getBlockNumber();
1475  for (b = 1; b <= nblockssdpa; b++)
1476  {
1477  /* get the block from SDPA */
1478  X = sdpisolver->sdpa->getResultYMat((long long) b);/*lint !e747*/
1479  nrow = (int) sdpisolver->sdpa->getBlockSize((long long) b);/*lint !e747*/
1480  assert( nrow >= 0 );
1481 
1482  /* if it is the LP-block, we omit the variable bounds as the penalty variable is not added to them */
1483  if ( sdpisolver->sdpa->getBlockType((long long) b) == SDPA::LP )/*lint !e747*/
1484  {
1485  /* iterate over all diagonal entries (until we reach the varbound part), adding them to the trace */
1486  for (i = 0; i < nrow - sdpisolver->nvarbounds; i++)
1487  trace += X[i]; /* get entry (i+1,i+1) for the diagonal matrix X */
1488  }
1489  else
1490  {
1491  /* iterate over all diagonal entries and add them to the trace */
1492  for (i = 0; i < nrow; i++)
1493  trace += X[i + i*nrow];/*lint !e679*/ /* get entry (i+1,i+1) in X */
1494  }
1495  }
1496 
1497  /* if the relative gap is smaller than the tolerance, we return equality */
1498  if ( (penaltyparam - trace) / penaltyparam < PENALTYBOUNDTOL )/*lint !e414*/
1499  {
1500  if ( penaltybound != NULL )
1501  *penaltybound = TRUE;
1502  SCIPdebugMessage("Tr(X) = %f == %f = Gamma, penalty formulation not exact, Gamma should be increased or problem is infeasible\n",
1503  trace, penaltyparam);
1504  }
1505  else if ( penaltybound != NULL )
1506  *penaltybound = FALSE;
1507 
1508 #ifdef NDEBUG
1509  }
1510 #endif
1511  }
1512  return SCIP_OKAY;
1513 }
1514 
1520 /*
1521  * Solution Information Methods
1522  */
1523 
1528 SCIP_Bool SCIPsdpiSolverWasSolved(
1529  SCIP_SDPISOLVER* sdpisolver
1530  )
1531 {/*lint !e1784*/
1532  assert( sdpisolver != NULL );
1533  return sdpisolver->solved;
1534 }
1535 
1543  SCIP_SDPISOLVER* sdpisolver
1544  )
1545 {/*lint !e1784*/
1546  SDPA::PhaseType phasetype;
1547 
1548  assert( sdpisolver != NULL );
1549  assert( sdpisolver->sdpa != NULL);
1550  CHECK_IF_SOLVED_BOOL( sdpisolver );
1551 
1552  phasetype = sdpisolver->sdpa->getPhaseValue();
1553 
1554  if ( phasetype == SDPA::noINFO || phasetype == SDPA::pFEAS || phasetype == SDPA::dFEAS || phasetype == SDPA::pdINF )
1555  return FALSE;
1556 
1557  return TRUE;
1558 }
1559 
1561 SCIP_RETCODE SCIPsdpiSolverGetSolFeasibility(
1562  SCIP_SDPISOLVER* sdpisolver,
1563  SCIP_Bool* primalfeasible,
1564  SCIP_Bool* dualfeasible
1565  )
1566 {/*lint !e1784*/
1567  SDPA::PhaseType phasetype;
1568 
1569  assert( sdpisolver != NULL );
1570  assert( sdpisolver->sdpa != NULL );
1571  assert( primalfeasible != NULL );
1572  assert( dualfeasible != NULL );
1573  CHECK_IF_SOLVED( sdpisolver );
1574 
1575  phasetype = sdpisolver->sdpa->getPhaseValue();
1576 
1577  switch ( phasetype )/*lint --e{788}*/
1578  {
1579  case SDPA::pdOPT:
1580  *primalfeasible = TRUE;
1581  *dualfeasible = TRUE;
1582  break;
1583  case SDPA::pdFEAS:
1584  *primalfeasible = TRUE;
1585  *dualfeasible = TRUE;
1586  break;
1587  case SDPA::pFEAS_dINF:
1588  *primalfeasible = TRUE;
1589  *dualfeasible = FALSE;
1590  break;
1591  case SDPA::pINF_dFEAS:
1592  *primalfeasible = FALSE;
1593  *dualfeasible = TRUE;
1594  break;
1595  case SDPA::pUNBD:
1596  *primalfeasible = TRUE;
1597  *dualfeasible = FALSE;
1598  SCIPdebugMessage("SDPA stopped because dual objective became smaller than lower bound\n");
1599  break;
1600  case SDPA::dUNBD:
1601  *primalfeasible = FALSE;
1602  *dualfeasible = TRUE;
1603  SCIPdebugMessage("SDPA stopped because primal objective became bigger than upper bound\n");
1604  break;
1605  default: /* contains noInfo, pFeas, dFeas, pdInf */
1606  SCIPerrorMessage("SDPA doesn't know if primal and dual solutions are feasible\n");
1607  return SCIP_LPERROR;
1608  }
1609 
1610  return SCIP_OKAY;
1611 }
1612 
1616  SCIP_SDPISOLVER* sdpisolver
1617  )
1618 {/*lint !e1784*/
1619  SDPA::PhaseType phasetype;
1620 
1621  assert( sdpisolver != NULL );
1622  assert( sdpisolver->sdpa != NULL );
1623  CHECK_IF_SOLVED_BOOL( sdpisolver );
1624 
1625  phasetype = sdpisolver->sdpa->getPhaseValue();
1626 
1627  if ( phasetype == SDPA::noINFO || phasetype == SDPA::pFEAS || phasetype == SDPA::pdINF )
1628  {
1629  SCIPdebugMessage("SDPA doesn't know if primal problem is unbounded");
1630  return FALSE;
1631  }
1632  else if ( phasetype == SDPA::pFEAS_dINF )
1633  return TRUE;
1634  else if ( phasetype == SDPA::pUNBD )
1635  {
1636  SCIPdebugMessage("SDPA was stopped because primal objective became bigger than upper bound");
1637  return TRUE;
1638  }
1639 
1640  return FALSE;
1641 }
1642 
1646  SCIP_SDPISOLVER* sdpisolver
1647  )
1648 {/*lint !e1784*/
1649  SDPA::PhaseType phasetype;
1650 
1651  assert( sdpisolver != NULL );
1652  assert( sdpisolver->sdpa != NULL );
1653  CHECK_IF_SOLVED_BOOL( sdpisolver );
1654 
1655  phasetype = sdpisolver->sdpa->getPhaseValue();
1656 
1657  if ( phasetype == SDPA::noINFO || phasetype == SDPA::dFEAS || phasetype == SDPA::pdINF )
1658  {
1659  SCIPdebugMessage("SDPA doesn't know if primal problem is infeasible");
1660  return FALSE;
1661  }
1662  else if ( phasetype == SDPA::pINF_dFEAS )
1663  return TRUE;
1664  else if ( phasetype == SDPA::dUNBD )
1665  {
1666  SCIPdebugMessage("SDPA was stopped because dual objective became smaller than lower bound");
1667  return TRUE;
1668  }
1669 
1670  return FALSE;
1671 }
1672 
1676  SCIP_SDPISOLVER* sdpisolver
1677  )
1678 {/*lint !e1784*/
1679  SDPA::PhaseType phasetype;
1680 
1681  assert( sdpisolver != NULL );
1682  assert( sdpisolver->sdpa != NULL );
1683  CHECK_IF_SOLVED_BOOL( sdpisolver );
1684 
1685  phasetype = sdpisolver->sdpa->getPhaseValue();
1686 
1687  if ( phasetype == SDPA::noINFO || phasetype == SDPA::dFEAS || phasetype == SDPA::pdINF )
1688  {
1689  SCIPdebugMessage("SDPA doesn't know if primal problem is feasible");
1690  return FALSE;
1691  }
1692  else if ( phasetype == SDPA::pFEAS_dINF || phasetype == SDPA::pdOPT || phasetype == SDPA::pFEAS || phasetype == SDPA::pdFEAS )
1693  return TRUE;
1694  else if ( phasetype == SDPA::dUNBD )
1695  {
1696  SCIPdebugMessage("SDPA was stopped because dual objective became smaller than lower bound");
1697  return TRUE;
1698  }
1699 
1700  return FALSE;
1701 }
1702 
1706  SCIP_SDPISOLVER* sdpisolver
1707  )
1708 {/*lint !e1784*/
1709  SDPA::PhaseType phasetype;
1710 
1711  assert( sdpisolver != NULL );
1712  assert( sdpisolver->sdpa != NULL);
1713  CHECK_IF_SOLVED_BOOL( sdpisolver );
1714 
1715  phasetype = sdpisolver->sdpa->getPhaseValue();
1716 
1717  if ( phasetype == SDPA::noINFO || phasetype == SDPA::dFEAS || phasetype == SDPA::pdINF )
1718  {
1719  SCIPdebugMessage("SDPA doesn't know if dual problem is unbounded");
1720  return FALSE;
1721  }
1722  else if ( phasetype == SDPA::pINF_dFEAS )
1723  return TRUE;
1724  else if ( phasetype == SDPA::dUNBD )
1725  {
1726  SCIPdebugMessage("SDPA was stopped because dual objective became smaller than lower bound");
1727  return TRUE;
1728  }
1729 
1730  return FALSE;
1731 }
1732 
1736  SCIP_SDPISOLVER* sdpisolver
1737  )
1738 {/*lint !e1784*/
1739  SDPA::PhaseType phasetype;
1740 
1741  assert( sdpisolver != NULL );
1742  assert( sdpisolver->sdpa != NULL);
1743  CHECK_IF_SOLVED_BOOL( sdpisolver );
1744 
1745  phasetype = sdpisolver->sdpa->getPhaseValue();
1746 
1747  if ( phasetype == SDPA::noINFO || phasetype == SDPA::pFEAS || phasetype == SDPA::pdINF )
1748  {
1749  SCIPdebugMessage("SDPA doesn't know if dual problem is infeasible");
1750  return FALSE;
1751  }
1752  else if ( phasetype == SDPA::pFEAS_dINF )
1753  return TRUE;
1754  else if ( phasetype == SDPA::pUNBD )
1755  {
1756  SCIPdebugMessage("SDPA was stopped because primal objective became bigger than upper bound");
1757  return TRUE;
1758  }
1759 
1760  return FALSE;
1761 }
1762 
1766  SCIP_SDPISOLVER* sdpisolver
1767  )
1768 {/*lint !e1784*/
1769  SDPA::PhaseType phasetype;
1770 
1771  assert( sdpisolver != NULL );
1772  assert( sdpisolver->sdpa != NULL);
1773  CHECK_IF_SOLVED_BOOL( sdpisolver );
1774 
1775  phasetype = sdpisolver->sdpa->getPhaseValue();
1776 
1777  if ( phasetype == SDPA::noINFO || phasetype == SDPA::dFEAS || phasetype == SDPA::pdINF )
1778  {
1779  SCIPdebugMessage("SDPA doesn't know if primal problem is feasible");
1780  return FALSE;
1781  }
1782  else if ( phasetype == SDPA::pINF_dFEAS || phasetype == SDPA::pdOPT || phasetype == SDPA::dFEAS || phasetype == SDPA::pdFEAS )
1783  return TRUE;
1784  else if ( phasetype == SDPA::dUNBD )
1785  {
1786  SCIPdebugMessage("SDPA was stopped because dual objective became smaller than lower bound");
1787  return TRUE;
1788  }
1789 
1790  return FALSE;
1791 }
1792 
1794 SCIP_Bool SCIPsdpiSolverIsConverged(
1795  SCIP_SDPISOLVER* sdpisolver
1796  )
1797 {/*lint !e1784*/
1798  SDPA::PhaseType phasetype;
1799 
1800  assert( sdpisolver != NULL );
1801  assert( sdpisolver->sdpa != NULL );
1802  CHECK_IF_SOLVED_BOOL( sdpisolver );
1803 
1804  phasetype = sdpisolver->sdpa->getPhaseValue();
1805 
1806  if ( phasetype == SDPA::pdOPT )
1807  return TRUE;
1808 
1809  return FALSE;
1810 }
1811 
1813 SCIP_Bool SCIPsdpiSolverIsObjlimExc(
1814  SCIP_SDPISOLVER* sdpisolver
1815  )
1816 {/*lint !e1784*/
1817  SDPA::PhaseType phasetype;
1818 
1819  assert( sdpisolver != NULL );
1820  assert( sdpisolver->sdpa != NULL );
1821  CHECK_IF_SOLVED_BOOL( sdpisolver );
1822 
1823  phasetype = sdpisolver->sdpa->getPhaseValue();
1824 
1825  if ( phasetype == SDPA::pUNBD )
1826  return TRUE;
1827 
1828  return FALSE;
1829 }
1830 
1832 SCIP_Bool SCIPsdpiSolverIsIterlimExc(
1833  SCIP_SDPISOLVER* sdpisolver
1834  )
1835 {/*lint !e1784*/
1836  SDPA::PhaseType phasetype;
1837 
1838  assert( sdpisolver != NULL );
1839  assert( sdpisolver->sdpa != NULL);
1840  CHECK_IF_SOLVED_BOOL( sdpisolver );
1841 
1842  phasetype = sdpisolver->sdpa->getPhaseValue();
1843 
1844  if ( phasetype == SDPA::noINFO || phasetype == SDPA::pFEAS || phasetype == SDPA::dFEAS || phasetype == SDPA::pdFEAS )
1845  {
1846  if ( sdpisolver->sdpa->getParameterMaxIteration() == sdpisolver->sdpa->getIteration() )
1847  return TRUE;
1848  }
1849 
1850  return FALSE;
1851 }
1852 
1854 SCIP_Bool SCIPsdpiSolverIsTimelimExc(
1855  SCIP_SDPISOLVER* sdpisolver
1856  )
1857 {/*lint !e1784*/
1858  assert( sdpisolver != NULL );
1859 
1860  return sdpisolver->timelimit;
1861 }
1862 
1874  SCIP_SDPISOLVER* sdpisolver
1875  )
1876 {/*lint !e1784*/
1877  SDPA::PhaseType phasetype;
1878 
1879  assert( sdpisolver != NULL );
1880  assert( sdpisolver->sdpa != NULL );
1881 
1882  if ( sdpisolver->sdpa == NULL || (! sdpisolver->solved) )
1883  return -1;
1884 
1885  phasetype = sdpisolver->sdpa->getPhaseValue();
1886 
1887  if ( phasetype == SDPA::pdOPT || phasetype == SDPA::pFEAS_dINF || phasetype == SDPA::pINF_dFEAS )
1888  return 0;
1889  if ( phasetype == SDPA::pdINF )
1890  return 1;
1891  if ( phasetype == SDPA::pUNBD)
1892  return 3;
1893  if ( phasetype == SDPA::noINFO || phasetype == SDPA::pFEAS || phasetype == SDPA::dFEAS || phasetype == SDPA::pdFEAS )
1894  return 4;
1895  else /* should include dUNBD */
1896  return 7;
1897 }
1898 
1900 SCIP_Bool SCIPsdpiSolverIsOptimal(
1901  SCIP_SDPISOLVER* sdpisolver
1902  )
1903 {/*lint !e1784*/
1904  SDPA::PhaseType phasetype;
1905 
1906  assert( sdpisolver != NULL );
1907  assert( sdpisolver->sdpa != NULL );
1908 
1909  if ( ! sdpisolver->solved )
1910  return FALSE;
1911 
1912  phasetype = sdpisolver->sdpa->getPhaseValue();
1913 
1914  if ( phasetype == SDPA::pdOPT )
1915  return TRUE;
1916 
1917  return FALSE;
1918 }
1919 
1922 SCIP_Bool SCIPsdpiSolverIsAcceptable(
1923  SCIP_SDPISOLVER* sdpisolver
1924  )
1925 {/*lint !e1784*/
1926  SDPA::PhaseType phasetype;
1927 
1928  assert( sdpisolver != NULL );
1929  assert( sdpisolver->sdpa != NULL );
1930 
1931  if ( sdpisolver->timelimit )
1932  return FALSE;
1933 
1934  if ( ! sdpisolver->solved )
1935  return FALSE;
1936 
1937  phasetype = sdpisolver->sdpa->getPhaseValue();
1938 
1939  /* we are happy if we converged, or we reached the objective limit (pUNBD) or we could show that our problem is
1940  * infeasible [except for numerics], or unbounded */
1941  if ( SCIPsdpiSolverIsConverged(sdpisolver) || phasetype == SDPA::pUNBD || phasetype == SDPA::pINF_dFEAS || phasetype == SDPA::pFEAS_dINF )
1942  return TRUE;
1943 
1944  return FALSE;
1945 }
1946 
1948 SCIP_RETCODE SCIPsdpiSolverIgnoreInstability(
1949  SCIP_SDPISOLVER* sdpisolver,
1950  SCIP_Bool* success
1951  )
1952 {/*lint !e1784*/
1953  SCIPdebugMessage("Not implemented yet\n");
1954 
1955  return SCIP_LPERROR;
1956 }/*lint !e715*/
1957 
1959 SCIP_RETCODE SCIPsdpiSolverGetObjval(
1960  SCIP_SDPISOLVER* sdpisolver,
1961  SCIP_Real* objval
1962  )
1963 {/*lint !e1784*/
1964  assert( sdpisolver != NULL );
1965  assert( sdpisolver->sdpa != NULL );
1966  assert( objval != NULL );
1967  CHECK_IF_SOLVED( sdpisolver );
1968 
1969  *objval = sdpisolver->sdpa->getPrimalObj();
1970 
1971 #ifndef NDEBUG
1972  SCIP_Real primalval = sdpisolver->sdpa->getDualObj();
1973  SCIP_Real gap = (REALABS(*objval - primalval) / (0.5 * (REALABS(primalval) + REALABS(*objval)))); /* duality gap used in SDPA */
1974  if ( gap > sdpisolver->gaptol )
1975  SCIPdebugMessage("Attention: got objective value (before adding values of fixed variables) of %f in SCIPsdpiSolverGetObjval, "
1976  "but primal objective is %f with duality gap %f!\n", *objval, primalval, gap );
1977 #endif
1978 
1979  /* as we didn't add the fixed (lb = ub) variables to sdpa, we have to add their contributions to the objective by hand */
1980  *objval += sdpisolver->fixedvarsobjcontr;
1981 
1982  return SCIP_OKAY;
1983 }
1984 
1989 SCIP_RETCODE SCIPsdpiSolverGetSol(
1990  SCIP_SDPISOLVER* sdpisolver,
1991  SCIP_Real* objval,
1992  SCIP_Real* dualsol,
1993  int* dualsollength
1995  )
1996 {/*lint !e1784*/
1997  SCIP_Real* sdpasol;
1998  int v;
1999 
2000  assert( sdpisolver != NULL );
2001  assert( sdpisolver->sdpa != NULL );
2002  assert( dualsollength != NULL );
2003  CHECK_IF_SOLVED( sdpisolver );
2004 
2005  if ( objval != NULL )
2006  {
2007  *objval = sdpisolver->sdpa->getPrimalObj();
2008 
2009 #ifndef NDEBUG
2010  SCIP_Real primalval = sdpisolver->sdpa->getDualObj();
2011  SCIP_Real gap = (REALABS(*objval - primalval) / (0.5 * (REALABS(primalval) + REALABS(*objval)))); /* duality gap used in SDPA */
2012  if ( gap > sdpisolver->gaptol )
2013  {
2014  SCIPdebugMessage("Attention: got objective value (before adding values of fixed variables) of %f in SCIPsdpiSolverGetSol, "
2015  "but primal objective is %f with duality gap %f!\n", *objval, primalval, gap );
2016  }
2017 #endif
2018 
2019  /* as we didn't add the fixed (lb = ub) variables to sdpa, we have to add their contributions to the objective by hand */
2020  *objval += sdpisolver->fixedvarsobjcontr;
2021  }
2022 
2023  if ( *dualsollength > 0 )
2024  {
2025  assert( dualsol != NULL );
2026  if ( *dualsollength < sdpisolver->nvars )
2027  {
2028  SCIPdebugMessage("The given array in SCIPsdpiSolverGetSol only had length %d, but %d was needed", *dualsollength, sdpisolver->nvars);
2029  *dualsollength = sdpisolver->nvars;
2030 
2031  return SCIP_OKAY;
2032  }
2033 
2034  /* get the solution from sdpa */
2035  assert( (sdpisolver->penalty && sdpisolver->nactivevars + 1 == sdpisolver->sdpa->getConstraintNumber()) || /*lint !e776*/
2036  sdpisolver->nactivevars == sdpisolver->sdpa->getConstraintNumber() ); /* in the second case we have r as an additional variable */
2037  sdpasol = sdpisolver->sdpa->getResultXVec();
2038  /* 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) */
2039  for (v = 0; v < sdpisolver->nvars; v++)
2040  {
2041  if ( sdpisolver->inputtosdpamapper[v] > 0 )
2042  {
2043  /* minus one because the inputtosdpamapper gives the sdpa indices which start at one, but the array starts at 0 */
2044  dualsol[v] = sdpasol[sdpisolver->inputtosdpamapper[v] - 1];
2045  }
2046  else
2047  {
2048  /* this is the value that was saved when inserting, as this variable has lb=ub */
2049  assert( -sdpisolver->inputtosdpamapper[v] <= sdpisolver->nvars - sdpisolver->nactivevars );
2050  dualsol[v] = sdpisolver->fixedvarsval[(-1 * sdpisolver->inputtosdpamapper[v]) - 1]; /*lint !e679*/
2051  }
2052  }
2053  }
2054  return SCIP_OKAY;
2055 }
2056 
2065  SCIP_SDPISOLVER* sdpisolver,
2066  SCIP_Real* lbvars,
2067  SCIP_Real* ubvars,
2068  int* arraylength
2070  )
2071 {/*lint !e1784*/
2072  int i;
2073  SCIP_Real* X; /* block of primal solution matrix corresponding to the LP-part */
2074  int lpblockind;
2075  int nlpcons;
2076 
2077  assert( sdpisolver != NULL );
2078  assert( sdpisolver->sdpa != NULL );
2079  assert( lbvars != NULL );
2080  assert( ubvars != NULL );
2081  assert( arraylength != NULL );
2082  assert( *arraylength >= 0 );
2083  CHECK_IF_SOLVED( sdpisolver );
2084 
2085  /* check if the arrays are long enough */
2086  if ( *arraylength < sdpisolver->nvars )
2087  {
2088  *arraylength = sdpisolver->nvars;
2089  SCIPdebugMessage("Insufficient length of array in SCIPsdpiSolverGetPrimalBoundVars (gave %d, needed %d)\n", *arraylength, sdpisolver->nvars);
2090  return SCIP_OKAY;
2091  }
2092 
2093  /* initialize the return-arrays with zero */
2094  for (i = 0; i < sdpisolver->nvars; i++)
2095  {
2096  lbvars[i] = 0.0;
2097  ubvars[i] = 0.0;
2098  }
2099 
2100  /* 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) */
2101  if ( sdpisolver->nvarbounds == 0 )
2102  {
2103  SCIPdebugMessage("Asked for PrimalBoundVars, but there were no variable bounds in sdpa, returning zero vector !");
2104  return SCIP_OKAY;
2105  }
2106 
2107  /* get the block of primal solution matrix corresponding to the LP-part from sdpa */
2108  lpblockind = (int) sdpisolver->sdpa->getBlockNumber(); /* the LP block is the last one and sdpa counts from one */
2109  assert( sdpisolver->sdpa->getBlockType((long long) lpblockind) == SDPA::LP );/*lint !e747*/
2110  nlpcons = (int) sdpisolver->sdpa->getBlockSize((long long) lpblockind);/*lint !e747*/
2111  assert( nlpcons >= 0 );
2112 
2113  X = sdpisolver->sdpa->getResultYMat((long long) lpblockind);/*lint !e747*/
2114 
2115  /* iterate over all variable bounds and insert the corresponding primal variables in the right positions of the return-arrays */
2116  assert( sdpisolver->nvarbounds <= 2 * sdpisolver->nvars || (sdpisolver->nvarbounds <= 2 * sdpisolver->nvars + 1 && sdpisolver->penalty ) );
2117  /* if we solved a penalty formulation, the last variable bound belongs to the penalty variable, which we aren't interested in here */
2118  for (i = 0; i < ((sdpisolver->penalty) ? sdpisolver->nvarbounds - 1 : sdpisolver->nvarbounds); i++)
2119  {
2120  if ( sdpisolver->varboundpos[i] < 0 )
2121  {
2122  /* this is a lower bound */
2123  /* the last nvarbounds entries correspond to the varbounds */
2124  lbvars[sdpisolver->sdpatoinputmapper[-1 * sdpisolver->varboundpos[i] -1]] = X[nlpcons - sdpisolver->nvarbounds + i]; /*lint !e679, !e834 */
2125  }
2126  else
2127  {
2128  /* this is an upper bound */
2129  /* the last nvarbounds entries correspond to the varbounds */
2130  ubvars[sdpisolver->sdpatoinputmapper[+1 * sdpisolver->varboundpos[i] - 1]] = X[nlpcons - sdpisolver->nvarbounds + i]; /*lint !e679, !e834 */
2131  }
2132  }
2133 
2134  return SCIP_OKAY;
2135 }
2136 
2138 SCIP_RETCODE SCIPsdpiSolverGetIterations(
2139  SCIP_SDPISOLVER* sdpisolver,
2140  int* iterations
2141  )
2142 {/*lint !e1784*/
2143  assert( sdpisolver != NULL );
2144  assert( sdpisolver->sdpa != NULL );
2145  assert( iterations != NULL );
2146 
2147  *iterations = sdpisolver->niterations;
2148 
2149  return SCIP_OKAY;
2150 }
2151 
2153 SCIP_RETCODE SCIPsdpiSolverGetSdpCalls(
2154  SCIP_SDPISOLVER* sdpisolver,
2155  int* calls
2156  )
2157 {/*lint !e1784*/
2158  assert( sdpisolver != NULL );
2159  assert( sdpisolver->sdpa != NULL );
2160  assert( calls != NULL );
2161 
2162  *calls = sdpisolver->nsdpcalls;
2163 
2164  return SCIP_OKAY;
2165 }
2166 
2168 SCIP_RETCODE SCIPsdpiSolverSettingsUsed(
2169  SCIP_SDPISOLVER* sdpisolver,
2170  SCIP_SDPSOLVERSETTING* usedsetting
2171  )
2172 {/*lint !e1784*/
2173  assert( sdpisolver != NULL );
2174  assert( usedsetting != NULL );
2175  CHECK_IF_SOLVED(sdpisolver);
2176 
2177  *usedsetting = sdpisolver->usedsetting;
2178 
2179  return SCIP_OKAY;
2180 }
2181 
2187 /*
2188  * Numerical Methods
2189  */
2190 
2195 SCIP_Real SCIPsdpiSolverInfinity(
2196  SCIP_SDPISOLVER* sdpisolver
2197  )
2198 {/*lint !e1784*/
2199  return 1E+20; /* default infinity from SCIP */
2200 }/*lint !e715*/
2201 
2203 SCIP_Bool SCIPsdpiSolverIsInfinity(
2204  SCIP_SDPISOLVER* sdpisolver,
2205  SCIP_Real val
2206  )
2207 {/*lint !e1784*/
2208  return ( val <= -SCIPsdpiSolverInfinity(sdpisolver) || val >= SCIPsdpiSolverInfinity(sdpisolver) );
2209 }
2210 
2212 SCIP_RETCODE SCIPsdpiSolverGetRealpar(
2213  SCIP_SDPISOLVER* sdpisolver,
2214  SCIP_SDPPARAM type,
2215  SCIP_Real* dval
2216  )
2217 {/*lint !e1784*/
2218  assert( sdpisolver != NULL );
2219  assert( dval != NULL );
2220 
2221  switch( type )/*lint --e{788}*/
2222  {
2223  case SCIP_SDPPAR_EPSILON:
2224  *dval = sdpisolver->epsilon;
2225  break;
2226  case SCIP_SDPPAR_GAPTOL:
2227  *dval = sdpisolver->gaptol;
2228  break;
2229  case SCIP_SDPPAR_FEASTOL:
2230  *dval = sdpisolver->feastol;
2231  break;
2233  *dval = sdpisolver->sdpsolverfeastol;
2234  break;
2236  *dval = 0.0;
2237  SCIPdebugMessage("Parameter SCIP_SDPPAR_PENALTYPARAM not used by SDPA"); /* this parameter is only used by DSDP */
2238  break;
2239  case SCIP_SDPPAR_OBJLIMIT:
2240  *dval = sdpisolver->objlimit;
2241  break;
2243  *dval = sdpisolver->lambdastar;
2244  break;
2245  default:
2246  return SCIP_PARAMETERUNKNOWN;
2247  }
2248 
2249  return SCIP_OKAY;
2250 }
2251 
2253 SCIP_RETCODE SCIPsdpiSolverSetRealpar(
2254  SCIP_SDPISOLVER* sdpisolver,
2255  SCIP_SDPPARAM type,
2256  SCIP_Real dval
2257  )
2258 {/*lint !e1784*/
2259  assert( sdpisolver != NULL );
2260 
2261  switch( type )/*lint --e{788}*/
2262  {
2263  case SCIP_SDPPAR_EPSILON:
2264  sdpisolver->epsilon = dval;
2265  SCIPdebugMessage("Setting sdpisolver epsilon to %f.\n", dval);
2266  break;
2267  case SCIP_SDPPAR_GAPTOL:
2268  sdpisolver->gaptol = dval;
2269  SCIPdebugMessage("Setting sdpisolver gaptol to %f.\n", dval);
2270  break;
2271  case SCIP_SDPPAR_FEASTOL:
2272  sdpisolver->feastol = dval;
2273  SCIPdebugMessage("Setting sdpisolver feastol to %f.\n", dval);
2274  break;
2276  sdpisolver->sdpsolverfeastol = dval;
2277  SCIPdebugMessage("Setting sdpisolver sdpsolverfeastol to %f.\n", dval);
2278  break;
2280  SCIPdebugMessage("Parameter SCIP_SDPPAR_PENALTYPARAM not used by SDPA"); /* this parameter is only used by DSDP */
2281  break;
2282  case SCIP_SDPPAR_OBJLIMIT:
2283  SCIPdebugMessage("Setting sdpisolver objlimit to %f.\n", dval);
2284  sdpisolver->objlimit = dval;
2285  break;
2287  SCIPdebugMessage("Setting sdpisolver lambdastar parameter to %f.\n", dval);
2288  sdpisolver->lambdastar = dval;
2289  break;
2290  default:
2291  return SCIP_PARAMETERUNKNOWN;
2292  }
2293 
2294  return SCIP_OKAY;
2295 }
2296 
2298 SCIP_RETCODE SCIPsdpiSolverGetIntpar(
2299  SCIP_SDPISOLVER* sdpisolver,
2300  SCIP_SDPPARAM type,
2301  int* ival
2302  )
2303 {/*lint !e1784*/
2304  assert( sdpisolver != NULL );
2305 
2306  switch( type )/*lint --e{788}*/
2307  {
2308  case SCIP_SDPPAR_SDPINFO:
2309  *ival = (int) sdpisolver->sdpinfo;
2310  SCIPdebugMessage("Getting sdpisolver information output (%d).\n", *ival);
2311  break;
2312  default:
2313  return SCIP_PARAMETERUNKNOWN;
2314  }
2315 
2316  return SCIP_OKAY;
2317 }
2318 
2320 SCIP_RETCODE SCIPsdpiSolverSetIntpar(
2321  SCIP_SDPISOLVER* sdpisolver,
2322  SCIP_SDPPARAM type,
2323  int ival
2324  )
2325 {/*lint !e1784*/
2326  assert( sdpisolver != NULL );
2327 
2328  switch( type )/*lint --e{788}*/
2329  {
2330  case SCIP_SDPPAR_SDPINFO:
2331  sdpisolver->sdpinfo = (SCIP_Bool) ival;
2332  SCIPdebugMessage("Setting sdpisolver information output (%d).\n", ival);
2333  break;
2334  default:
2335  return SCIP_PARAMETERUNKNOWN;
2336  }
2337 
2338  return SCIP_OKAY;
2339 }
2340 
2342 SCIP_RETCODE SCIPsdpiSolverComputeLambdastar(
2343  SCIP_SDPISOLVER* sdpisolver,
2344  SCIP_Real maxguess
2345  )
2346 {/*lint !e1784*/
2347  SCIP_Real compval;
2348 
2349  assert( sdpisolver != NULL );
2350 
2351  /* we set the value to min{max{MIN_LAMBDASTAR, LAMBDASTAR_FACTOR * MAX_GUESS}, MAX_LAMBDASTAR}, where MAX_GUESS is the maximum of the guesses
2352  * of the SDP-Blocks, if the define LAMBDASTAR_TWOPOINTS is set, we instead choose either LAMBDASTAR_LOW or HIGH depending on LAMBASTAR_THRESHOLD */
2353 
2354 #ifdef LAMBDASTAR_TWOPOINTS
2355  if ( maxguess < LAMBDASTAR_THRESHOLD )
2356  compval = LAMBDASTAR_LOW;
2357  else
2358  compval = LAMBDASTAR_HIGH;
2359 #else
2360  compval = LAMBDASTAR_FACTOR * maxguess;
2361 #endif
2362 
2363  if ( compval < MIN_LAMBDASTAR )
2364  {
2365  sdpisolver->lambdastar = MIN_LAMBDASTAR;
2366  SCIPdebugMessage("Setting lambdastar to %f.\n", MIN_LAMBDASTAR);
2367  }
2368  else if ( compval > MAX_LAMBDASTAR )
2369  {
2370  sdpisolver->lambdastar = MAX_LAMBDASTAR;
2371  SCIPdebugMessage("Setting lambdastar to %f.\n", MAX_LAMBDASTAR);
2372  }
2373  else
2374  {
2375  sdpisolver->lambdastar = compval;
2376  SCIPdebugMessage("Setting lambdastar to %f.\n", compval);
2377  }
2378 
2379  return SCIP_OKAY;
2380 }
2381 
2384  SCIP_SDPISOLVER* sdpisolver,
2385  SCIP_Real maxcoeff,
2386  SCIP_Real* penaltyparam
2387  )
2388 {/*lint !e1784*/
2389  SCIP_Real compval;
2390 
2391  assert( sdpisolver != NULL );
2392  assert( penaltyparam != NULL );
2393 
2394  compval = PENALTYPARAM_FACTOR * maxcoeff;
2395 
2396  if ( compval < MIN_PENALTYPARAM )
2397  {
2398  SCIPdebugMessage("Setting penaltyparameter to %f.\n", MIN_PENALTYPARAM);
2399  *penaltyparam = MIN_PENALTYPARAM;
2400  }
2401  else if ( compval > MAX_PENALTYPARAM )
2402  {
2403  SCIPdebugMessage("Setting penaltyparameter to %f.\n", MAX_PENALTYPARAM);
2404  *penaltyparam = MAX_PENALTYPARAM;
2405  }
2406  else
2407  {
2408  SCIPdebugMessage("Setting penaltyparameter to %f.\n", compval);
2409  *penaltyparam = compval;
2410  }
2411  return SCIP_OKAY;
2412 }
2413 
2416  SCIP_SDPISOLVER* sdpisolver,
2417  SCIP_Real penaltyparam,
2418  SCIP_Real* maxpenaltyparam
2419  )
2420 {/*lint !e1784*/
2421  SCIP_Real compval;
2422 
2423  assert( sdpisolver != NULL );
2424  assert( maxpenaltyparam != NULL );
2425 
2426  compval = penaltyparam * MAXPENALTYPARAM_FACTOR;
2427 
2428  if ( compval < MAX_MAXPENALTYPARAM )
2429  {
2430  *maxpenaltyparam = compval;
2431  SCIPdebugMessage("Setting maximum penaltyparameter to %f.\n", compval);
2432  }
2433  else
2434  {
2435  *maxpenaltyparam = MAX_MAXPENALTYPARAM;
2436  SCIPdebugMessage("Setting penaltyparameter to %f.\n", MAX_MAXPENALTYPARAM);
2437  }
2438 
2439  return SCIP_OKAY;
2440 }
2441 
2447 /*
2448  * File Interface Methods
2449  */
2450 
2455 SCIP_RETCODE SCIPsdpiSolverReadSDP(
2456  SCIP_SDPISOLVER* sdpisolver,
2457  const char* fname
2458  )
2459 {/*lint !e1784*/
2460  SCIPdebugMessage("Not implemented yet\n");
2461  return SCIP_LPERROR;
2462 }/*lint !e715*/
2463 
2465 SCIP_RETCODE SCIPsdpiSolverWriteSDP(
2466  SCIP_SDPISOLVER* sdpisolver,
2467  const char* fname
2468  )
2469 {/*lint !e1784*/
2470  assert( fname != NULL );
2471 
2472  sdpisolver->sdpa->writeInputSparse(const_cast<char*>(fname), const_cast<char*>("%8.3f"));
2473 
2474  return SCIP_OKAY;
2475 }
2476 
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:78
SCIP_Bool SCIPsdpiSolverIsPrimalUnbounded(SCIP_SDPISOLVER *sdpisolver)
#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_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_RETCODE SCIPsdpiSolverSettingsUsed(SCIP_SDPISOLVER *sdpisolver, SCIP_SDPSOLVERSETTING *usedsetting)
SCIP_RETCODE SCIPsdpiSolverGetIntpar(SCIP_SDPISOLVER *sdpisolver, SCIP_SDPPARAM type, int *ival)
SCIP_Bool SCIPsdpiSolverWasSolved(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpSolcheckerCheck(BMS_BUFMEM *bufmem, int nvars, SCIP_Real *lb, SCIP_Real *ub, int nsdpblocks, int *sdpblocksizes, int *sdpnblockvars, int sdpconstnnonz, int *sdpconstnblocknonz, int **sdpconstrow, int **sdpconstcol, SCIP_Real **sdpconstval, int sdpnnonz, int **sdpnblockvarnonz, int **sdpvar, int ***sdprow, int ***sdpcol, SCIP_Real ***sdpval, int **indchanges, int *nremovedinds, int *blockindchanges, int nlpcons, int noldlpcons, SCIP_Real *lplhs, SCIP_Real *lprhs, int *rownactivevars, int lpnnonz, int *lprow, int *lpcol, SCIP_Real *lpval, SCIP_Real *solvector, SCIP_Real feastol, SCIP_Real epsilon, SCIP_Bool *infeasible)
Definition: sdpsolchecker.c:57
SCIP_RETCODE SCIPsdpiSolverCreate(SCIP_SDPISOLVER **sdpisolver, SCIP_MESSAGEHDLR *messagehdlr, BMS_BLKMEM *blkmem, BMS_BUFMEM *bufmem)
#define LAMBDASTAR_FACTOR
#define CHECK_IF_SOLVED_BOOL(sdpisolver)
checks a given SDP solution for feasibility
static SCIP_Bool isFixed(SCIP_SDPISOLVER *sdpisolver, SCIP_Real lb, SCIP_Real ub)
#define GAPTOLCHANGE
int SCIPsdpiSolverGetDefaultSdpiSolverNpenaltyIncreases(void)
#define MIN_LAMBDASTAR
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 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)
SCIP_RETCODE SCIPsdpiSolverLoadAndSolveWithPenalty(SCIP_SDPISOLVER *sdpisolver, SCIP_Real penaltyparam, SCIP_Bool withobj, SCIP_Bool rbound, int nvars, SCIP_Real *obj, SCIP_Real *lb, SCIP_Real *ub, int nsdpblocks, int *sdpblocksizes, int *sdpnblockvars, int sdpconstnnonz, int *sdpconstnblocknonz, int **sdpconstrow, int **sdpconstcol, SCIP_Real **sdpconstval, int sdpnnonz, int **sdpnblockvarnonz, int **sdpvar, int ***sdprow, int ***sdpcol, SCIP_Real ***sdpval, int **indchanges, int *nremovedinds, int *blockindchanges, int nremovedblocks, int nlpcons, int noldlpcons, SCIP_Real *lplhs, SCIP_Real *lprhs, int *rownactivevars, int lpnnonz, int *lprow, int *lpcol, SCIP_Real *lpval, SCIP_Real *start, SCIP_SDPSOLVERSETTING startsettings, SCIP_Real timelimit, SCIP_Bool *feasorig, SCIP_Bool *penaltybound)
enum SCIP_SDPParam SCIP_SDPPARAM
Definition: type_sdpi.h:67
SCIP_Bool SCIPsdpiSolverIsDualUnbounded(SCIP_SDPISOLVER *sdpisolver)
#define INFEASMINFEASTOL
SCIP_Bool SCIPsdpiSolverIsTimelimExc(SCIP_SDPISOLVER *sdpisolver)
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 *start, SCIP_SDPSOLVERSETTING startsettings, SCIP_Real timelimit)
#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