SCIP-SDP  2.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 programms based on SCIP. */
5 /* */
6 /* Copyright (C) 2011-2013 Discrete Optimization, TU Darmstadt */
7 /* EDOM, FAU Erlangen-Nürnberg */
8 /* 2014-2015 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-2015 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 
43 #include <assert.h>
44 
45 #include "sdpi/sdpisolver.h"
46 
47 /* turn off warnings for sdpa (doesn't seem to work) */
48 #pragma GCC diagnostic ignored "-Wstrict-prototypes"
49 #include "sdpa_call.h" /* SDPA callable library interface */
50 #pragma GCC diagnostic warning "-Wstrict-prototypes"
51 
52 #include "blockmemshell/memory.h" /* for memory allocation */
53 #include "scip/def.h" /* for SCIP_Real, _Bool, ... */
54 #include "scip/pub_misc.h" /* for sorting */
55 
56 #define EPSILONCHANGE 0.1
57 #define FEASTOLCHANGE 0.1
60 #define BMS_CALL(x) do \
61  { \
62  if( NULL == (x) ) \
63  { \
64  SCIPerrorMessage("No memory in function call.\n"); \
65  return SCIP_NOMEMORY; \
66  } \
67  } \
68  while( FALSE )
69 
71 #define CHECK_IF_SOLVED(sdpisolver) do \
72  { \
73  if (!(sdpisolver->solved)) \
74  { \
75  SCIPerrorMessage("Tried to access solution information for SDP %d ahead of solving!\n", sdpisolver->sdpcounter); \
76  return SCIP_LPERROR; \
77  } \
78  } \
79  while( FALSE )
80 
82 #define CHECK_IF_SOLVED_BOOL(sdpisolver) do \
83  { \
84  if (!(sdpisolver->solved)) \
85  { \
86  SCIPerrorMessage("Tried to access solution information for SDP %d ahead of solving!\n", sdpisolver->sdpcounter); \
87  return FALSE; \
88  } \
89  } \
90  while( FALSE )
91 
92 
94 struct SCIP_SDPiSolver
95 {
96  SCIP_MESSAGEHDLR* messagehdlr;
97  BMS_BLKMEM* blkmem;
98  SDPA* sdpa;
99  int nvars;
100  int nactivevars;
101  int* inputtosdpamapper;
104  int* sdpatoinputmapper;
105  SCIP_Real* fixedvarsval;
106  SCIP_Real fixedvarsobjcontr;
107  int nvarbounds;
108  int* varboundpos;
110  SCIP_Bool solved;
111  int sdpcounter;
112  SCIP_Real epsilon;
113  SCIP_Real feastol;
114  SCIP_Real objlimit;
115 #if 0
116  int threads;
117 #endif
118  SCIP_Bool sdpinfo;
119  SCIP_Bool penalty;
120  SCIP_Bool rbound;
121 };
122 
123 
124 /*
125  * Local Functions
126  */
127 
128 #ifndef NDEBUG
129 
130 static
131 SCIP_Bool isFixed(
132  SCIP_SDPISOLVER* sdpisolver,
133  SCIP_Real lb,
134  SCIP_Real ub
135  )
136 {
137  assert( sdpisolver != NULL );
138  assert( lb < ub + sdpisolver->feastol );
139 
140  return (REALABS(ub-lb) <= sdpisolver->feastol);
141 }
142 #else
143 #define isFixed(sdpisolver,lb,ub) (REALABS(ub-lb) <= sdpisolver->feastol)
144 #endif
145 
146 
147 /*
148  * Miscellaneous Methods
149  */
150 
157  void
158  )
159 {
160  return "SDPA"; /* version number can only be printed to file/stdout */
161 }
162 
165  void
166  )
167 {
168  return "Primal-dual Interior Point Solver for Semidefinite Programming developed by Katsuki Fujisawa et al. (sdpa.sourceforge.net)";
169 }
170 
178  SCIP_SDPISOLVER* sdpisolver
179  )
180 {
181  assert( sdpisolver != NULL );
182  return (void*) sdpisolver->sdpa;
183 }
184 
188 /*
189  * SDPI Creation and Destruction Methods
190  */
191 
196 SCIP_RETCODE SCIPsdpiSolverCreate(
197  SCIP_SDPISOLVER** sdpisolver,
198  SCIP_MESSAGEHDLR* messagehdlr,
199  BMS_BLKMEM* blkmem
200  )
201 {
202  assert( sdpisolver != NULL );
203  assert( blkmem != NULL );
204 
205  SCIPdebugMessage("Calling SCIPsdpiCreate \n");
206 
207  BMS_CALL( BMSallocBlockMemory(blkmem, sdpisolver) );
208 
209  (*sdpisolver)->messagehdlr = messagehdlr;
210  (*sdpisolver)->blkmem = blkmem;
211 
212  /* this will be properly initialized then calling solve */
213  (*sdpisolver)->sdpa = NULL;
214 
215  (*sdpisolver)->nvars = 0;
216  (*sdpisolver)->nactivevars = 0;
217  (*sdpisolver)->inputtosdpamapper = NULL;
218  (*sdpisolver)->sdpatoinputmapper = NULL;
219  (*sdpisolver)->fixedvarsval = NULL;
220  (*sdpisolver)->fixedvarsobjcontr = 0.0;
221  (*sdpisolver)->nvarbounds = 0;
222  (*sdpisolver)->varboundpos = NULL;
223  (*sdpisolver)->solved = FALSE;
224  (*sdpisolver)->sdpcounter = 0;
225 
226  (*sdpisolver)->epsilon = 1e-5;
227  (*sdpisolver)->feastol = 1e-4;
228  (*sdpisolver)->objlimit = SCIPsdpiSolverInfinity(*sdpisolver);
229 #if 0
230  (*sdpisolver)->threads = 1;
231 #endif
232  (*sdpisolver)->sdpinfo = FALSE;
233 
234  return SCIP_OKAY;
235 }
236 
238 SCIP_RETCODE SCIPsdpiSolverFree(
239  SCIP_SDPISOLVER** sdpisolver
240  )
241 {
242  assert( sdpisolver != NULL );
243  assert( *sdpisolver != NULL );
244 
245  SCIPdebugMessage("Freeing SDPISolver\n");
246 
247  if (((*sdpisolver)->sdpa) != NULL)
248  {
249  /* free SDPA object using destructor and free memory via blockmemshell */
250  delete (*sdpisolver)->sdpa;
251  }
252 
253  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->varboundpos, 2 * (*sdpisolver)->nvars); /*lint !e647*/
254 
255  if ( (*sdpisolver)->nvars > 0 )
256  BMSfreeBlockMemoryArray((*sdpisolver)->blkmem, &(*sdpisolver)->inputtosdpamapper, (*sdpisolver)->nvars);
257 
258  if ( (*sdpisolver)->nactivevars > 0 )
259  BMSfreeBlockMemoryArray((*sdpisolver)->blkmem, &(*sdpisolver)->sdpatoinputmapper, (*sdpisolver)->nactivevars);
260 
261  if ( (*sdpisolver)->nvars >= (*sdpisolver)->nactivevars )
262  BMSfreeBlockMemoryArrayNull((*sdpisolver)->blkmem, &(*sdpisolver)->fixedvarsval, (*sdpisolver)->nvars - (*sdpisolver)->nactivevars); /*lint !e776*/
263 
264  BMSfreeBlockMemory((*sdpisolver)->blkmem, sdpisolver);
265 
266  return SCIP_OKAY;
267 }
268 
271  SCIP_SDPISOLVER* sdpisolver
272  )
273 {
274  assert( sdpisolver != NULL );
275 
276  sdpisolver->sdpcounter++;
277 
278  return SCIP_OKAY;
279 }
280 
283  SCIP_SDPISOLVER* sdpisolver
284  )
285 {
286  assert( sdpisolver != NULL );
287 
288  SCIPdebugMessage("Resetting counter of SDP-Interface from %d to 0.\n", sdpisolver->sdpcounter);
289  sdpisolver->sdpcounter = 0;
290 
291  return SCIP_OKAY;
292 }
293 
297 /*
298  * Solving Methods
299  */
300 
317  SCIP_SDPISOLVER* sdpisolver,
318  int nvars,
319  SCIP_Real* obj,
320  SCIP_Real* lb,
321  SCIP_Real* ub,
322  int nsdpblocks,
323  int* sdpblocksizes,
324  int* sdpnblockvars,
325  int sdpconstnnonz,
326  int* sdpconstnblocknonz,
328  int** sdpconstrow,
329  int** sdpconstcol,
330  SCIP_Real** sdpconstval,
331  int sdpnnonz,
332  int** sdpnblockvarnonz,
334  int** sdpvar,
336  int*** sdprow,
337  int*** sdpcol,
338  SCIP_Real*** sdpval,
339  int** indchanges,
341  int* nremovedinds,
342  int* blockindchanges,
343  int nremovedblocks,
344  int nlpcons,
345  int noldlpcons,
346  SCIP_Real* lplhs,
347  SCIP_Real* lprhs,
348  int* lprownactivevars,
349  int lpnnonz,
350  int* lprow,
351  int* lpcol,
352  SCIP_Real* lpval,
353  SCIP_Real* start
354  )/* TODO: start needs to include X,y,Z for SDPA */
355 {
356  return SCIPsdpiSolverLoadAndSolveWithPenalty(sdpisolver, 0.0, TRUE, FALSE, nvars, obj, lb, ub, nsdpblocks, sdpblocksizes, sdpnblockvars, sdpconstnnonz,
357  sdpconstnblocknonz, sdpconstrow, sdpconstcol, sdpconstval, sdpnnonz, sdpnblockvarnonz, sdpvar, sdprow, sdpcol, sdpval, indchanges,
358  nremovedinds, blockindchanges, nremovedblocks, nlpcons, noldlpcons, lplhs, lprhs, lprownactivevars, lpnnonz, lprow, lpcol, lpval, start, NULL);
359 }
360 
381  SCIP_SDPISOLVER* sdpisolver,
382  SCIP_Real penaltyparam,
383  SCIP_Bool withobj,
384  SCIP_Bool rbound,
385  int nvars,
386  SCIP_Real* obj,
387  SCIP_Real* lb,
388  SCIP_Real* ub,
389  int nsdpblocks,
390  int* sdpblocksizes,
391  int* sdpnblockvars,
392  int sdpconstnnonz,
393  int* sdpconstnblocknonz,
395  int** sdpconstrow,
396  int** sdpconstcol,
397  SCIP_Real** sdpconstval,
398  int sdpnnonz,
399  int** sdpnblockvarnonz,
401  int** sdpvar,
403  int*** sdprow,
404  int*** sdpcol,
405  SCIP_Real*** sdpval,
406  int** indchanges,
408  int* nremovedinds,
409  int* blockindchanges,
410  int nremovedblocks,
411  int nlpcons,
412  int noldlpcons,
413  SCIP_Real* lplhs,
414  SCIP_Real* lprhs,
415  int* rownactivevars,
416  int lpnnonz,
417  int* lprow,
418  int* lpcol,
419  SCIP_Real* lpval,
420  SCIP_Real* start,
421  SCIP_Bool* feasorig
423 ) /*TODO: start needs to include X,y,Z for SDPA*/
424 {
425  SCIP_Real* sdpavarbounds;
426  int i;
427  int k;
428  int block;
429  int nfixedvars;
430  bool checkinput; /* should the input be checked for consistency in SDPA ? */
431  int lpconsind;
432  int lastrow;
433  int* rowmapper; /* maps the lhs- and rhs-inequalities of the old LP-cons to their constraint numbers in DSDP */
434  int nlpineqs;
435  int pos;
436  int newpos;
437 #ifdef SCIP_MORE_DEBUG
438  int ind;
439 #endif
440 
441 #ifdef SCIP_DEBUG
442  char phase_string[15];
443 #endif
444 
445  assert( sdpisolver != NULL );
446  assert( penaltyparam > -1 * sdpisolver->epsilon );
447  assert( penaltyparam < sdpisolver->epsilon || feasorig != NULL );
448  assert( nvars > 0 );
449  assert( obj != NULL );
450  assert( lb != NULL );
451  assert( ub != NULL );
452  assert( nsdpblocks >= 0 );
453  assert( nsdpblocks == 0 || sdpblocksizes != NULL );
454  assert( nsdpblocks == 0 || sdpnblockvars != NULL );
455  assert( sdpconstnnonz >= 0 );
456  assert( nsdpblocks == 0 || sdpconstnblocknonz != NULL );
457  assert( nsdpblocks == 0 || sdpconstrow != NULL );
458  assert( nsdpblocks == 0 || sdpconstcol != NULL );
459  assert( nsdpblocks == 0 || sdpconstval != NULL );
460  assert( sdpnnonz >= 0 );
461  assert( nsdpblocks == 0 || sdpnblockvarnonz != NULL );
462  assert( nsdpblocks == 0 || sdpvar != NULL );
463  assert( nsdpblocks == 0 || sdprow != NULL );
464  assert( nsdpblocks == 0 || sdpcol != NULL );
465  assert( nsdpblocks == 0 || sdpval != NULL );
466  assert( nsdpblocks == 0 || indchanges != NULL );
467  assert( nsdpblocks == 0 || nremovedinds != NULL );
468  assert( nsdpblocks == 0 || blockindchanges != NULL );
469  assert( 0 <= nremovedblocks && nremovedblocks <= nsdpblocks );
470  assert( nlpcons >= 0 );
471  assert( noldlpcons >= nlpcons );
472  assert( nlpcons == 0 || lplhs != NULL );
473  assert( nlpcons == 0 || lprhs != NULL );
474  assert( nlpcons == 0 || rownactivevars != NULL );
475  assert( lpnnonz >= 0 );
476  assert( nlpcons == 0 || lprow != NULL );
477  assert( nlpcons == 0 || lpcol != NULL );
478  assert( nlpcons == 0 || lpval != NULL );
479 
480 #ifndef SCIP_NDEBUG
481  checkinput = false;
482 #else
483  checkinput = true;
484 #endif
485 
486  /* 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
487  * same SDP) */
488  if ( penaltyparam < sdpisolver->epsilon )
489  SCIPdebugMessage("Inserting Data into SDPA for SDP (%d) \n", ++sdpisolver->sdpcounter);
490  else
491  SCIPdebugMessage("Inserting Data again into SDPA for SDP (%d) \n", sdpisolver->sdpcounter);
492 
493  /* set the penalty and rbound flags accordingly */
494  sdpisolver->penalty = (penaltyparam < sdpisolver->epsilon) ? FALSE : TRUE;
495  sdpisolver->rbound = rbound;
496 
497  /* allocate memory for inputtosdpamapper, sdpatoinputmapper and the fixed variable information, for the latter this will
498  * later be shrinked if the needed size is known */
499  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->inputtosdpamapper), sdpisolver->nvars, nvars) );
500  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->sdpatoinputmapper), sdpisolver->nactivevars, nvars) );
501  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->fixedvarsval), sdpisolver->nvars - sdpisolver->nactivevars, nvars) ); /*lint !e776*/
502 
503  sdpisolver->nvars = nvars;
504  sdpisolver->nactivevars = 0;
505  nfixedvars = 0;
506 
507  /* find the fixed variables */
508  sdpisolver->fixedvarsobjcontr = 0.0;
509  for (i = 0; i < nvars; i++)
510  {
511  if ( isFixed(sdpisolver, lb[i], ub[i]) )
512  {
513  sdpisolver->fixedvarsobjcontr += obj[i] * lb[i]; /* this is the value this fixed variable contributes to the objective */
514  sdpisolver->fixedvarsval[nfixedvars] = lb[i]; /* if lb=ub, than this is the value the variable will have in every solution */
515  nfixedvars++;
516  sdpisolver->inputtosdpamapper[i] = -nfixedvars;
517  SCIPdebugMessage("Fixing variable %d locally to %f for SDP %d in SDPA\n", i, lb[i], sdpisolver->sdpcounter);
518  }
519  else
520  {
521  sdpisolver->sdpatoinputmapper[sdpisolver->nactivevars] = i;
522  sdpisolver->nactivevars++;
523  sdpisolver->inputtosdpamapper[i] = sdpisolver->nactivevars; /* sdpa starts counting at 1, so we do this after increasing nactivevars */
524 #ifdef SCIP_MORE_DEBUG
525  SCIPdebugMessage("Variable %d becomes variable %d for SDP %d in SDPA\n", i, sdpisolver->inputtosdpamapper[i], sdpisolver->sdpcounter);
526 #endif
527  }
528  }
529  assert( sdpisolver->nactivevars + nfixedvars == sdpisolver->nvars );
530 
531  /* if we want to solve without objective, we reset fixedvarsobjcontr */
532  if ( ! withobj )
533  sdpisolver->fixedvarsobjcontr = 0.0;
534 
535  /* shrink the fixedvars and sdpatoinputmapper arrays to the right size */
536  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->fixedvarsval), nvars, nfixedvars) );
537  BMS_CALL( BMSreallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->sdpatoinputmapper), nvars, sdpisolver->nactivevars) );
538 
539  /* insert data */
540  if ( sdpisolver->sdpa != 0 )
541  {
542  /* if the SDPA solver has already been created, clear the current problem instance */
543  delete sdpisolver->sdpa;
544  sdpisolver->sdpa = new SDPA();
545  }
546  else
547  sdpisolver->sdpa = new SDPA();
548  assert( sdpisolver->sdpa != 0 );
549 
550  /* compute number of variable bounds and save them in sdpavarbounds */
551  sdpisolver->nvarbounds = 0;
552  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &sdpavarbounds, 2 * sdpisolver->nactivevars) ); /*lint !e647*/
553  if ( sdpisolver->varboundpos == NULL )
554  {
555  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &(sdpisolver->varboundpos), 2 * sdpisolver->nvars) ); /*lint !e647*/
556  }
557  for (i = 0; i < sdpisolver->nactivevars; i++)
558  {
559  assert( 0 <= sdpisolver->sdpatoinputmapper[i] && sdpisolver->sdpatoinputmapper[i] < nvars );
560  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, lb[sdpisolver->sdpatoinputmapper[i]]))
561  {
562  sdpavarbounds[sdpisolver->nvarbounds] = lb[sdpisolver->sdpatoinputmapper[i]];
563  sdpisolver->varboundpos[sdpisolver->nvarbounds] = -(i + 1); /* negative sign means lower bound, i + 1 because sdpa starts counting from one */
564  (sdpisolver->nvarbounds)++;
565  }
566  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, ub[sdpisolver->sdpatoinputmapper[i]]) )
567  {
568  sdpavarbounds[sdpisolver->nvarbounds] = ub[sdpisolver->sdpatoinputmapper[i]];
569  sdpisolver->varboundpos[sdpisolver->nvarbounds] = +(i + 1); /* positive sign means upper bound, i + 1 because sdpa starts counting from one */
570  (sdpisolver->nvarbounds)++;
571  }
572  }
573 
574  if ( nlpcons > 0 )
575  {
576  /* 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 */
577  BMS_CALL( BMSallocBlockMemoryArray(sdpisolver->blkmem, &rowmapper, 2*noldlpcons) ); /*lint !e647*/ /*lint !e530*/
578 
579  /* compute the number of LP constraints after splitting the ranged rows and compute the rowmapper */
580  pos = 1; /* SDPA starts counting the LP-inequalities at one */
581  newpos = 0; /* the position in the lhs and rhs arrays */
582  for (i = 0; i < noldlpcons; i++)
583  {
584  if ( rownactivevars[i] >= 2 )
585  {
586  if ( lplhs[newpos] > - SCIPsdpiSolverInfinity(sdpisolver) )
587  {
588  rowmapper[2*i] = pos; /*lint !e679*/
589  pos++;
590  }
591  else
592  rowmapper[2*i] = -1; /*lint !e679*/
593  if ( lprhs[newpos] < SCIPsdpiSolverInfinity(sdpisolver) )
594  {
595  rowmapper[2*i + 1] = pos; /*lint !e679*/
596  pos++;
597  }
598  else
599  rowmapper[2*i + 1] = -1; /*lint !e679*/
600 
601  newpos++;
602  }
603  else
604  {
605  rowmapper[2*i] = -1; /*lint !e679*/
606  rowmapper[2*i + 1] = -1; /*lint !e679*/
607  }
608  }
609  nlpineqs = pos - 1; /* minus one because we started at one as SDPA wants them numbered one to nlpineqs */
610  assert( nlpineqs <= 2*nlpcons ); /* *2 comes from left- and right-hand-sides */
611  }
612  else
613  nlpineqs = 0;
614 
615  /* if we use a penalty formulation, we need the constraint r >= 0 */
616  if ( penaltyparam >= sdpisolver->epsilon && rbound )
617  sdpisolver->nvarbounds++;
618 
619  if ( sdpisolver->sdpinfo )
620  sdpisolver->sdpa->setDisplay(stdout);
621  else
622  sdpisolver->sdpa->setDisplay(0);
623 
624 #ifdef SCIP_MORE_DEBUG
625  FILE* fpOut = fopen("output.tmp", "w");
626  if ( ! fpOut )
627  exit(-1);
628  sdpisolver->sdpa->setResultFile(fpOut);
629 #endif
630 
631  /* if we want to use a starting point we have to tell SDPA to allocate memory for it */
632  if ( start != NULL )
633  sdpisolver->sdpa->setInitPoint(true);
634 
635  /* initialize blockstruct */
636  if ( penaltyparam < sdpisolver->epsilon ) /* we initialize this with an exact 0.0 in Solve without penalty */
637  sdpisolver->sdpa->inputConstraintNumber((long long) sdpisolver->nactivevars);
638  else
639  sdpisolver->sdpa->inputConstraintNumber((long long) sdpisolver->nactivevars + 1); /* the additional variable is r for the penalty formulation */
640 
641  /* if there are any lp-cons/variable-bounds, we get an extra block for those, lastrow - nshifts is the number of lp constraints added */
642  sdpisolver->sdpa->inputBlockNumber((long long) ((nlpineqs + sdpisolver->nvarbounds > 0) ?
643  nsdpblocks - nremovedblocks + 1 : nsdpblocks - nremovedblocks)); /*lint !e834 !e776*/
644 
645  /* block+1 because SDPA starts counting at 1 */
646  for (block = 0; block < nsdpblocks; block++)
647  {
648  if ( blockindchanges[block] >= 0 )
649  {
650  SCIPdebugMessage("adding block %d to SDPA as block %d with size %d\n",
651  block, block - blockindchanges[block] + 1, sdpblocksizes[block] - nremovedinds[block]); /*lint !e834*/
652  sdpisolver->sdpa->inputBlockSize((long long) block - blockindchanges[block] + 1,
653  (long long) sdpblocksizes[block] - nremovedinds[block]); /*lint !e834, !e776*/
654  sdpisolver->sdpa->inputBlockType((long long) block - blockindchanges[block] + 1, SDPA::SDP); /*lint !e834, !e776*/
655  }
656  }
657  if ( nlpineqs + sdpisolver->nvarbounds > 0 )
658  {
659  /* the last block is the lp block, the size has a negative sign */
660  sdpisolver->sdpa->inputBlockSize((long long) nsdpblocks - nremovedblocks + 1, (long long) -(nlpineqs + sdpisolver->nvarbounds)); /*lint !e834, !e776*/
661  sdpisolver->sdpa->inputBlockType((long long) nsdpblocks - nremovedblocks + 1, SDPA::LP); /*lint !e834, !e776*/
662  SCIPdebugMessage("adding LP block to SDPA as block %d with size %d\n", nsdpblocks - nremovedblocks + 1,
663  -(nlpineqs + sdpisolver->nvarbounds)); /*lint !e834*/
664  }
665  sdpisolver->sdpa->initializeUpperTriangleSpace();
666 
667  /* set objective values */
668  for (i = 0; i < sdpisolver->nactivevars; i++)
669  {
670  if ( withobj )
671  {
672  /* insert objective value, SDPA counts from 1 to n instead of 0 to n-1 */
673  sdpisolver->sdpa->inputCVec((long long) i + 1, obj[sdpisolver->sdpatoinputmapper[i]]);
674 #ifdef SCIP_MORE_DEBUG
675  SCIPdebugMessage("inserting objective %f for variable %d which became variable %d in SDPA\n", obj[sdpisolver->sdpatoinputmapper[i]],
676  sdpisolver->sdpatoinputmapper[i], i+1);
677 #endif
678  }
679  if ( penaltyparam >= sdpisolver->epsilon )
680  sdpisolver->sdpa->inputCVec((long long) sdpisolver->nactivevars + 1, penaltyparam); /* set the objective of the additional var to penaltyparam */
681  }
682 
683  /* start inserting the non-constant SDP-Constraint-Matrices */
684  if ( sdpnnonz > 0 )
685  {
686  int v;
687  int blockvar;
688 
689  assert( nsdpblocks > 0 );
690  assert( sdpnblockvarnonz != NULL );
691  assert( sdpnblockvars != NULL );
692  assert( sdpcol != NULL );
693  assert( sdprow != NULL );
694  assert( sdpval != NULL );
695  assert( sdpvar != NULL );
696  assert( indchanges != NULL );
697  assert( nremovedinds != NULL );
698 
699  for (block = 0; block < nsdpblocks; block++)
700  {
701  /* if the block has no entries, we skip it */
702  if ( blockindchanges[block] == -1 )
703  continue;
704 #ifdef SCIP_MORE_DEBUG
705  SCIPdebugMessage(" -> building block %d, which becomes block %d in SDPA (%d)\n", block, block - blockindchanges[block] + 1,sdpisolver->sdpcounter);
706 #endif
707  /* iterate over all variables in this block */
708  for (blockvar = 0; blockvar < sdpnblockvars[block]; blockvar++)
709  {
710  v = sdpisolver->inputtosdpamapper[sdpvar[block][blockvar]];
711 
712 #ifdef SCIP_MORE_DEBUG
713  SCIPdebugMessage(" -> adding coefficient matrix for variable %d which becomes variable %d in SDPA (%d)\n",
714  sdpvar[block][blockvar], v, sdpisolver->sdpcounter);
715 #endif
716 
717  /* check if the variable is active */
718  if ( v > -1 )
719  {
720  for (k = 0; k < sdpnblockvarnonz[block][blockvar]; k++)
721  {
722  /* rows and cols with active nonzeros should not be removed */
723  assert( indchanges[block][sdprow[block][blockvar][k]] > -1 && indchanges[block][sdpcol[block][blockvar][k]] > -1 );
724 
725  assert( indchanges[block][sdprow[block][blockvar][k]] <= sdprow[block][blockvar][k]);
726  assert( indchanges[block][sdpcol[block][blockvar][k]] <= sdpcol[block][blockvar][k]);
727 
728  assert( 0 <= sdprow[block][blockvar][k] && sdprow[block][blockvar][k] < sdpblocksizes[block] );
729  assert( 0 <= sdpcol[block][blockvar][k] && sdpcol[block][blockvar][k] < sdpblocksizes[block] );
730 
731  /* rows and columns start with one in SDPA, so we have to add 1 to the indices */
732 #ifdef SCIP_MORE_DEBUG
733  SCIPdebugMessage(" -> adding nonzero %g at (%d,%d) (%d)\n",
734  sdpval[block][blockvar][k],
735  sdpcol[block][blockvar][k] - indchanges[block][sdpcol[block][blockvar][k]] + 1,
736  sdprow[block][blockvar][k] - indchanges[block][sdprow[block][blockvar][k]] + 1,
737  sdpisolver->sdpcounter);
738 #endif
739 
740  sdpisolver->sdpa->inputElement((long long) v, (long long) block - blockindchanges[block] + 1, /*lint !e834*/
741  (long long) sdpcol[block][blockvar][k] - indchanges[block][sdpcol[block][blockvar][k]] + 1, /*lint !e834*/
742  (long long) sdprow[block][blockvar][k] - indchanges[block][sdprow[block][blockvar][k]] + 1, /*lint !e834*/
743  sdpval[block][blockvar][k], checkinput); /*lint !e776 !e834*/
744  }
745  }
746  }
747  /* insert the identity matrix if we are using a penalty formulation */
748  if ( penaltyparam >= sdpisolver->epsilon )
749  {
750 #ifdef SCIP_MORE_DEBUG
751  SCIPdebugMessage(" -> adding coefficient matrix for penalty variable r in SDPA (%d)\n", sdpisolver->sdpcounter);
752 #endif
753  for (i = 0; i < sdpblocksizes[block] - nremovedinds[block]; i++)
754  {
755 #ifdef SCIP_MORE_DEBUG
756  SCIPdebugMessage(" -> adding nonzero 1.0 at (%d,%d) (%d)\n", i + 1, i + 1, sdpisolver->sdpcounter);
757 #endif
758 
759  sdpisolver->sdpa->inputElement((long long) sdpisolver->nactivevars + 1, (long long) block - blockindchanges[block] + 1, /*lint !e776, !e834*/
760  (long long) i + 1, (long long) i + 1, 1.0, checkinput);
761  }
762  }
763  }
764  }
765 
766  /* start inserting the constant matrix */
767  if ( sdpconstnnonz > 0 )
768  {
769  assert( nsdpblocks > 0 );
770  assert( sdpconstnblocknonz!= NULL );
771  assert( sdpconstcol != NULL );
772  assert( sdpconstrow != NULL );
773  assert( sdpconstval != NULL );
774 
775  for (block = 0; block < nsdpblocks; block++)
776  {
777  if ( blockindchanges[block] == -1 )
778  continue;
779 #ifdef SCIP_MORE_DEBUG
780  SCIPdebugMessage(" -> building block %d (%d)\n", block + 1, sdpisolver->sdpcounter);
781 #endif
782  for (k = 0; k < sdpconstnblocknonz[block]; k++)
783  {
784  /* rows and cols with active nonzeros should not be removed */
785  assert( indchanges[block][sdpconstrow[block][k]] > -1 && indchanges[block][sdpconstcol[block][k]] > -1 );
786 
787  assert( indchanges[block][sdpconstrow[block][k]] <= sdpconstrow[block][k]);
788  assert( indchanges[block][sdpconstcol[block][k]] <= sdpconstcol[block][k]);
789 
790  assert (0 <= sdpconstrow[block][k] && sdpconstrow[block][k] < sdpblocksizes[block]);
791  assert (0 <= sdpconstcol[block][k] && sdpconstcol[block][k] < sdpblocksizes[block]);
792 
793  /* 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 */
794 #ifdef SCIP_MORE_DEBUG
795  SCIPdebugMessage(" -> adding constant nonzero %g at (%d,%d) (%d)\n", sdpconstval[block][k],
796  sdpconstcol[block][k] - indchanges[block][sdpconstcol[block][k]] + 1,
797  sdpconstrow[block][k] - indchanges[block][sdpconstrow[block][k]] + 1,
798  sdpisolver->sdpcounter);
799 #endif
800  sdpisolver->sdpa->inputElement((long long) 0, (long long) block - blockindchanges[block] + 1, /*lint !e776, !e834*/
801  (long long) sdpconstcol[block][k] - indchanges[block][sdpconstcol[block][k]] + 1, /*lint !e776, !e834*/
802  (long long) sdpconstrow[block][k] - indchanges[block][sdpconstrow[block][k]] + 1, /*lint !e776, !e834*/
803  sdpconstval[block][k], checkinput);
804  }
805  }
806  }
807 
808 #ifdef SCIP_MORE_DEBUG
809  SCIPdebugMessage(" -> building LP-block %d (%d)\n", nsdpblocks - nremovedblocks + 1, sdpisolver->sdpcounter);
810 #endif
811  /* inserting LP nonzeros */
812  lastrow = -1;
813  for (i = 0; i < lpnnonz; i++)
814  {
815  assert( 0 <= lprow[i] && lprow[i] < noldlpcons );
816  assert( 0 <= lpcol[i] && lpcol[i] < nvars );
817  assert( REALABS(lpval[i]) > sdpisolver->epsilon );
818 
819  /* if the variable is active and the constraint is more than a bound, we add it */
820  if ( sdpisolver->inputtosdpamapper[lpcol[i]] > 0 )
821  {
822  /* as this is an active variable, there should be at least one in the constraint */
823  assert( rownactivevars[lprow[i]] > 0 );
824  if ( rownactivevars[lprow[i]] > 1 )
825  {
826  if ( lprow[i] > lastrow ) /* we update the lpcons-counter */
827  {
828  lastrow = lprow[i];
829  /* if we use a penalty formulation, add the r * Identity entry */
830  if ( penaltyparam >= sdpisolver->epsilon )
831  {
832  /* check for the lhs-inequality */
833  if ( rowmapper[2*lastrow] > -1 ) /*lint !e679*/
834  {
835 #ifdef SCIP_MORE_DEBUG
836  SCIPdebugMessage(" -> adding nonzero 1.0 at (%d,%d) for penalty variable r in SDPA (%d)\n",
837  rowmapper[2*lastrow], rowmapper[2*lastrow], sdpisolver->sdpcounter);
838 #endif
839  /* LP nonzeros are added as diagonal entries of the last block (coming after the last SDP-block, with
840  * blocks starting at 1, as are rows), the r-variable is variable nactivevars + 1 */
841  sdpisolver->sdpa->inputElement((long long) sdpisolver->nactivevars + 1, (long long) nsdpblocks - nremovedblocks + 1, /*lint !e776, !e834*/
842  (long long) rowmapper[2*lastrow], (long long) rowmapper[2*lastrow], 1.0, checkinput); /*lint !e679, !e834*/
843  }
844 
845  /* check for the rhs-inequality */
846  if ( rowmapper[2*lastrow + 1] > -1 ) /*lint !e679*/
847  {
848 #ifdef SCIP_MORE_DEBUG
849  SCIPdebugMessage(" -> adding nonzero 1.0 at (%d,%d) for penalty variable r in SDPA (%d)\n",
850  rowmapper[2*lastrow + 1], rowmapper[2*lastrow + 1], sdpisolver->sdpcounter);
851 #endif
852  /* LP nonzeros are added as diagonal entries of the last block (coming after the last SDP-block, with
853  * blocks starting at 1, as are rows), the r-variable is variable nactivevars + 1 */
854  sdpisolver->sdpa->inputElement((long long) sdpisolver->nactivevars + 1, (long long) nsdpblocks - nremovedblocks + 1, /*lint !e776, !e834*/
855  (long long) rowmapper[2*lastrow + 1], (long long) rowmapper[2*lastrow + 1], 1.0, checkinput); /*lint !e679, !e834*/
856  }
857  }
858  }
859  /* add the lp-nonzero to the lhs-inequality if it exists: */
860  if ( rowmapper[2*lastrow] > -1 ) /*lint !e679*/
861  {
862 #ifdef SCIP_MORE_DEBUG
863  SCIPdebugMessage(" -> adding nonzero %g at (%d,%d) for variable %d which became variable %d in SDPA (%d)\n",
864  lpval[i], rowmapper[2*lastrow], rowmapper[2*lastrow], lpcol[i], sdpisolver->inputtosdpamapper[lpcol[i]], sdpisolver->sdpcounter);
865 #endif
866  /* 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) */
867  sdpisolver->sdpa->inputElement((long long) sdpisolver->inputtosdpamapper[lpcol[i]], (long long) nsdpblocks - nremovedblocks + 1, /*lint !e776, !e834*/
868  (long long) rowmapper[2*lastrow], (long long) rowmapper[2*lastrow], lpval[i], checkinput); /*lint !e679, !e834*/
869  }
870  /* add the lp-nonzero to the rhs-inequality if it exists: */
871  if ( rowmapper[2*lastrow + 1] > -1 ) /*lint !e679*/
872  {
873 #ifdef SCIP_MORE_DEBUG
874  SCIPdebugMessage(" -> adding nonzero %g at (%d,%d) for variable %d which became variable %d in SDPA (%d)\n",
875  -1 * lpval[i], rowmapper[2*lastrow + 1], rowmapper[2*lastrow + 1], lpcol[i], sdpisolver->inputtosdpamapper[lpcol[i]], sdpisolver->sdpcounter);
876 #endif
877  /* 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),
878  * the -1 comes from the fact that this is a <=-constraint, while SDPA works with >= */
879  sdpisolver->sdpa->inputElement((long long) sdpisolver->inputtosdpamapper[lpcol[i]], (long long) nsdpblocks - nremovedblocks + 1, /*lint !e776, !e834*/
880  (long long) rowmapper[2*lastrow + 1], (long long) rowmapper[2*lastrow + 1], -1 * lpval[i], checkinput); /*lint !e679, !e834*/
881  }
882  }
883  }
884  }
885 
886  /* inserting LP left- and right-hand-sides for active constraints */
887  lpconsind = 1; /* this is the same order we used when computing the rowmapper, so we insert at the right positions */
888  for (i = 0; i < nlpcons; i++)
889  {
890  /* check for left-hand side */
891  if ( lplhs[i] > - SCIPsdpiSolverInfinity(sdpisolver) )
892  {
893 #ifdef SCIP_MORE_DEBUG
894  SCIPdebugMessage(" -> adding lhs %g at (%d,%d) (%d)\n", lplhs[i], lpconsind, lpconsind, sdpisolver->sdpcounter);
895 #endif
896  /* LP constraints are added as diagonal entries of the last block, left-hand-side is added as variable zero */
897  sdpisolver->sdpa->inputElement((long long) 0, (long long) nsdpblocks - nremovedblocks + 1, (long long) lpconsind, /*lint !e776, !e834*/
898  (long long) lpconsind, lplhs[i], checkinput);
899  lpconsind++;
900  }
901  /* check for right-hand side */
902  if ( lprhs[i] < SCIPsdpiSolverInfinity(sdpisolver) )
903  {
904 #ifdef SCIP_MORE_DEBUG
905  SCIPdebugMessage(" -> adding lhs (originally rhs) %g at (%d,%d) (%d)\n", -1 * lprhs[i], lpconsind, lpconsind, sdpisolver->sdpcounter);
906 #endif
907  /* LP constraints are added as diagonal entries of the last block, right-hand side is added as variable zero, the -1 comes from
908  * the fact, that SDPA uses >=, while the rhs is a <=-constraint */
909  sdpisolver->sdpa->inputElement((long long) 0, (long long) nsdpblocks - nremovedblocks + 1, (long long) lpconsind, /*lint !e776, !e834*/
910  (long long) lpconsind, -1 * lprhs[i], checkinput);
911  lpconsind++;
912  }
913  }
914 
915  assert( lpconsind == nlpineqs + 1 ); /* plus one because we started at one as SDPA wants them numbered one to nlpineqs */
916 
917  /* print each LP-constraint as one formatted constraint in addition to the single entries inserted into SDPA */
918 #ifdef SCIP_MORE_DEBUG
919  lastrow = -1;
920  ind = -1; /* this is increased once before the first usage */
921  for (i = 0; i < lpnnonz; i++)
922  {
923  /* if the variable is active and the constraint is more than a bound, we added it */
924  if ( sdpisolver->inputtosdpamapper[lpcol[i]] > 0 )
925  {
926  if ( rownactivevars[lprow[i]] > 1 )
927  {
928  if ( lprow[i] > lastrow ) /* we finished the old row */
929  {
930  if ( lastrow >= 0 )
931  {
932  if ( lprhs[ind] < SCIPsdpiSolverInfinity(sdpisolver) )
933  printf(" <= %f\n", lprhs[ind]);
934  else
935  printf("\n");
936  }
937  lastrow = lprow[i];
938  ind++;
939  if ( lplhs[ind] > - SCIPsdpiSolverInfinity(sdpisolver) )
940  printf("%f <= ", lplhs[ind]);
941  }
942  printf("+ %f <x%d> ", lpval[i], lpcol[i]);
943  }
944  }
945  }
946  if ( lastrow >= 0 )
947  {
948  if ( lprhs[ind] < SCIPsdpiSolverInfinity(sdpisolver) )
949  printf(" <= %f\n", lprhs[ind]);
950  else
951  printf("\n");
952  }
953  assert( ind == nlpcons - 1 ); /* -1 because we start indexing at zero and do not increase after the last row */
954 #endif
955 
956  /* free the memory for the rowmapper */
957  if ( nlpcons > 0 )
958  BMSfreeBlockMemoryArray(sdpisolver->blkmem, &rowmapper, 2 * noldlpcons);
959 
960  /* insert variable bounds, these are also added as LP-constraints and therefore diagonal entries of the LP block
961  * if we work with the penalty formulation, we get an extra entry for r >= 0, but this we will add afterwards */
962  for (i = 0; i < ((penaltyparam < sdpisolver->epsilon) ? sdpisolver->nvarbounds : sdpisolver->nvarbounds - 1); i++)
963  {
964  assert( 0 < abs(sdpisolver->varboundpos[i]) && abs(sdpisolver->varboundpos[i] <= sdpisolver->nactivevars) ); /* the indices are already those for SDPA */
965 
966  /* for lower bound */
967  if ( sdpisolver->varboundpos[i] < 0 )
968  {
969  /* add it as an lp-constraint for this variable (- because we saved -n for the lower bound), at the position
970  * (nactivelpcons + 1) + varbound-index, because we have >= the variable has coefficient +1 */
971  sdpisolver->sdpa->inputElement((long long) -sdpisolver->varboundpos[i], (long long) nsdpblocks - nremovedblocks + 1, /*lint !e776, !e834*/
972  (long long) nlpineqs + 1 + i, (long long) nlpineqs + 1 + i, 1.0, checkinput);
973 
974  if ( REALABS(sdpavarbounds[i]) > sdpisolver->epsilon )
975  {
976  /* the bound is added as the rhs and therefore variable zero */
977 #ifdef SCIP_MORE_DEBUG
978  SCIPdebugMessage(" -> adding lower bound %g at (%d,%d) for variable %d which became variable %d in SDPA (%d)\n",
979  sdpavarbounds[i], nlpineqs + 1 + i, nlpineqs + 1 + i, sdpisolver->sdpatoinputmapper[-sdpisolver->varboundpos[i] - 1],
980  -sdpisolver->varboundpos[i], sdpisolver->sdpcounter);
981 #endif
982  sdpisolver->sdpa->inputElement((long long) 0, (long long) nsdpblocks - nremovedblocks + 1, (long long) nlpineqs + 1 + i, /*lint !e776, !e834*/
983  (long long) nlpineqs + 1 + i, sdpavarbounds[i], checkinput);
984  }
985  else
986  {
987  /* as the bound is zero, we don't need to add a right hand side */
988 #ifdef SCIP_MORE_DEBUG
989  SCIPdebugMessage(" -> adding lower bound 0 at (%d,%d) for variable %d which became variable %d in SDPA (%d)\n",
990  nlpineqs + 1 + i, nlpineqs + 1 + i, sdpisolver->sdpatoinputmapper[-sdpisolver->varboundpos[i] - 1],
991  -sdpisolver->varboundpos[i], sdpisolver->sdpcounter);
992 #endif
993  }
994  }
995  else
996  {
997  /* this is an upper bound */
998 
999  /* add it as an lp-constraint for this variable, at the position nactivelpcons + varbound-index, because we have >= but we
1000  * want <= for the upper bound, we have to multiply by -1 and therefore the variable has coefficient -1 */
1001  sdpisolver->sdpa->inputElement((long long) sdpisolver->varboundpos[i], (long long) nsdpblocks - nremovedblocks + 1, /*lint !e776, !e834*/
1002  (long long) nlpineqs + 1 + i, (long long) nlpineqs + 1 + i, -1.0, checkinput);
1003 
1004  if ( REALABS(sdpavarbounds[i]) > sdpisolver->epsilon )
1005  {
1006  /* the bound is added as the rhs and therefore variable zero, we multiply by -1 for <= */
1007 #ifdef SCIP_MORE_DEBUG
1008  SCIPdebugMessage(" -> adding upper bound %g at (%d,%d) for variable %d which became variable %d in SDPA (%d)\n",
1009  sdpavarbounds[i], nlpineqs + 1 + i, nlpineqs + 1 + i, sdpisolver->sdpatoinputmapper[sdpisolver->varboundpos[i] - 1],
1010  sdpisolver->varboundpos[i], sdpisolver->sdpcounter);
1011 #endif
1012  sdpisolver->sdpa->inputElement((long long) 0, (long long) nsdpblocks - nremovedblocks + 1, (long long) nlpineqs + 1 + i, /*lint !e776, !e834*/
1013  (long long) nlpineqs + 1 + i, -sdpavarbounds[i], checkinput);
1014  }
1015  else
1016  {
1017  /* as the bound is zero, we don't need to add a right hand side */
1018 #ifdef SCIP_MORE_DEBUG
1019  SCIPdebugMessage(" -> adding upper bound 0 at (%d,%d) for variable %d which became variable %d in SDPA (%d)\n",
1020  0, nlpineqs + 1 + i, nlpineqs + 1 + i, sdpisolver->sdpatoinputmapper[sdpisolver->varboundpos[i] - 1],
1021  sdpisolver->varboundpos[i]);
1022 #endif
1023  }
1024  }
1025  }
1026 
1027  if ( penaltyparam >= sdpisolver->epsilon && rbound )
1028  {
1029  /* we add the variable bound r >= 0 */
1030  sdpisolver->sdpa->inputElement((long long) sdpisolver->nactivevars + 1, (long long) nsdpblocks - nremovedblocks + 1, /*lint !e776, !e834*/
1031  (long long) nlpineqs + 1 + i, (long long) nlpineqs + 1 + i, 1.0, checkinput);
1032 #ifdef SCIP_MORE_DEBUG
1033  SCIPdebugMessage(" -> adding lower bound r >= 0 at (%d,%d) in SDPA (%d)\n", nlpineqs + 1 + i, nlpineqs + 1 + i, sdpisolver->sdpcounter);
1034 #endif
1035  }
1036 
1037  /* free the arrays used for counting and saving variable bounds and LP-right-hand-sides */
1038  BMSfreeBlockMemoryArray(sdpisolver->blkmem, &sdpavarbounds, 2 * sdpisolver->nactivevars); /*lint !e647*/
1039 
1040  /* transform the matrices to a more efficient form */
1041  sdpisolver->sdpa->initializeUpperTriangle();
1042 
1043 #ifdef SCIP_DEBUG_PRINTTOFILE
1044  /* if necessary, dump input data and initial point */
1045  sdpisolver->sdpa->writeInputSparse(const_cast<char*>("sdpa.dat-s"), const_cast<char*>("%+8.3e"));
1046  sdpisolver->sdpa->writeInitSparse(const_cast<char*>("sdpa.ini-s"), const_cast<char*>("%+8.3e"));
1047 #endif
1048 
1049  sdpisolver->sdpa->initializeSolve();
1050 
1051  /* set the starting solution */
1052  if ( start != NULL && penaltyparam < sdpisolver->epsilon )
1053  {
1054  /* TODO: needs to be changed to y, Z and penalty formulation */
1055  SCIPdebugMessage("Starting with a previous solution is not yet tested for the interface, only x-vector is given, not y and Z");
1056  for (i = 1; i <= sdpisolver->nactivevars; i++) /* we iterate over the variables in sdpa */
1057  sdpisolver->sdpa->inputInitXVec((long long) i, start[sdpisolver->sdpatoinputmapper[i] - 1]);
1058  }
1059  else if ( penaltyparam >= sdpisolver->epsilon )
1060  SCIPdebugMessage("Skipping insertion of starting point, as this is not yet supported for penalty formulation.\n");
1061 
1062  /* initialize settings */
1063  if ( penaltyparam < sdpisolver->epsilon )
1064  {
1065  sdpisolver->sdpa->setParameterType(SDPA::PARAMETER_UNSTABLE_BUT_FAST);
1066  sdpisolver->sdpa->setParameterEpsilonStar(sdpisolver->epsilon);
1067  sdpisolver->sdpa->setParameterEpsilonDash(sdpisolver->feastol);
1068  }
1069  else
1070  {
1071  sdpisolver->sdpa->setParameterType(SDPA::PARAMETER_STABLE_BUT_SLOW); /* if we already had problems with this problem, there is no reason to try fast */
1072  /* 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 */
1073  sdpisolver->sdpa->setParameterEpsilonStar(EPSILONCHANGE * EPSILONCHANGE * sdpisolver->epsilon);
1074  sdpisolver->sdpa->setParameterEpsilonDash(FEASTOLCHANGE * FEASTOLCHANGE * sdpisolver->feastol);
1075  }
1076  sdpisolver->sdpa->setParameterLowerBound(-1e20);
1077 
1078  /* set the objective limit */
1079  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, sdpisolver->objlimit) )
1080  sdpisolver->sdpa->setParameterUpperBound(sdpisolver->objlimit);
1081  else
1082  sdpisolver->sdpa->setParameterUpperBound(1e20);
1083 #ifdef SCIP_MORE_DEBUG
1084  sdpisolver->sdpa->printParameters(stdout);
1085 #endif
1086 
1087 #if 0
1088  /* set number of threads */
1089  char str[1024];
1090  snprintf(str, 1024, "OMP_NUM_THREADS=%d", sdpisolver->threads);
1091  int status = putenv(str);
1092  if ( status )
1093  {
1094  SCIPdebugMessage("Setting the number of threads failed (%d, %d).\n", status, errno);
1095  return SCIP_LPERROR;
1096  }
1097 #endif
1098 #if 0
1099  SCIPdebugMessage("Calling SDPA solve (SDP: %d, threads: %d)\n", sdpisolver->sdpcounter, sdpisolver->sdpa->getNumThreads());
1100 #else
1101  SCIPdebugMessage("Calling SDPA solve (SDP: %d)\n", sdpisolver->sdpcounter);
1102 #endif
1103  sdpisolver->sdpa->solve();
1104  sdpisolver->solved = TRUE;
1105 
1106 #ifdef SCIP_DEBUG
1107  /* print the phase value , i.e. whether solving was successfull */
1108  sdpisolver->sdpa->getPhaseString((char*)phase_string);
1109  SCIPdebugMessage("SDPA solving finished with status %s (primal and dual here are switched in contrast to our formulation)\n", phase_string);
1110 #endif
1111 
1112  /* check whether problem has been stably solved, if it wasn't and we didn't yet run the stable parametersettings (for the penalty formulation we do so), try
1113  * again with more stable parameters */
1114  if ( (! SCIPsdpiSolverIsAcceptable(sdpisolver)) && penaltyparam < sdpisolver->epsilon )
1115  {
1116  SCIPdebugMessage("Numerical troubles -- solving SDP %d again ...\n", sdpisolver->sdpcounter);
1117 
1118  /* initialize settings */
1119  sdpisolver->sdpa->setParameterType(SDPA::PARAMETER_DEFAULT);
1120  sdpisolver->sdpa->setParameterEpsilonStar(EPSILONCHANGE * sdpisolver->epsilon);
1121  sdpisolver->sdpa->setParameterEpsilonDash(FEASTOLCHANGE * sdpisolver->feastol);
1122  /* set the objective limit */
1123  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, sdpisolver->objlimit) )
1124  sdpisolver->sdpa->setParameterUpperBound(sdpisolver->objlimit);
1125  else
1126  sdpisolver->sdpa->setParameterUpperBound(1e20);
1127 #ifdef SCIP_MORE_DEBUG
1128  sdpisolver->sdpa->printParameters(stdout);
1129 #endif
1130  sdpisolver->sdpa->solve();
1131  sdpisolver->solved = TRUE;
1132 
1133 #ifdef SCIP_DEBUG
1134  /* print the phase value , i.e. whether solving was successfull */
1135  sdpisolver->sdpa->getPhaseString((char*)phase_string);
1136  SCIPdebugMessage("SDPA solving finished with status %s (primal and dual here are switched in contrast to our formulation)\n", phase_string);
1137 #endif
1138 
1139  /* if we still didn't converge, set the parameters even more conservativly */
1140  if ( ! SCIPsdpiSolverIsAcceptable(sdpisolver) )
1141  {
1142  SCIPdebugMessage("Numerical troubles -- solving SDP %d again^2 ...\n", sdpisolver->sdpcounter);
1143 
1144  /* initialize settings */
1145  sdpisolver->sdpa->setParameterType(SDPA::PARAMETER_STABLE_BUT_SLOW);
1146  sdpisolver->sdpa->setParameterEpsilonStar(EPSILONCHANGE * EPSILONCHANGE * sdpisolver->epsilon);
1147  sdpisolver->sdpa->setParameterEpsilonDash(FEASTOLCHANGE * FEASTOLCHANGE * sdpisolver->feastol);
1148  /* set the objective limit */
1149  if ( ! SCIPsdpiSolverIsInfinity(sdpisolver, sdpisolver->objlimit) )
1150  sdpisolver->sdpa->setParameterUpperBound(sdpisolver->objlimit);
1151  else
1152  sdpisolver->sdpa->setParameterUpperBound(1e20);
1153 #ifdef SCIP_MORE_DEBUG
1154  sdpisolver->sdpa->printParameters(stdout);
1155 #endif
1156  sdpisolver->sdpa->solve();
1157  sdpisolver->solved = TRUE;
1158 
1159 #ifdef SCIP_DEBUG
1160  /* print the phase value , i.e. whether solving was successfull */
1161  sdpisolver->sdpa->getPhaseString((char*)phase_string);
1162  SCIPdebugMessage("SDPA solving finished with status %s (primal and dual here are switched in constrast to our formulation)\n", phase_string);
1163 #endif
1164  }
1165  }
1166 
1167 #ifdef SCIP_MORE_DEBUG
1168  (void) fclose(fpOut);
1169 #endif
1170 
1171  /* if we solved a penalty formulation, check if the solution is feasible for the original problem (which is the case iff r < feastol) */
1172  if ( penaltyparam >= sdpisolver->epsilon )
1173  {
1174  double* sdpasol;
1175 
1176  /* in the second case we have r as an additional variable */
1177  assert( (sdpisolver->nactivevars + 1 == sdpisolver->sdpa->getConstraintNumber()) ); /*lint !e776*/
1178 
1179  sdpasol = sdpisolver->sdpa->getResultXVec();
1180 
1181  /* we get r as the last variable in SDPA */
1182  *feasorig = (sdpasol[sdpisolver->nactivevars] < sdpisolver->feastol); /*lint !e413*/
1183  if ( ! *feasorig )
1184  {
1185  SCIPdebugMessage("Solution not feasible in original problem, r = %f\n", sdpasol[sdpisolver->nactivevars]);
1186  }
1187  }
1188 
1189  return SCIP_OKAY;
1190 }
1191 
1197 /*
1198  * Solution Information Methods
1199  */
1200 
1206  SCIP_SDPISOLVER* sdpisolver
1207  )
1208 {
1209  assert( sdpisolver != NULL );
1210  return sdpisolver->solved;
1211 }
1212 
1220  SCIP_SDPISOLVER* sdpisolver
1221  )
1222 {
1223  SDPA::PhaseType phasetype;
1224 
1225  assert( sdpisolver != NULL );
1226  assert( sdpisolver->sdpa != NULL);
1227  CHECK_IF_SOLVED_BOOL( sdpisolver );
1228 
1229  phasetype = sdpisolver->sdpa->getPhaseValue();
1230 
1231  if ( phasetype == SDPA::noINFO || phasetype == SDPA::pFEAS || phasetype == SDPA::dFEAS || phasetype == SDPA::pdINF )
1232  return FALSE;
1233 
1234  return TRUE;
1235 }
1236 
1239  SCIP_SDPISOLVER* sdpisolver,
1240  SCIP_Bool* primalfeasible,
1241  SCIP_Bool* dualfeasible
1242  )
1243 {
1244  SDPA::PhaseType phasetype;
1245 
1246  assert( sdpisolver != NULL );
1247  assert( sdpisolver->sdpa != NULL );
1248  assert( primalfeasible != NULL );
1249  assert( dualfeasible != NULL );
1250  CHECK_IF_SOLVED( sdpisolver );
1251 
1252  phasetype = sdpisolver->sdpa->getPhaseValue();
1253 
1254  switch ( phasetype )/*lint --e{788}*/
1255  {
1256  case SDPA::pdOPT:
1257  *primalfeasible = TRUE;
1258  *dualfeasible = TRUE;
1259  break;
1260  case SDPA::pdFEAS:
1261  *primalfeasible = TRUE;
1262  *dualfeasible = TRUE;
1263  break;
1264  case SDPA::pFEAS_dINF:
1265  *primalfeasible = TRUE;
1266  *dualfeasible = FALSE;
1267  break;
1268  case SDPA::pINF_dFEAS:
1269  *primalfeasible = FALSE;
1270  *dualfeasible = TRUE;
1271  break;
1272  case SDPA::pUNBD:
1273  *primalfeasible = TRUE;
1274  *dualfeasible = FALSE;
1275  SCIPdebugMessage("SDPA stopped because dual objective became smaller than lower bound\n");
1276  break;
1277  case SDPA::dUNBD:
1278  *primalfeasible = FALSE;
1279  *dualfeasible = TRUE;
1280  SCIPdebugMessage("SDPA stopped because primal objective became bigger than upper bound\n");
1281  break;
1282  default: /* contains noInfo, pFeas, dFeas, pdInf */
1283  SCIPerrorMessage("SDPA doesn't know if primal and dual solutions are feasible\n");
1284  return SCIP_LPERROR;
1285  }
1286 
1287  return SCIP_OKAY;
1288 }
1289 
1293  SCIP_SDPISOLVER* sdpisolver
1294  )
1295 {
1296  SDPA::PhaseType phasetype;
1297 
1298  assert( sdpisolver != NULL );
1299  assert( sdpisolver->sdpa != NULL );
1300  CHECK_IF_SOLVED_BOOL( sdpisolver );
1301 
1302  phasetype = sdpisolver->sdpa->getPhaseValue();
1303 
1304  if ( phasetype == SDPA::noINFO || phasetype == SDPA::pFEAS || phasetype == SDPA::pdINF )
1305  {
1306  SCIPdebugMessage("SDPA doesn't know if primal problem is unbounded");
1307  return FALSE;
1308  }
1309  else if ( phasetype == SDPA::pFEAS_dINF )
1310  return TRUE;
1311  else if ( phasetype == SDPA::pUNBD )
1312  {
1313  SCIPdebugMessage("SDPA was stopped because primal objective became bigger than upper bound");
1314  return TRUE;
1315  }
1316 
1317  return FALSE;
1318 }
1319 
1323  SCIP_SDPISOLVER* sdpisolver
1324  )
1325 {
1326  SDPA::PhaseType phasetype;
1327 
1328  assert( sdpisolver != NULL );
1329  assert( sdpisolver->sdpa != NULL );
1330  CHECK_IF_SOLVED_BOOL( sdpisolver );
1331 
1332  phasetype = sdpisolver->sdpa->getPhaseValue();
1333 
1334  if ( phasetype == SDPA::noINFO || phasetype == SDPA::dFEAS || phasetype == SDPA::pdINF )
1335  {
1336  SCIPdebugMessage("SDPA doesn't know if primal problem is infeasible");
1337  return FALSE;
1338  }
1339  else if ( phasetype == SDPA::pINF_dFEAS )
1340  return TRUE;
1341  else if ( phasetype == SDPA::dUNBD )
1342  {
1343  SCIPdebugMessage("SDPA was stopped because dual objective became smaller than lower bound");
1344  return TRUE;
1345  }
1346 
1347  return FALSE;
1348 }
1349 
1353  SCIP_SDPISOLVER* sdpisolver
1354  )
1355 {
1356  SDPA::PhaseType phasetype;
1357 
1358  assert( sdpisolver != NULL );
1359  assert( sdpisolver->sdpa != NULL );
1360  CHECK_IF_SOLVED_BOOL( sdpisolver );
1361 
1362  phasetype = sdpisolver->sdpa->getPhaseValue();
1363 
1364  if ( phasetype == SDPA::noINFO || phasetype == SDPA::dFEAS || phasetype == SDPA::pdINF )
1365  {
1366  SCIPdebugMessage("SDPA doesn't know if primal problem is feasible");
1367  return FALSE;
1368  }
1369  else if ( phasetype == SDPA::pFEAS_dINF || phasetype == SDPA::pdOPT || phasetype == SDPA::pFEAS || phasetype == SDPA::pdFEAS )
1370  return TRUE;
1371  else if ( phasetype == SDPA::dUNBD )
1372  {
1373  SCIPdebugMessage("SDPA was stopped because dual objective became smaller than lower bound");
1374  return TRUE;
1375  }
1376 
1377  return FALSE;
1378 }
1379 
1383  SCIP_SDPISOLVER* sdpisolver
1384  )
1385 {
1386  SDPA::PhaseType phasetype;
1387 
1388  assert( sdpisolver != NULL );
1389  assert( sdpisolver->sdpa != NULL);
1390  CHECK_IF_SOLVED_BOOL( sdpisolver );
1391 
1392  phasetype = sdpisolver->sdpa->getPhaseValue();
1393 
1394  if ( phasetype == SDPA::noINFO || phasetype == SDPA::dFEAS || phasetype == SDPA::pdINF )
1395  {
1396  SCIPdebugMessage("SDPA doesn't know if dual problem is unbounded");
1397  return FALSE;
1398  }
1399  else if ( phasetype == SDPA::pINF_dFEAS )
1400  return TRUE;
1401  else if ( phasetype == SDPA::dUNBD )
1402  {
1403  SCIPdebugMessage("SDPA was stopped because dual objective became smaller than lower bound");
1404  return TRUE;
1405  }
1406 
1407  return FALSE;
1408 }
1409 
1413  SCIP_SDPISOLVER* sdpisolver
1414  )
1415 {
1416  SDPA::PhaseType phasetype;
1417 
1418  assert( sdpisolver != NULL );
1419  assert( sdpisolver->sdpa != NULL);
1420  CHECK_IF_SOLVED_BOOL( sdpisolver );
1421 
1422  phasetype = sdpisolver->sdpa->getPhaseValue();
1423 
1424  if ( phasetype == SDPA::noINFO || phasetype == SDPA::pFEAS || phasetype == SDPA::pdINF )
1425  {
1426  SCIPdebugMessage("SDPA doesn't know if dual problem is infeasible");
1427  return FALSE;
1428  }
1429  else if ( phasetype == SDPA::pFEAS_dINF )
1430  return TRUE;
1431  else if ( phasetype == SDPA::pUNBD )
1432  {
1433  SCIPdebugMessage("SDPA was stopped because primal objective became bigger than upper bound");
1434  return TRUE;
1435  }
1436 
1437  return FALSE;
1438 }
1439 
1443  SCIP_SDPISOLVER* sdpisolver
1444  )
1445 {
1446  SDPA::PhaseType phasetype;
1447 
1448  assert( sdpisolver != NULL );
1449  assert( sdpisolver->sdpa != NULL);
1450  CHECK_IF_SOLVED_BOOL( sdpisolver );
1451 
1452  phasetype = sdpisolver->sdpa->getPhaseValue();
1453 
1454  if ( phasetype == SDPA::noINFO || phasetype == SDPA::dFEAS || phasetype == SDPA::pdINF )
1455  {
1456  SCIPdebugMessage("SDPA doesn't know if primal problem is feasible");
1457  return FALSE;
1458  }
1459  else if ( phasetype == SDPA::pINF_dFEAS || phasetype == SDPA::pdOPT || phasetype == SDPA::dFEAS || phasetype == SDPA::pdFEAS )
1460  return TRUE;
1461  else if ( phasetype == SDPA::dUNBD )
1462  {
1463  SCIPdebugMessage("SDPA was stopped because dual objective became smaller than lower bound");
1464  return TRUE;
1465  }
1466 
1467  return FALSE;
1468 }
1469 
1472  SCIP_SDPISOLVER* sdpisolver
1473  )
1474 {
1475  SDPA::PhaseType phasetype;
1476 
1477  assert( sdpisolver != NULL );
1478  assert( sdpisolver->sdpa != NULL );
1479  CHECK_IF_SOLVED_BOOL( sdpisolver );
1480 
1481  phasetype = sdpisolver->sdpa->getPhaseValue();
1482 
1483  if ( phasetype == SDPA::pdOPT )
1484  return TRUE;
1485 
1486  return FALSE;
1487 }
1488 
1491  SCIP_SDPISOLVER* sdpisolver
1492  )
1493 {
1494  SDPA::PhaseType phasetype;
1495 
1496  assert( sdpisolver != NULL );
1497  assert( sdpisolver->sdpa != NULL );
1498  CHECK_IF_SOLVED_BOOL( sdpisolver );
1499 
1500  phasetype = sdpisolver->sdpa->getPhaseValue();
1501 
1502  if ( phasetype == SDPA::pUNBD )
1503  return TRUE;
1504 
1505  return FALSE;
1506 }
1507 
1510  SCIP_SDPISOLVER* sdpisolver
1511  )
1512 {
1513  SDPA::PhaseType phasetype;
1514 
1515  assert( sdpisolver != NULL );
1516  assert( sdpisolver->sdpa != NULL);
1517  CHECK_IF_SOLVED_BOOL( sdpisolver );
1518 
1519  phasetype = sdpisolver->sdpa->getPhaseValue();
1520 
1521  if ( phasetype == SDPA::noINFO || phasetype == SDPA::pFEAS || phasetype == SDPA::dFEAS || phasetype == SDPA::pdFEAS )
1522  {
1523  if ( sdpisolver->sdpa->getParameterMaxIteration() == sdpisolver->sdpa->getIteration() )
1524  return TRUE;
1525  }
1526 
1527  return FALSE;
1528 }
1529 
1532  SCIP_SDPISOLVER* sdpisolver
1533  )
1534 {/*lint --e{715}*/
1535  SCIPdebugMessage("Not implemented in SDPA!\n");
1536  return FALSE;
1537 }
1538 
1550  SCIP_SDPISOLVER* sdpisolver
1551  )
1552 {
1553  SDPA::PhaseType phasetype;
1554 
1555  assert( sdpisolver != NULL );
1556  assert( sdpisolver->sdpa != NULL );
1557 
1558  if ( sdpisolver->sdpa == NULL || (! sdpisolver->solved) )
1559  return -1;
1560 
1561  phasetype = sdpisolver->sdpa->getPhaseValue();
1562 
1563  if ( phasetype == SDPA::pdOPT || phasetype == SDPA::pFEAS_dINF || phasetype == SDPA::pINF_dFEAS )
1564  return 0;
1565  if ( phasetype == SDPA::pdINF )
1566  return 1;
1567  if ( phasetype == SDPA::pUNBD)
1568  return 3;
1569  if ( phasetype == SDPA::noINFO || phasetype == SDPA::pFEAS || phasetype == SDPA::dFEAS || phasetype == SDPA::pdFEAS )
1570  return 4;
1571  else /* should include dUNBD */
1572  return 7;
1573 }
1574 
1577  SCIP_SDPISOLVER* sdpisolver
1578  )
1579 {
1580  SDPA::PhaseType phasetype;
1581 
1582  assert( sdpisolver != NULL );
1583  assert( sdpisolver->sdpa != NULL );
1584  CHECK_IF_SOLVED_BOOL( sdpisolver );
1585 
1586  phasetype = sdpisolver->sdpa->getPhaseValue();
1587 
1588  if ( phasetype == SDPA::pdOPT )
1589  return TRUE;
1590 
1591  return FALSE;
1592 }
1593 
1597  SCIP_SDPISOLVER* sdpisolver
1598  )
1599 {
1600  SDPA::PhaseType phasetype;
1601 
1602  assert( sdpisolver != NULL );
1603  assert( sdpisolver->sdpa != NULL );
1604  CHECK_IF_SOLVED_BOOL( sdpisolver );
1605 
1606  phasetype = sdpisolver->sdpa->getPhaseValue();
1607 
1608  /* we are happy if we converged, or we reached the objective limit (pUNBD) or we could show that our problem is
1609  * infeasible [except for numerics], or unbounded */
1610  if ( SCIPsdpiSolverIsConverged(sdpisolver) || phasetype == SDPA::pUNBD || phasetype == SDPA::pINF_dFEAS || phasetype == SDPA::pFEAS_dINF )
1611  return TRUE;
1612 
1613  return FALSE;
1614 }
1615 
1618  SCIP_SDPISOLVER* sdpisolver,
1619  SCIP_Bool* success
1620  )
1621 {/*lint --e{715}*/
1622  SCIPdebugMessage("Not implemented yet\n");
1623 
1624  /* todo: change settings to stable */
1625  return SCIP_LPERROR;
1626 }
1627 
1630  SCIP_SDPISOLVER* sdpisolver,
1631  SCIP_Real* objval
1632  )
1633 {
1634  assert( sdpisolver != NULL );
1635  assert( sdpisolver->sdpa != NULL );
1636  assert( objval != NULL );
1637  CHECK_IF_SOLVED( sdpisolver );
1638 
1639  *objval = sdpisolver->sdpa->getPrimalObj();
1640 
1641 #ifndef NDEBUG
1642  SCIP_Real primalval = sdpisolver->sdpa->getDualObj();
1643  SCIP_Real gap = (REALABS(*objval - primalval) / (0.5 * (REALABS(primalval) + REALABS(*objval)))); /* duality gap used in SDPA */
1644  if ( gap > sdpisolver->epsilon )
1645  SCIPdebugMessage("Attention: got objective value (before adding values of fixed variables) of %f in SCIPsdpiSolverGetObjval, "
1646  "but primal objective is %f with duality gap %f!\n", *objval, primalval, gap );
1647 #endif
1648 
1649  /* as we didn't add the fixed (lb = ub) variables to sdpa, we have to add their contributions to the objective by hand */
1650  *objval += sdpisolver->fixedvarsobjcontr;
1651 
1652  return SCIP_OKAY;
1653 }
1654 
1660  SCIP_SDPISOLVER* sdpisolver,
1661  SCIP_Real* objval,
1662  SCIP_Real* dualsol,
1663  int* dualsollength
1665  )
1666 {
1667  SCIP_Real* sdpasol;
1668  int v;
1669 
1670  assert( sdpisolver != NULL );
1671  assert( sdpisolver->sdpa != NULL );
1672  assert( dualsollength != NULL );
1673  CHECK_IF_SOLVED( sdpisolver );
1674 
1675  if ( objval != NULL )
1676  {
1677  *objval = sdpisolver->sdpa->getPrimalObj();
1678 
1679 #ifndef NDEBUG
1680  SCIP_Real primalval = sdpisolver->sdpa->getDualObj();
1681  SCIP_Real gap = (REALABS(*objval - primalval) / (0.5 * (REALABS(primalval) + REALABS(*objval)))); /* duality gap used in SDPA */
1682  if ( gap > sdpisolver->epsilon )
1683  {
1684  SCIPdebugMessage("Attention: got objective value (before adding values of fixed variables) of %f in SCIPsdpiSolverGetSol, "
1685  "but primal objective is %f with duality gap %f!\n", *objval, primalval, gap );
1686  }
1687 #endif
1688 
1689  /* as we didn't add the fixed (lb = ub) variables to sdpa, we have to add their contributions to the objective by hand */
1690  *objval += sdpisolver->fixedvarsobjcontr;
1691  }
1692 
1693  if ( *dualsollength > 0 )
1694  {
1695  assert( dualsol != NULL );
1696  if ( *dualsollength < sdpisolver->nvars )
1697  {
1698  SCIPdebugMessage("The given array in SCIPsdpiSolverGetSol only had length %d, but %d was needed", *dualsollength, sdpisolver->nvars);
1699  *dualsollength = sdpisolver->nvars;
1700 
1701  return SCIP_OKAY;
1702  }
1703 
1704  /* get the solution from sdpa */
1705  assert( (sdpisolver->penalty && sdpisolver->nactivevars + 1 == sdpisolver->sdpa->getConstraintNumber()) || /*lint !e776*/
1706  sdpisolver->nactivevars == sdpisolver->sdpa->getConstraintNumber() ); /* in the second case we have r as an additional variable */
1707  sdpasol = sdpisolver->sdpa->getResultXVec();
1708  /* 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) */
1709  for (v = 0; v < sdpisolver->nvars; v++)
1710  {
1711  if ( sdpisolver->inputtosdpamapper[v] > 0 )
1712  {
1713  /* minus one because the inputtosdpamapper gives the sdpa indices which start at one, but the array starts at 0 */
1714  dualsol[v] = sdpasol[sdpisolver->inputtosdpamapper[v] - 1];
1715  }
1716  else
1717  {
1718  /* this is the value that was saved when inserting, as this variable has lb=ub */
1719  assert( -sdpisolver->inputtosdpamapper[v] <= sdpisolver->nvars - sdpisolver->nactivevars );
1720  dualsol[v] = sdpisolver->fixedvarsval[(-1 * sdpisolver->inputtosdpamapper[v]) - 1]; /*lint !e679*/
1721  }
1722  }
1723  }
1724  return SCIP_OKAY;
1725 }
1726 
1735  SCIP_SDPISOLVER* sdpisolver,
1736  SCIP_Real* lbvars,
1737  SCIP_Real* ubvars,
1738  int* arraylength
1740  )
1741 {
1742  int i;
1743  double* X; /* block of primal solution matrix corresponding to the LP-part */
1744  int lpblockind;
1745  int nlpcons;
1746 
1747  assert( sdpisolver != NULL );
1748  assert( sdpisolver->sdpa != NULL );
1749  assert( lbvars != NULL );
1750  assert( ubvars != NULL );
1751  assert( arraylength != NULL );
1752  assert( *arraylength >= 0 );
1753  CHECK_IF_SOLVED( sdpisolver );
1754 
1755  /* check if the arrays are long enough */
1756  if ( *arraylength < sdpisolver->nvars )
1757  {
1758  *arraylength = sdpisolver->nvars;
1759  SCIPdebugMessage("Insufficient length of array in SCIPsdpiSolverGetPrimalBoundVars (gave %d, needed %d)\n", *arraylength, sdpisolver->nvars);
1760  return SCIP_OKAY;
1761  }
1762 
1763  /* initialize the return-arrays with zero */
1764  for (i = 0; i < sdpisolver->nvars; i++)
1765  {
1766  lbvars[i] = 0.0;
1767  ubvars[i] = 0.0;
1768  }
1769 
1770  /* 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) */
1771  if ( sdpisolver->nvarbounds == 0 )
1772  {
1773  SCIPdebugMessage("Asked for PrimalBoundVars, but there were no variable bounds in sdpa, returning zero vector !");
1774  return SCIP_OKAY;
1775  }
1776 
1777  /* get the block of primal solution matrix corresponding to the LP-part from sdpa */
1778  lpblockind = (int) sdpisolver->sdpa->getBlockNumber(); /* the LP block is the last one and sdpa counts from one */
1779  assert( sdpisolver->sdpa->getBlockType((long long) lpblockind) == SDPA::LP );
1780  nlpcons = (int) sdpisolver->sdpa->getBlockSize((long long) lpblockind);
1781  assert( nlpcons >= 0 );
1782 
1783  X = sdpisolver->sdpa->getResultYMat((long long) lpblockind);
1784 
1785  /* iterate over all variable bounds and insert the corresponding primal variables in the right positions of the return-arrays */
1786  assert( sdpisolver->nvarbounds <= 2 * sdpisolver->nvars || (sdpisolver->nvarbounds <= 2 * sdpisolver->nvars + 1 && sdpisolver->penalty ) );
1787  /* if we solved a penalty formulation, the last variable bound belongs to the penalty variable, which we aren't interested in here */
1788  for (i = 0; i < ((sdpisolver->penalty) ? sdpisolver->nvarbounds - 1 : sdpisolver->nvarbounds); i++)
1789  {
1790  if ( sdpisolver->varboundpos[i] < 0 )
1791  {
1792  /* this is a lower bound */
1793  /* the last nvarbounds entries correspond to the varbounds */
1794  lbvars[sdpisolver->sdpatoinputmapper[-1 * sdpisolver->varboundpos[i] -1]] = X[nlpcons - sdpisolver->nvarbounds + i]; /*lint !e679, !e834 */
1795  }
1796  else
1797  {
1798  /* this is an upper bound */
1799  /* the last nvarbounds entries correspond to the varbounds */
1800  ubvars[sdpisolver->sdpatoinputmapper[+1 * sdpisolver->varboundpos[i] - 1]] = X[nlpcons - sdpisolver->nvarbounds + i]; /*lint !e679, !e834 */
1801  }
1802  }
1803 
1804  return SCIP_OKAY;
1805 }
1806 
1809  SCIP_SDPISOLVER* sdpisolver,
1810  int* iterations
1811  )
1812 {
1813  assert( sdpisolver != NULL );
1814  assert( sdpisolver->sdpa != NULL );
1815  assert( iterations != NULL );
1816  CHECK_IF_SOLVED( sdpisolver );
1817 
1818  *iterations = (int) sdpisolver->sdpa->getIteration();
1819  return SCIP_OKAY;
1820 }
1821 
1827 /*
1828  * Numerical Methods
1829  */
1830 
1836  SCIP_SDPISOLVER* sdpisolver
1837  )
1838 {/*lint --e{715}*/
1839  return 1E+20; /* default infinity from SCIP */
1840 }
1841 
1844  SCIP_SDPISOLVER* sdpisolver,
1845  SCIP_Real val
1846  )
1847 {
1848  return ((val <= -SCIPsdpiSolverInfinity(sdpisolver)) || (val >= SCIPsdpiSolverInfinity(sdpisolver)));
1849 }
1850 
1853  SCIP_SDPISOLVER* sdpisolver
1854  )
1855 {/*lint --e{715}*/
1856  return 1E+10; /* this is the value DSDP will start with if called normally */
1857 }
1858 
1861  SCIP_SDPISOLVER* sdpisolver,
1862  SCIP_Real val
1863  )
1864 {
1865  return ((val <= -SCIPsdpiSolverMaxPenParam(sdpisolver)) || (val >= SCIPsdpiSolverMaxPenParam(sdpisolver)));
1866 }
1867 
1870  SCIP_SDPISOLVER* sdpisolver,
1871  SCIP_SDPPARAM type,
1872  SCIP_Real* dval
1873  )
1874 {
1875  assert( sdpisolver != NULL );
1876  assert( dval != NULL );
1877 
1878  switch( type )/*lint --e{788}*/
1879  {
1880  case SCIP_SDPPAR_EPSILON:
1881  *dval = sdpisolver->epsilon;
1882  break;
1883  case SCIP_SDPPAR_FEASTOL:
1884  *dval = sdpisolver->feastol;
1885  break;
1886  case SCIP_SDPPAR_OBJLIMIT:
1887  *dval = sdpisolver->objlimit;
1888  break;
1889  default:
1890  return SCIP_PARAMETERUNKNOWN;
1891  }
1892 
1893  return SCIP_OKAY;
1894 }
1895 
1898  SCIP_SDPISOLVER* sdpisolver,
1899  SCIP_SDPPARAM type,
1900  SCIP_Real dval
1901  )
1902 {
1903  assert( sdpisolver != NULL );
1904 
1905  switch( type )/*lint --e{788}*/
1906  {
1907  case SCIP_SDPPAR_EPSILON:
1908  sdpisolver->epsilon = dval;
1909  SCIPdebugMessage("Setting sdpisolver epsilon to %f.\n", dval);
1910  break;
1911  case SCIP_SDPPAR_FEASTOL:
1912  sdpisolver->feastol = dval;
1913  SCIPdebugMessage("Setting sdpisolver feastol to %f.\n", dval);
1914  break;
1915  case SCIP_SDPPAR_OBJLIMIT:
1916  SCIPdebugMessage("Setting sdpisolver objlimit to %f.\n", dval);
1917  sdpisolver->objlimit = dval;
1918  break;
1919  default:
1920  return SCIP_PARAMETERUNKNOWN;
1921  }
1922 
1923  return SCIP_OKAY;
1924 }
1925 
1928  SCIP_SDPISOLVER* sdpisolver,
1929  SCIP_SDPPARAM type,
1930  int* ival
1931  )
1932 {
1933  assert( sdpisolver != NULL );
1934 
1935  switch( type )/*lint --e{788}*/
1936  {
1937 #if 0
1938  case SCIP_SDPPAR_THREADS:
1939  *ival = sdpisolver->threads;
1940  SCIPdebugMessage("Getting sdpisolver number of threads: %d.\n", *ival);
1941  break;
1942 #endif
1943  case SCIP_SDPPAR_SDPINFO:
1944  *ival = (int) sdpisolver->sdpinfo;
1945  SCIPdebugMessage("Getting sdpisolver information output (%d).\n", *ival);
1946  break;
1947  default:
1948  return SCIP_PARAMETERUNKNOWN;
1949  }
1950 
1951  return SCIP_OKAY;
1952 }
1953 
1956  SCIP_SDPISOLVER* sdpisolver,
1957  SCIP_SDPPARAM type,
1958  int ival
1959  )
1960 {
1961  assert( sdpisolver != NULL );
1962 
1963  switch( type )/*lint --e{788}*/
1964  {
1965 #if 0
1966  case SCIP_SDPPAR_THREADS:
1967  sdpisolver->threads = ival;
1968  SCIPdebugMessage("Setting sdpisolver number of threads to %d.\n", ival);
1969  break;
1970 #endif
1971  case SCIP_SDPPAR_SDPINFO:
1972  sdpisolver->sdpinfo = (SCIP_Bool) ival;
1973  SCIPdebugMessage("Setting sdpisolver information output (%d).\n", ival);
1974  break;
1975  default:
1976  return SCIP_PARAMETERUNKNOWN;
1977  }
1978 
1979  return SCIP_OKAY;
1980 }
1981 
1987 /*
1988  * File Interface Methods
1989  */
1990 
1996  SCIP_SDPISOLVER* sdpisolver,
1997  const char* fname
1998  )
1999 {/*lint --e{715}*/
2000  SCIPdebugMessage("Not implemented yet\n");
2001  return SCIP_LPERROR;
2002 }
2003 
2006  SCIP_SDPISOLVER* sdpisolver,
2007  const char* fname
2008  )
2009 {
2010  assert( fname != NULL );
2011 
2012  sdpisolver->sdpa->writeInputSparse(const_cast<char*>(fname), const_cast<char*>("%8.3f"));
2013 
2014  return SCIP_OKAY;
2015 }
2016 
const char * SCIPsdpiSolverGetSolverName(void)
#define FEASTOLCHANGE
SCIP_RETCODE SCIPsdpiSolverSetRealpar(SCIP_SDPISOLVER *sdpisolver, SCIP_SDPPARAM type, SCIP_Real dval)
SCIP_Bool SCIPsdpiSolverIsGEMaxPenParam(SCIP_SDPISOLVER *sdpisolver, SCIP_Real val)
SCIP_RETCODE SCIPsdpiSolverFree(SCIP_SDPISOLVER **sdpisolver)
SCIP_Real SCIPsdpiSolverInfinity(SCIP_SDPISOLVER *sdpisolver)
void * SCIPsdpiSolverGetSolverPointer(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverIgnoreInstability(SCIP_SDPISOLVER *sdpisolver, SCIP_Bool *success)
SCIP_Bool SCIPsdpiSolverIsPrimalUnbounded(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverGetObjval(SCIP_SDPISOLVER *sdpisolver, SCIP_Real *objval)
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 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)
#define EPSILONCHANGE
SCIP_RETCODE SCIPsdpiSolverGetSol(SCIP_SDPISOLVER *sdpisolver, SCIP_Real *objval, SCIP_Real *dualsol, int *dualsollength)
SCIP_Bool SCIPsdpiSolverFeasibilityKnown(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverCreate(SCIP_SDPISOLVER **sdpisolver, SCIP_MESSAGEHDLR *messagehdlr, BMS_BLKMEM *blkmem)
SCIP_Bool SCIPsdpiSolverIsPrimalFeasible(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverGetIntpar(SCIP_SDPISOLVER *sdpisolver, SCIP_SDPPARAM type, int *ival)
SCIP_Bool SCIPsdpiSolverWasSolved(SCIP_SDPISOLVER *sdpisolver)
#define CHECK_IF_SOLVED_BOOL(sdpisolver)
static SCIP_Bool isFixed(SCIP_SDPISOLVER *sdpisolver, SCIP_Real lb, SCIP_Real ub)
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_Bool *feasorig)
SCIP_RETCODE SCIPsdpiSolverIncreaseCounter(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverGetSolFeasibility(SCIP_SDPISOLVER *sdpisolver, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
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 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_Real SCIPsdpiSolverMaxPenParam(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverReadSDP(SCIP_SDPISOLVER *sdpisolver, const char *fname)
struct SCIP_SDPiSolver SCIP_SDPISOLVER
Definition: sdpisolver.h:71
SCIP_Bool SCIPsdpiSolverIsIterlimExc(SCIP_SDPISOLVER *sdpisolver)
int SCIPsdpiSolverGetInternalStatus(SCIP_SDPISOLVER *sdpisolver)
enum SCIP_SDPParam SCIP_SDPPARAM
Definition: type_sdpi.h:63
SCIP_Bool SCIPsdpiSolverIsDualUnbounded(SCIP_SDPISOLVER *sdpisolver)
SCIP_Bool SCIPsdpiSolverIsTimelimExc(SCIP_SDPISOLVER *sdpisolver)
#define BMS_CALL(x)
SCIP_Bool SCIPsdpiSolverIsDualFeasible(SCIP_SDPISOLVER *sdpisolver)
SCIP_RETCODE SCIPsdpiSolverGetIterations(SCIP_SDPISOLVER *sdpisolver, int *iterations)
SCIP_Bool SCIPsdpiSolverIsConverged(SCIP_SDPISOLVER *sdpisolver)