SCIP-SDP  3.1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
relax_sdp.c
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 
40 /* #define SCIP_DEBUG*/
41 /* #define SCIP_MORE_DEBUG *//* displays complete solution for each relaxation */
42 /* #define SCIP_EVEN_MORE_DEBUG *//* shows number of deleted empty cols/rows for every relaxation and variable status &
43  * bounds as well as all constraints in the beginning */
44 /* #define SCIP_PRINT_WARMSTART *//* print initial point given for warmstarts */
45 #define SLATERSOLVED_ABSOLUTE /* uncomment this to return the absolute number of nodes for, e.g., solved fast with slater in addition to percentages */
46 
47 #include "relax_sdp.h"
48 
49 #include "assert.h" /*lint !e451*/
50 #include "string.h" /* for strcmp */
51 #include <sys/time.h> /* for timeofday */
52 
53 #include "SdpVarmapper.h"
54 #include "SdpVarfixer.h"
55 #include "sdpi/sdpi.h"
56 #include "sdpi/lapack.h"
57 #include "scipsdp/cons_sdp.h"
60 
61 /* turn off lint warnings for whole file: */
62 /*lint --e{788,818}*/
63 
64 #define RELAX_NAME "SDP"
65 #define RELAX_DESC "SDP-relaxator"
66 #define RELAX_PRIORITY 1
67 #define RELAX_FREQ 1
68 
69 /* default values for parameters: */
70 #define DEFAULT_PENALTYPARAM -1.0
71 #define DEFAULT_LAMBDASTAR -1.0
72 #define DEFAULT_MAXPENALTYPARAM -1.0
73 #define DEFAULT_WARMSTARTIPFACTOR 0.50
74 #define DEFAULT_WARMSTARTPRIMALTYPE 3
75 #define DEFAULT_WARMSTARTIPTYPE 1
76 #define DEFAULT_WARMSTARTPROJECT 2
77 #define DEFAULT_WARMSTARTPROJMINEV -1
78 #define DEFAULT_WARMSTARTPROJPDSAME TRUE
79 #define DEFAULT_WARMSTART_PREOPTIMAL_SOL FALSE
80 #define DEFAULT_WARMSTARTPREOPTGAP 1e-2
81 #define DEFAULT_WARMSTARTROUNDONLYINF FALSE
82 #define DEFAULT_SLATERCHECK 0
83 #define DEFAULT_OBJLIMIT FALSE
84 #define DEFAULT_RESOLVE TRUE
85 #define DEFAULT_TIGHTENVB TRUE
86 #define DEFAULT_SDPINFO FALSE
87 #define DEFAULT_WARMSTART FALSE
88 #define DEFAULT_DISPLAYSTAT FALSE
89 #define DEFAULT_SETTINGSRESETFREQ -1
90 #define DEFAULT_SETTINGSRESETOFS 0
91 #define DEFAULT_SDPSOLVERTHREADS -1
93 #define WARMSTART_MINVAL 0.01
94 #define WARMSTART_PROJ_MINRHSOBJ 1
95 #define WARMSTART_PROJ_FACTOR 0.1
96 #define WARMSTART_PROJ_FACTOR_LHS 10
97 #define WARMSTART_PROJ_FACTOR_PRIMAL 0.1
98 #define WARMSTART_PROJ_FACTOR_DUAL 0.1
99 #define WARMSTART_PREOPT_MIN_Z_LPVAL 0.01
102 #define TIMEOFDAY_CALL(x) do \
103  { \
104  int _errorcode_; \
105  if ( (_errorcode_ = (x)) != 0 ) \
106  { \
107  SCIPerrorMessage("Error in gettimeofday! \n"); \
108  return SCIP_ERROR; \
109  } \
110  } \
111  while( FALSE )
112 
113 /*
114  * Data structures
115  */
116 
118 struct SCIP_RelaxData
119 {
120  SCIP_SDPI* sdpi;
121  SCIP_LPI* lpi;
122  SdpVarmapper* varmapper;
124  SCIP_Real objval;
125  SCIP_Bool origsolved;
126  SCIP_Bool probingsolved;
127  long int lastsdpnode;
128  SCIP_Bool feasible;
130  SCIP_Real sdpsolvergaptol;
131  SCIP_Real sdpsolverfeastol;
132  SCIP_Real penaltyparam;
133  SCIP_Real maxpenaltyparam;
134  SCIP_Real lambdastar;
135  SCIP_Real computedlambdastar;
136  int npenaltyincr;
137  int slatercheck;
138  SCIP_Bool sdpinfo;
139  SCIP_Bool displaystat;
140  SCIP_Bool objlimit;
141  SCIP_Bool resolve;
142  SCIP_Bool tightenvb;
143  int settingsresetfreq;
144  int settingsresetofs;
145  int sdpsolverthreads;
147  int sdpcalls;
148  int sdpinterfacecalls;
149  int sdpiterations;
150  int solvedfast;
151  int solvedmedium;
152  int solvedstable;
153  int solvedpenalty;
154  int unsolved;
155  int stablewslater;
156  int unstablewslater;
157  int penaltywslater;
158  int boundedwslater;
159  int unsolvedwslater;
160  int stablenoslater;
161  int unstablenoslater;
162  int penaltynoslater;
163  int boundednoslater;
164  int unsolvednoslater;
165  int nslaterholds;
166  int nnoslater;
167  int nslatercheckfailed;
169  int npslaterholds;
170  int npnoslater;
171  int npslatercheckfailed;
172  int ndslaterholds;
173  int ndnoslater;
174  int ndslatercheckfailed;
175  int nslaterinfeasible;
176  int stableinfeasible;
177  int unstableinfeasible;
178  int penaltyinfeasible;
179  int boundedinfeasible;
180  int unsolvedinfeasible;
181  int roundingprobinf;
182  int primalroundfails;
183  int dualroundfails;
184  int roundstartsuccess;
185  int roundingoptimal;
186  int roundingcutoff;
187  SCIP_Real roundingprobtime;
189  SCIP_Bool warmstart;
190  SCIP_Real warmstartipfactor;
191  int warmstartprimaltype;
193  int warmstartproject;
194  SCIP_Real warmstartpmevprimalpar;
195  SCIP_Real warmstartpmevdualpar;
196  SCIP_Real warmstartprojminevprimal;
197  SCIP_Real warmstartprojminevdual;
198  SCIP_Bool warmstartprojpdsame;
199  int warmstartiptype;
200  SCIP_Bool warmstartpreoptsol;
201  SCIP_Real warmstartpreoptgap;
202  SCIP_Bool warmstartroundonlyinf;
203  int nblocks;
204  SCIP_Bool ipXexists;
205  int* ipXnblocknonz;
207  int** ipXrow;
208  int** ipXcol;
209  SCIP_Real** ipXval;
210  SCIP_Bool ipZexists;
211  SCIP_SOL* ipy;
212  int* ipZnblocknonz;
214  int** ipZrow;
215  int** ipZcol;
216  SCIP_Real** ipZval;
217 };
218 
220 static
221 SCIP_RETCODE expandSparseMatrix(
222  int nnonz,
223  int blocksize,
224  int* row,
225  int* col,
226  SCIP_Real* val,
227  SCIP_Real* fullmat
228  )
229 {
230  int i;
231  int matrixsize;
232 
233  assert( nnonz >= 0 );
234  assert( row != NULL );
235  assert( col != NULL );
236  assert( val != NULL );
237  assert( fullmat != NULL );
238 
239  matrixsize = blocksize * blocksize;
240 
241  /* initialize matrix with zeros */
242  for (i = 0; i < matrixsize; i++)
243  fullmat[i] = 0.0;
244 
245  for (i = 0; i < nnonz; i++)
246  {
247  assert( row[i] * blocksize + col[i] <= matrixsize );
248  fullmat[row[i] * blocksize + col[i]] = val[i];
249  assert( col[i] * blocksize + row[i] <= matrixsize );
250  fullmat[col[i] * blocksize + row[i]] = val[i];
251  }
252 
253  return SCIP_OKAY;
254 }
255 
257 static
259  int blocksize, /* number of rows and columns */
260  SCIP_Real* matrix, /* matrix entries given as blocksize^2 array */
261  SCIP_Real* scale /* array of length blocksize to multiply the columns of matrix with */
262  )
263 {
264  int r;
265  int c;
266 
267  assert( blocksize >= 0 );
268  assert( matrix != NULL );
269  assert( scale != NULL );
270 
271  for (r = 0; r < blocksize; r++)
272  {
273  for (c = 0; c < blocksize; c++)
274  {
275  matrix[r * blocksize + c] *= scale[c];
276  }
277  }
278 
279  return SCIP_OKAY;
280 }
281 
283 static
285  SCIP* scip,
286  SCIP_SDPI* sdpi,
287  SdpVarmapper* varmapper,
288  SCIP_Bool primalobj,
289  SCIP_Bool boundprimal
290  )
291 {
292  SCIP_CONSHDLR* conshdlr;
293  const char* conshdlrname;
294  SCIP_CONS** conss;
295  SCIP_VAR** blockvars;
296  SCIP_VAR** vars;
297  SCIP_Real*** val;
298  SCIP_Real** constval;
299  SCIP_Real* obj;
300  SCIP_Real* lb;
301  SCIP_Real* ub;
302  SCIP_Real param;
303  int*** row;
304  int*** col;
305  int** nblockvarnonz;
306  int** constrow;
307  int** constcol;
308  int** sdpvar;
309  int* sdpblocksizes;
310  int* nblockvars;
311  int* nconstblocknonz;
312  int constnnonzcounter;
313  int blocknnonz;
314  int sdpconstnnonz;
315  int sdpnnonz;
316  int nsdpblocks;
317  int constlength;
318  int nvars;
319  int nvarspen;
320  int nconss;
321  int ind;
322  int i;
323  int j;
324 
325  SCIP_CALL( SCIPgetRealParam(scip, "relaxing/SDP/sdpsolvergaptol", &param) );
326 
327  SCIPdebugMessage("Putting SDP Data in general SDP interface!\n");
328 
329  assert( scip != NULL );
330  assert( sdpi != NULL );
331  assert( varmapper != NULL );
332 
333  vars = SCIPgetVars(scip);
334  nvars = SCIPgetNVars(scip);
335  nvarspen = boundprimal ? nvars + 1 : nvars; /* if the primal should be bounded, an additional penalty variable is added to the dual */
336 
337  /* prepare arrays of objective values and bounds */
338  SCIP_CALL( SCIPallocBufferArray(scip, &obj, nvarspen) );
339  SCIP_CALL( SCIPallocBufferArray(scip, &lb, nvarspen) );
340  SCIP_CALL( SCIPallocBufferArray(scip, &ub, nvarspen) );
341 
342  for (i = 0; i < nvars; i++)
343  {
344  obj[i] = SCIPvarGetObj(vars[i]);
345  lb[i] = SCIPvarGetLbLocal(vars[i]);
346  ub[i] = SCIPvarGetUbLocal(vars[i]);
347  }
348  if ( boundprimal )
349  {
350  obj[nvars] = 1.0; /* this objective coefficient together with lb = 0 and the identity matrix leads to constraint Tr(X) <= 1 */
351  lb[nvars] = 0.0;
352  ub[nvars] = SCIPinfinity(scip);
353  }
354 
355  nconss = SCIPgetNConss(scip);
356  conss = SCIPgetConss(scip);
357 
358  /* count the number of sdpblocks and compute the number of nonzeros */
359  nsdpblocks = 0;
360  sdpnnonz = 0;
361  sdpconstnnonz = 0;
362 
363  for (i = 0; i < nconss; i++)
364  {
365  conshdlr = SCIPconsGetHdlr(conss[i]);
366  assert( conshdlr != NULL );
367 
368  conshdlrname = SCIPconshdlrGetName(conshdlr);
369 
370 #ifdef SCIP_EVEN_MORE_DEBUG
371  SCIP_CALL( SCIPprintCons(scip, conss[i], NULL) );
372  SCIPinfoMessage(scip, NULL, "\n");
373 #endif
374 
375  if ( strcmp(conshdlrname, "SDP") == 0 )
376  {
377  nsdpblocks++;
378 
379  SCIP_CALL( SCIPconsSdpGetNNonz(scip, conss[i], &blocknnonz, &constnnonzcounter) );
380  sdpnnonz += blocknnonz;
381  sdpconstnnonz += constnnonzcounter;
382  }
383  }
384 
385  /* create the sdp- and sdpconst-arrays */
386  SCIP_CALL( SCIPallocBufferArray(scip, &sdpblocksizes, nsdpblocks) );
387  SCIP_CALL( SCIPallocBufferArray(scip, &nblockvarnonz, nsdpblocks) );
388  SCIP_CALL( SCIPallocBufferArray(scip, &nconstblocknonz, nsdpblocks) );
389  SCIP_CALL( SCIPallocBufferArray(scip, &col, nsdpblocks) );
390  SCIP_CALL( SCIPallocBufferArray(scip, &row, nsdpblocks) );
391  SCIP_CALL( SCIPallocBufferArray(scip, &val, nsdpblocks) );
392  SCIP_CALL( SCIPallocBufferArray(scip, &constcol, nsdpblocks) );
393  SCIP_CALL( SCIPallocBufferArray(scip, &constrow, nsdpblocks) );
394  SCIP_CALL( SCIPallocBufferArray(scip, &constval, nsdpblocks) );
395  SCIP_CALL( SCIPallocBufferArray(scip, &nblockvars, nsdpblocks) );
396  SCIP_CALL( SCIPallocBufferArray(scip, &sdpvar, nsdpblocks) );
397 
398  for (i = 0; i < nsdpblocks; i++)
399  {
400  SCIP_CALL( SCIPallocBufferArray(scip, &(nblockvarnonz[i]), nvarspen) );
401  SCIP_CALL( SCIPallocBufferArray(scip, &col[i], nvarspen) );
402  SCIP_CALL( SCIPallocBufferArray(scip, &row[i], nvarspen) );
403  SCIP_CALL( SCIPallocBufferArray(scip, &val[i], nvarspen) );
404  }
405 
406  /* get the SDP-data */
407  ind = 0; /* index of the current sdp block in the complete sdp */
408  SCIP_CALL( SCIPallocBufferArray(scip, &blockvars, nvars) );
409 
410  for (i = 0; i < nconss; i++)
411  {
412  conshdlr = SCIPconsGetHdlr(conss[i]);
413  assert( conshdlr != NULL );
414 
415  conshdlrname = SCIPconshdlrGetName(conshdlr);
416 
417  if ( strcmp(conshdlrname, "SDP") == 0 )
418  {
419  assert( ind < nsdpblocks );
420 
421  /* allocate memory for the constant nonzeros */
422  SCIP_CALL( SCIPconsSdpGetNNonz(scip, conss[i], NULL, &constlength) );
423  nconstblocknonz[ind] = constlength;
424  SCIP_CALL( SCIPallocBufferArray(scip, &(constcol[ind]), constlength) );
425  SCIP_CALL( SCIPallocBufferArray(scip, &(constrow[ind]), constlength) );
426  SCIP_CALL( SCIPallocBufferArray(scip, &(constval[ind]), constlength) );
427 
428  /* get the data */
429  SCIP_CALL( SCIPconsSdpGetData(scip, conss[i], &nblockvars[ind], &blocknnonz, &sdpblocksizes[ind], &nvars, nblockvarnonz[ind], col[ind],
430  row[ind], val[ind], blockvars, &nconstblocknonz[ind], constcol[ind], constrow[ind], constval[ind]) );
431 
432  /* nvars and nconstblocknonz[ind] would have been overwritten if the space in the given arrays hadn't been sufficient */
433  assert( nvars == SCIPgetNVars(scip) );
434  assert( nconstblocknonz[ind] <= constlength );
435 
436  SCIP_CALL( SCIPallocBufferArray(scip, &(sdpvar[ind]), boundprimal ? nblockvars[ind] + 1 : nblockvars[ind]) );
437 
438  /* get global variable indices */
439  for (j = 0; j < nblockvars[ind]; j++)
440  sdpvar[ind][j] = SCIPsdpVarmapperGetSdpIndex(varmapper, blockvars[j]);
441 
442  if ( boundprimal )
443  {
444  /* penalty variable is added as final variable to bound the primal */
445  sdpvar[ind][nblockvars[ind]] = SCIPsdpVarmapperGetNVars(varmapper);
446  nblockvarnonz[ind][nblockvars[ind]] = sdpblocksizes[ind];
447 
448  /* add identity matrix times penalty variable */
449  SCIP_CALL( SCIPallocBufferArray(scip, &col[ind][nblockvars[ind]], sdpblocksizes[ind]) );
450  SCIP_CALL( SCIPallocBufferArray(scip, &row[ind][nblockvars[ind]], sdpblocksizes[ind]) );
451  SCIP_CALL( SCIPallocBufferArray(scip, &val[ind][nblockvars[ind]], sdpblocksizes[ind]) );
452 
453  for (j = 0; j < sdpblocksizes[ind]; j++)
454  {
455  col[ind][nblockvars[ind]][j] = j;
456  row[ind][nblockvars[ind]][j] = j;
457  val[ind][nblockvars[ind]][j] = 1.0;
458  }
459  nblockvars[ind]++;
460  }
461 
462  ind++;
463  }
464  }
465 
466  /* free the memory that is no longer needed */
467  SCIPfreeBufferArray(scip, &blockvars);
468 
469  /* load data into SDPI */
470  if ( primalobj )
471  {
472  SCIP_CALL( SCIPsdpiLoadSDP(sdpi, nvarspen, obj, lb, ub, nsdpblocks, sdpblocksizes, nblockvars, sdpconstnnonz, nconstblocknonz, constrow,
473  constcol, constval, sdpnnonz, nblockvarnonz, sdpvar, row, col, val, 0,
474  NULL, NULL, 0, NULL, NULL, NULL) ); /* insert the SDP part, add an empty LP part */
475  }
476  else
477  {
478  /* overwrite nconstblocknonz */
479  for (i = 0; i < nsdpblocks; i++)
480  nconstblocknonz[i] = 0;
481 
482  SCIP_CALL( SCIPsdpiLoadSDP(sdpi, nvarspen, obj, lb, ub, nsdpblocks, sdpblocksizes, nblockvars, 0, nconstblocknonz, NULL,
483  NULL, NULL, sdpnnonz, nblockvarnonz, sdpvar, row, col, val, 0,
484  NULL, NULL, 0, NULL, NULL, NULL) ); /* insert the SDP part, add an empty LP part */
485  }
486 
487 
488  /* free the remaining memory */
489  for (i = 0; i < nsdpblocks; i++)
490  {
491  if ( boundprimal )
492  {
493  SCIPfreeBufferArrayNull(scip, &val[i][nblockvars[i] - 1]);
494  SCIPfreeBufferArrayNull(scip, &row[i][nblockvars[i] - 1]);
495  SCIPfreeBufferArrayNull(scip, &col[i][nblockvars[i] - 1]);
496  }
497  SCIPfreeBufferArrayNull(scip, &(sdpvar[i]));
498  SCIPfreeBufferArrayNull(scip, &val[i]);
499  SCIPfreeBufferArrayNull(scip, &row[i]);
500  SCIPfreeBufferArrayNull(scip, &col[i]);
501  SCIPfreeBufferArrayNull(scip, &(nblockvarnonz[i]));
502  SCIPfreeBufferArrayNull(scip, &(constval[i]));
503  SCIPfreeBufferArrayNull(scip, &(constrow[i]));
504  SCIPfreeBufferArrayNull(scip, &(constcol[i]));
505  }
506 
507  SCIPfreeBufferArrayNull(scip, &sdpvar);
508  SCIPfreeBufferArrayNull(scip, &nblockvars);
509  SCIPfreeBufferArrayNull(scip, &constval);
510  SCIPfreeBufferArrayNull(scip, &constrow);
511  SCIPfreeBufferArrayNull(scip, &constcol);
512  SCIPfreeBufferArrayNull(scip, &val);
513  SCIPfreeBufferArrayNull(scip, &row);
514  SCIPfreeBufferArrayNull(scip, &col);
515  SCIPfreeBufferArrayNull(scip, &nconstblocknonz);
516  SCIPfreeBufferArrayNull(scip, &nblockvarnonz);
517  SCIPfreeBufferArrayNull(scip, &sdpblocksizes);
518  SCIPfreeBufferArray(scip, &ub);
519  SCIPfreeBufferArray(scip, &lb);
520  SCIPfreeBufferArray(scip, &obj);
521 
522  return SCIP_OKAY;
523 }
524 
526 static
527 SCIP_RETCODE putLpDataInInterface(
528  SCIP* scip,
529  SCIP_SDPI* sdpi,
530  SdpVarmapper* varmapper,
531  SCIP_Bool primalobj,
532  SCIP_Bool dualobj
533  )
534 {
535  SCIP_VAR** vars;
536  SCIP_COL** rowcols;
537  SCIP_ROW** rows;
538  SCIP_Bool tightenvb;
539  SCIP_Real* rowvals;
540  SCIP_Real* lhs;
541  SCIP_Real* rhs;
542  SCIP_Real* obj;
543  SCIP_Real* lb;
544  SCIP_Real* ub;
545  SCIP_Real* val;
546  SCIP_Real sciplhs;
547  SCIP_Real sciprhs;
548  int* inds;
549  int* objinds;
550  int* rowind;
551  int* colind;
552  int nrowssdpi;
553  int nrows;
554  int rownnonz;
555  int nvars;
556  int nconss;
557  int scipnnonz;
558  int nnonz;
559  int i;
560  int j;
561 
562  assert( scip != NULL );
563  assert( sdpi != NULL );
564  assert( varmapper != NULL );
565 
566  nvars = SCIPgetNVars(scip);
567  assert( nvars > 0 );
568 
569  SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
570  SCIP_CALL( SCIPgetBoolParam(scip, "relaxing/SDP/tightenvb", &tightenvb) );
571 
572  SCIPdebugMessage("inserting %d LPRows into the interface.\n", nrows);
573 
574  /* compute the total number of LP nonzeroes in SCIP */
575  scipnnonz = 0;
576  for (i = 0; i < nrows; i++)
577  {
578  assert( rows[i] != NULL );
579  scipnnonz += SCIProwGetNNonz(rows[i]);
580  }
581 
582  /* allocate memory */
583  SCIP_CALL( SCIPallocBufferArray(scip, &lhs, nrows) );
584  SCIP_CALL( SCIPallocBufferArray(scip, &rhs, nrows) );
585  SCIP_CALL( SCIPallocBufferArray(scip, &rowind, scipnnonz) );
586  SCIP_CALL( SCIPallocBufferArray(scip, &colind, scipnnonz) );
587  SCIP_CALL( SCIPallocBufferArray(scip, &val, scipnnonz) );
588 
589  /* insert the nonzeroes */
590  nnonz = 0; /* this is recomputed for the sdpi, because of the possible duplication of non-zeroes for lhs and rhs */
591  nconss = 0; /* this will be increased for each finite lhs and rhs */
592 
593  for (i = 0; i < nrows; i++)
594  {
595  SCIP_ROW* row;
596  SCIP_Bool tightened = FALSE;
597  SCIP_Real tightenedval = 0.0;
598  SCIP_Bool swapped = FALSE;
599 
600  row = rows[i];
601  assert( row != 0 );
602  rownnonz = SCIProwGetNNonz(row);
603 
604  rowvals = SCIProwGetVals(row);
605  rowcols = SCIProwGetCols(row);
606  sciplhs = SCIProwGetLhs(row) - SCIProwGetConstant(row);
607  sciprhs = SCIProwGetRhs(row) - SCIProwGetConstant(row);
608 
609  /* check whether we have a variable bound and can strenghten the big-M */
610  if ( tightenvb && rownnonz == 2 && (SCIPisZero(scip, sciplhs) || SCIPisZero(scip, sciprhs) ) )
611  {
612  SCIP_VAR* var1;
613  SCIP_VAR* var2;
614  SCIP_Real val1;
615  SCIP_Real val2;
616 
617  val1 = rowvals[0];
618  val2 = rowvals[1];
619 
620  assert( rowcols[0] != NULL );
621  assert( rowcols[1] != NULL );
622  var1 = SCIPcolGetVar(rowcols[0]);
623  var2 = SCIPcolGetVar(rowcols[1]);
624  assert( var1 != NULL );
625  assert( var2 != NULL );
626 
627  /* check that variables are not locally fixed */
628  if ( ! SCIPisEQ(scip, SCIPvarGetLbLocal(var1), SCIPvarGetUbLocal(var1)) && ! SCIPisEQ(scip, SCIPvarGetLbLocal(var2), SCIPvarGetUbLocal(var2)) )
629  {
630  /* one coefficient must be 1 and the other negative */
631  if ( (SCIPisEQ(scip, val1, 1.0) || SCIPisEQ(scip, val2, 1.0)) && ( SCIPisNegative(scip, val1) || SCIPisNegative(scip, val2) ) )
632  {
633  /* We want x - a z <= 0 or x - a z >= 0, where var1 = x and var2 = z; possibly swap variables otherwise */
634  if ( ! SCIPisEQ(scip, val1, 1.0) || ! SCIPisNegative(scip, val2) )
635  {
636  SCIPswapPointers((void**) &var1, (void**) &var2);
637 
638  val2 = val1;
639  swapped = TRUE;
640  }
641 
642  /* var2 needs to be binary */
643  if ( SCIPvarIsBinary(var2) )
644  {
645  if ( SCIPisZero(scip, sciprhs) )
646  {
647  if ( SCIPisLT(scip, SCIPvarGetUbLocal(var1), REALABS(val2)) )
648  {
649  SCIPdebugMessage("Big-M in %s changed from %f to %f\n", SCIProwGetName(row), REALABS(val2), SCIPvarGetUbLocal(var1));
650 
651  tightened = TRUE;
652  tightenedval = -SCIPvarGetUbLocal(var1); /* negative sign because the coefficient needs to be negative */
653  }
654  }
655 
656  if ( SCIPisZero(scip, sciplhs) )
657  {
658  if ( SCIPisGT(scip, SCIPvarGetLbLocal(var1), REALABS(val2)) )
659  {
660  SCIPdebugMessage("Big-M in %s changed from %f to %f\n", SCIProwGetName(row), REALABS(val2), SCIPvarGetLbLocal(var1));
661 
662  tightened = TRUE;
663  tightenedval = -SCIPvarGetUbLocal(var1); /* negative sign because the coefficient needs to be negative */
664  }
665  }
666  }
667  }
668  }
669  }
670 
671  for (j = 0; j < rownnonz; j++)
672  {
673  /* if the Big-M was tightened, we use the new value (the position where this new value is used is dependant on wheter we needed to swap) */
674  if ( tightened && ( (swapped && (j == 0)) || ((! swapped) && (j == 1)) ) ) /* use the tightened value */
675  {
676  if ( SCIPisFeasGT(scip, REALABS(tightenedval), 0.0) )
677  {
678  assert( SCIPcolGetVar(rowcols[j]) != 0 );
679  colind[nnonz] = SCIPsdpVarmapperGetSdpIndex(varmapper, SCIPcolGetVar(rowcols[j]));
680  rowind[nnonz] = nconss;
681  val[nnonz] = tightenedval;
682  nnonz++;
683  }
684  }
685  else if ( SCIPisFeasGT(scip, REALABS(rowvals[j]), 0.0))
686  {
687  assert( SCIPcolGetVar(rowcols[j]) != 0 );
688  colind[nnonz] = SCIPsdpVarmapperGetSdpIndex(varmapper, SCIPcolGetVar(rowcols[j]));
689  rowind[nnonz] = nconss;
690  val[nnonz] = rowvals[j];
691  nnonz++;
692  }
693  }
694  lhs[nconss] = primalobj ? sciplhs : (SCIPisInfinity(scip, -sciplhs) ? -sciplhs : 0.0);
695  rhs[nconss] = primalobj ? sciprhs : (SCIPisInfinity(scip, sciprhs) ? sciprhs : 0.0);
696  nconss++;
697  }
698 
699  /* delete the old LP-block from the sdpi */
700  SCIP_CALL( SCIPsdpiGetNLPRows(sdpi, &nrowssdpi) );
701  if ( nrowssdpi > 0 )
702  {
703  SCIP_CALL( SCIPsdpiDelLPRows(sdpi, 0, nrowssdpi - 1) );
704  }
705 
706  /* add the LP-block to the sdpi */
707  SCIP_CALL( SCIPsdpiAddLPRows(sdpi, nconss, lhs, rhs, nnonz, (const int*)rowind, (const int*)colind, val) );
708 
709  /* free the remaining arrays */
710  SCIPfreeBufferArray(scip, &val);
711  SCIPfreeBufferArray(scip, &colind);
712  SCIPfreeBufferArray(scip, &rowind);
713  SCIPfreeBufferArray(scip, &rhs);
714  SCIPfreeBufferArray(scip, &lhs);
715 
716  /* update bounds */
717 
718  /* get the variables */
719  vars = SCIPgetVars(scip);
720  assert( vars != NULL );
721 
722  /* prepare arrays of bounds */
723  SCIP_CALL( SCIPallocBufferArray(scip, &lb, nvars) );
724  SCIP_CALL( SCIPallocBufferArray(scip, &ub, nvars) );
725  SCIP_CALL( SCIPallocBufferArray(scip, &inds, nvars) );
726  SCIP_CALL( SCIPallocBufferArray(scip, &obj, nvars) );
727  SCIP_CALL( SCIPallocBufferArray(scip, &objinds, nvars) );
728 
729  /* get new bounds and objective coefficients */
730  for (i = 0; i < nvars; i++)
731  {
732  assert( vars[i] != NULL );
733  lb[i] = primalobj ? SCIPvarGetLbLocal(vars[i]) : (SCIPisInfinity(scip, -SCIPvarGetLbLocal(vars[i])) ? SCIPvarGetLbLocal(vars[i]) : 0.0);
734  ub[i] = primalobj ? SCIPvarGetUbLocal(vars[i]) : (SCIPisInfinity(scip, SCIPvarGetUbLocal(vars[i])) ? SCIPvarGetUbLocal(vars[i]) : 0.0);
735  inds[i] = i; /* we want to change all bounds, so all indices are included in inds */
736  obj[i] = dualobj ? SCIPvarGetObj(vars[i]) : 0.0;
737  objinds[i] = i;
738  }
739 
740  /* inform interface */
741  SCIP_CALL( SCIPsdpiChgBounds(sdpi, nvars, inds, lb, ub) );
742  SCIP_CALL( SCIPsdpiChgObj(sdpi, nvars, objinds, obj) );
743 
744  /* free the bounds-arrays */
745  SCIPfreeBufferArray(scip, &objinds);
746  SCIPfreeBufferArray(scip, &obj);
747  SCIPfreeBufferArray(scip, &inds);
748  SCIPfreeBufferArray(scip, &ub);
749  SCIPfreeBufferArray(scip, &lb);
750 
751  return SCIP_OKAY;
752 }
753 
755 static
756 SCIP_RETCODE calcRelax(
757  SCIP* scip,
758  SCIP_RELAXDATA* relaxdata,
759  SCIP_RESULT* result,
760  SCIP_Real* lowerbound
761  )
762 {
763  char saveconsname[SCIP_MAXSTRLEN];
764  SCIP_SDPSOLVERSETTING startsetting;
765  SCIP_SDPSOLVERSETTING usedsetting;
766  SCIP_CONS* savedsetting;
767  SCIP_CONS** conss;
768  SCIP_VAR** vars;
769  SCIP_SDPI* sdpi;
770  SCIP_Bool rootnode;
771  SCIP_Bool enforceslater;
772  SCIP_Real timelimit;
773  SCIP_Real objforscip;
774  SCIP_Real* solforscip;
775  SCIP_SDPSLATERSETTING slatersetting;
776  SCIP_SDPSLATER primalslater;
777  SCIP_SDPSLATER dualslater;
778  int naddediters;
779  int naddedsdpcalls;
780  int nblocks;
781  int nvars;
782  int b;
783  int i;
784  int v;
785 
786  SCIPdebugMessage("calcRelax called\n");
787 
788  assert( scip != NULL );
789  assert( relaxdata != NULL );
790  assert( result != NULL );
791  assert( lowerbound != NULL );
792 
793  nvars = SCIPgetNVars(scip);
794  assert( nvars > 0 );
795  vars = SCIPgetVars (scip);
796 
797  sdpi = relaxdata->sdpi;
798  assert( sdpi != NULL );
799 
800  if ( relaxdata->objlimit )
801  {
802  /* set the objective limit */
803  assert( SCIPgetUpperbound(scip) > -SCIPsdpiInfinity(sdpi) );
804  SCIP_CALL( SCIPsdpiSetRealpar(sdpi, SCIP_SDPPAR_OBJLIMIT, SCIPgetUpperbound(scip)) );
805  }
806  /* if this is the root node and we cannot solve the problem, we want to check for the Slater condition independent from the SCIP parameter */
807  rootnode = ! SCIPnodeGetParent(SCIPgetCurrentNode(scip));
808 
809  /* find settings to use for this relaxation */
810  if ( rootnode || (SCIPnodeGetDepth(SCIPgetCurrentNode(scip)) == relaxdata->settingsresetofs) ||
811  ( relaxdata->settingsresetfreq > 0 && ((SCIPnodeGetDepth(SCIPgetCurrentNode(scip)) - relaxdata->settingsresetofs) % relaxdata->settingsresetfreq == 0)) ||
812  (strcmp(SCIPsdpiGetSolverName(), "DSDP") == 0) || (strstr(SCIPsdpiGetSolverName(), "Mosek") != NULL))
813  {
814  startsetting = SCIP_SDPSOLVERSETTING_UNSOLVED; /* in the root node we have no information, at each multiple of resetfreq we reset */
815  }
816  else
817  {
818  SCIP_CONSHDLR* conshdlr;
819  int parentconsind;
820 
821  /* get constraint handler */
822  conshdlr = SCIPfindConshdlr(scip, "Savedsdpsettings");
823  if ( conshdlr == NULL )
824  {
825  SCIPerrorMessage("Savedsdpsettings constraint handler not found!\n");
826  return SCIP_PLUGINNOTFOUND;
827  }
828 
829  /* get startsettings of parent node, usually it will be the last active constraint of the corresponding constraint handler, so we iterate from
830  * the end of the list until we find the correct one */
831  conss = SCIPconshdlrGetConss(conshdlr);
832  parentconsind = SCIPconshdlrGetNActiveConss(conshdlr) - 1;
833  (void) SCIPsnprintf(saveconsname, SCIP_MAXSTRLEN, "savedsettings_node_%d", SCIPnodeGetNumber(SCIPnodeGetParent(SCIPgetCurrentNode(scip))));
834 
835  while ( parentconsind >= 0 && strcmp(saveconsname, SCIPconsGetName(conss[parentconsind])) )
836  parentconsind--;
837  if ( parentconsind >= 0 )
838  startsetting = SCIPconsSavedsdpsettingsGetSettings(scip, conss[parentconsind]);
839  else
840  {
841  SCIPdebugMessage("Startsetting from parent node not found, restarting with fastest settings!\n");
842  startsetting = SCIP_SDPSOLVERSETTING_UNSOLVED;
843  }
844  }
845 
846  /* set time limit */
847  SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
848  if ( ! SCIPisInfinity(scip, timelimit) )
849  {
850  timelimit -= SCIPgetSolvingTime(scip);
851  if ( timelimit <= 0.0 )
852  {
853  *result = SCIP_DIDNOTRUN;
854  return SCIP_OKAY;
855  }
856  }
857 
858  /* if no dual bound is known (we are in the root node and not only repropagating), we will have to abort, so we want
859  * to check the Slater condition in this case */
860  enforceslater = SCIPisInfinity(scip, -1 * SCIPnodeGetLowerbound(SCIPgetCurrentNode(scip)));
861 
862  /* solve the problem (using warmstarts if parameter is true and we are not in the root node and all neccessary data is available) */
863  if ( ( ! SCIPnodeGetParent(SCIPgetCurrentNode(scip))) || ( ! relaxdata->warmstart ) || ((relaxdata->warmstartiptype == 2) &&
864  SCIPisGT(scip, relaxdata->warmstartipfactor, 0.0) && ((SCIPsdpiDoesWarmstartNeedPrimal() && ! relaxdata->ipXexists) || (! relaxdata->ipZexists))) )
865  {
866  SCIP_CALL(SCIPsdpiSolve(sdpi, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, startsetting, enforceslater, timelimit));
867  }
868  else if ( relaxdata->warmstart && (relaxdata->warmstartprimaltype != 2) && (relaxdata->warmstartiptype == 2) && SCIPisEQ(scip, relaxdata->warmstartipfactor, 1.0) )
869  {
870  SCIP_Real* ipy;
871 
872  /* if we warmstart with the analytic center, we give a pointer to the arrays in relaxdata (just the sol needs to be transformed to a vector first) */
873 
874  SCIP_CALL( SCIPallocBufferArray(scip, &ipy, nvars) );
875  for (v = 0; v < nvars; v++)
876  ipy[v] = SCIPgetSolVal(scip, relaxdata->ipy, SCIPsdpVarmapperGetSCIPvar(relaxdata->varmapper, v));
877 
878 #ifdef SCIP_PRINT_WARMSTART
879  SCIPdebugMessage("warmstart using the following analytic centers:\n");
880  for (v = 0; v < nvars; v++)
881  SCIPdebugMessage("y[%d] = %f\n", v, ipy[v]);
883  {
884  for (b = 0; b < relaxdata->nblocks; b++)
885  {
886  SCIPdebugMessage("dual block %d\n", b);
887  for (i = 0; i < relaxdata->ipZnblocknonz[b]; i++)
888  {
889  SCIPdebugMessage("Z(%d,%d)=%f\n", relaxdata->ipZrow[b][i], relaxdata->ipZcol[b][i], relaxdata->ipZval[b][i]);
890  }
891  }
892  for (b = 0; b < relaxdata->nblocks; b++)
893  {
894  SCIPdebugMessage("primal block %d\n", b);
895  for (i = 0; i < relaxdata->ipXnblocknonz[b]; i++)
896  {
897  SCIPdebugMessage("X(%d,%d)=%f\n", relaxdata->ipXrow[b][i], relaxdata->ipXcol[b][i], relaxdata->ipXval[b][i]);
898  }
899  }
900  }
901 #endif
902 
903  SCIP_CALL(SCIPsdpiSolve(sdpi, ipy, relaxdata->ipZnblocknonz, relaxdata->ipZrow, relaxdata->ipZcol, relaxdata->ipZval, relaxdata->ipXnblocknonz,
904  relaxdata->ipXrow, relaxdata->ipXcol, relaxdata->ipXval, startsetting, enforceslater, timelimit));
905 
906  SCIPfreeBufferArray(scip, &ipy);
907  }
908  else
909  {
910  SCIP_CONSHDLR* conshdlr;
911  SCIP_SOL* dualsol;
912  SCIP_Real* starty = NULL;
913  int* startZnblocknonz = NULL;
914  int** startZrow = NULL;
915  int** startZcol = NULL;
916  SCIP_Real** startZval = NULL;
917  int* startXnblocknonz = NULL;
918  int** startXrow = NULL;
919  int** startXcol = NULL;
920  SCIP_Real** startXval = NULL;
921  int parentconsind;
922  SCIP_Longint parentnodenumber;
923  SCIP_VAR* var;
924 
925  /* find starting solution as optimal solution of parent node */
926 
927  /* get constraint handler */
928  conshdlr = SCIPfindConshdlr(scip, "Savesdpsol");
929  if ( conshdlr == NULL )
930  {
931  SCIPerrorMessage("Savesdpsol constraint handler not found\n");
932  return SCIP_PLUGINNOTFOUND;
933  }
934 
935  /* get saveconstraint of parent node, usually it will be the last active constraint of the corresponding constraint handler, so we iterate from
936  * the end of the list until we find the correct one */
937  conss = SCIPconshdlrGetConss(conshdlr);
938  parentconsind = SCIPconshdlrGetNActiveConss(conshdlr) - 1;
939  parentnodenumber = SCIPnodeGetNumber(SCIPnodeGetParent(SCIPgetCurrentNode(scip)));
940 
941  while ( parentconsind >= 0 && SCIPconsSavesdpsolGetNodeIndex(scip, conss[parentconsind]) != parentnodenumber)
942  parentconsind--;
943 
944  /* if there are no savesdpsol constraints (e.g. because the parent node couldn't be solved successfully), solve
945  * without warmstart
946  */
947  if ( parentconsind < 0 )
948  {
949  SCIPdebugMessage("Starting SDP-Solving from scratch since no warmstart information available for node %lld\n", parentnodenumber);
950  SCIP_CALL(SCIPsdpiSolve(sdpi, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, startsetting, enforceslater, timelimit));
951  }
952  else
953  {
954  SCIPdebugMessage("Using warmstartinformation from node %lld\n", parentnodenumber);
955 
956  /* get solution */
957  dualsol = SCIPconsSavesdpsolGetDualVector(scip, conss[parentconsind]);
958 
959  /* allocate memory */
960  SCIP_CALL( SCIPallocBufferArray(scip, &starty, nvars) );
961 
962  /* transform solution to vector for SDPI and check if it is still feasible for the variable bounds, otherwise round it */
963  for (v = 0; v < nvars; v++)
964  {
965  var = SCIPsdpVarmapperGetSCIPvar(relaxdata->varmapper, v);
966  starty[v] = SCIPgetSolVal(scip, dualsol, var);
967  /* correct solution to new bounds unless warmstartproject == 1 */
968  if (SCIPisLT(scip, starty[v], SCIPvarGetLbLocal(var)) && (relaxdata->warmstartproject == 2 || relaxdata->warmstartproject == 3 || relaxdata->warmstartproject == 4))
969  {
970  starty[v] = SCIPvarGetLbLocal(var);
971  /* update solution (used to compute dual matrix) according to new bounds */
972  SCIP_CALL( SCIPsetSolVal(scip, dualsol, var, SCIPvarGetLbLocal(var)) );
973  }
974  else if (SCIPisGT(scip, starty[v], SCIPvarGetUbLocal(var)) && (relaxdata->warmstartproject == 2 || relaxdata->warmstartproject == 3 || relaxdata->warmstartproject == 4))
975  {
976  starty[v] = SCIPvarGetUbLocal(var);
977  /* update solution (used to compute dual matrix) according to new bounds */
978  SCIP_CALL( SCIPsetSolVal(scip, dualsol, var, SCIPvarGetUbLocal(var)) );
979  }
980 
981  /* if we take a convex combination, adjust y accordingly (if we use rounding problems, we recompute y later anyways) */
982  if ( SCIPisGT(scip, relaxdata->warmstartipfactor, 0.0) && relaxdata->warmstartproject != 4 )
983  {
984  if ( relaxdata->warmstartiptype == 1 )
985  {
986  /* we take a convex combination with 0, so we just scale */
987  starty[v] *= 1 - relaxdata->warmstartipfactor;
988  }
989  else if ( relaxdata->warmstartiptype == 2 )
990  {
991  /* take the convex combination with the saved analytic center */
992  starty[v] = (1 - relaxdata->warmstartipfactor) * starty[v] + relaxdata->warmstartipfactor * SCIPgetSolVal(scip, relaxdata->ipy, var);
993  }
994  }
995  }
996 
997  /* if the SDP-solver needs the primal solution (and the dual matrix) in addition to the dual vector... */
999  {
1000  SCIP_CONSHDLR* sdpconshdlr;
1001  SCIP_CONS** sdpblocks;
1002  SCIP_COL** rowcols;
1003  SCIP_ROW** rows;
1004  int blocksize;
1005  int nrows;
1006  int rownnonz;
1007  int r;
1008  SCIP_Real maxprimalentry = 0.0;
1009  SCIP_Real maxdualentry;
1010  SCIP_Real identitydiagonal = 0.0;
1011  SCIP_Real rowval;
1012  SCIP_Real* rowvals;
1013  SCIP_Bool* diagentryexists;
1014 
1015  sdpconshdlr = SCIPfindConshdlr(scip, "SDP");
1016  nblocks = SCIPconshdlrGetNConss(sdpconshdlr);
1017  sdpblocks = SCIPconshdlrGetConss(sdpconshdlr);
1018  SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
1019 
1020  SCIP_CALL( SCIPallocBufferArray(scip, &startZnblocknonz, nblocks + 1) );
1021  SCIP_CALL( SCIPallocBufferArray(scip, &startZrow, nblocks + 1) );
1022  SCIP_CALL( SCIPallocBufferArray(scip, &startZcol, nblocks + 1) );
1023  SCIP_CALL( SCIPallocBufferArray(scip, &startZval, nblocks + 1) );
1024  SCIP_CALL( SCIPallocBufferArray(scip, &startXnblocknonz, nblocks + 1) );
1025  SCIP_CALL( SCIPallocBufferArray(scip, &startXrow, nblocks + 1) );
1026  SCIP_CALL( SCIPallocBufferArray(scip, &startXcol, nblocks + 1) );
1027  SCIP_CALL( SCIPallocBufferArray(scip, &startXval, nblocks + 1) );
1028 
1029  /* compute the scaling factor for the dual identity matrix (for numerical stability, this should be at least 1) */
1030  if ( relaxdata->warmstartiptype == 1 )
1031  {
1032  maxprimalentry = SCIPconsSavesdpsolGetMaxPrimalEntry(scip, conss[0]);
1033  if ( SCIPisLT(scip, maxprimalentry, 1.0) )
1034  maxprimalentry = 1.0;
1035  }
1036 
1037  /* iterate over all blocks and fill X and Z */
1038  for (b = 0; b < nblocks; b++)
1039  {
1040  blocksize = SCIPconsSdpGetBlocksize(scip, sdpblocks[b]);
1041 
1042  if ( relaxdata->warmstartproject == 3 || relaxdata->warmstartproject == 4 )
1043  {
1044  /* since we later take the projection onto the psd cone, we cannot a priori determine the size, so we take the maximum possible */
1045  startZnblocknonz[b] = blocksize * (blocksize + 1) / 2;
1046  }
1047  else
1048  {
1049  startZnblocknonz[b] = SCIPconsSdpComputeUbSparseSdpMatrixLength(scip, sdpblocks[b]);
1050 
1051  /* since we take a convex combination with either the identity matrix or the analytic center, we have to allocate memory for that as well */
1052  if ( SCIPisGT(scip, relaxdata->warmstartipfactor, 0.0) )
1053  {
1054  if ( relaxdata->warmstartiptype == 1 )
1055  startZnblocknonz[b] += blocksize;
1056  else if ( relaxdata->warmstartiptype == 2 )
1057  startZnblocknonz[b] += relaxdata->ipZnblocknonz[b];
1058  }
1059  }
1060 
1061  SCIP_CALL( SCIPallocBufferArray(scip, &startZrow[b], startZnblocknonz[b]) );
1062  SCIP_CALL( SCIPallocBufferArray(scip, &startZcol[b], startZnblocknonz[b]) );
1063  SCIP_CALL( SCIPallocBufferArray(scip, &startZval[b], startZnblocknonz[b]) );
1064 
1065  /* compute Z matrix */
1066  SCIP_CALL( SCIPconsSdpComputeSparseSdpMatrix(scip, sdpblocks[b], dualsol, &(startZnblocknonz[b]), startZrow[b], startZcol[b], startZval[b]) );
1067 
1068  /* compute projection onto psd cone (computed as U * diag(lambda_i_+) * U^T where U consists of the eigenvectors of the matrix) */
1069  if ( relaxdata->warmstartproject == 3 )
1070  {
1071  SCIP_Real* fullZmatrix;
1072  SCIP_Real* eigenvalues;
1073  SCIP_Real* eigenvectors;
1074  SCIP_Real* scaledeigenvectors;
1075  SCIP_Real matrixsize;
1076  SCIP_Real epsilon;
1077  int c;
1078  int matrixpos;
1079 
1080  matrixsize = blocksize * blocksize;
1081 
1082  SCIP_CALL( SCIPallocBufferArray(scip, &fullZmatrix, matrixsize) );
1083  SCIP_CALL( SCIPallocBufferArray(scip, &eigenvalues, blocksize) );
1084  SCIP_CALL( SCIPallocBufferArray(scip, &eigenvectors, matrixsize) );
1085 
1086  SCIP_CALL( expandSparseMatrix(startZnblocknonz[b], blocksize, startZrow[b], startZcol[b], startZval[b], fullZmatrix) );
1087 
1088  SCIP_CALL( SCIPlapackComputeEigenvectorDecomposition(SCIPbuffer(scip), blocksize, fullZmatrix, eigenvalues, eigenvectors) );
1089 
1090  /* duplicate memory of eigenvectors to compute diag(lambda_i_+) * U^T */
1091  SCIP_CALL( SCIPduplicateBufferArray(scip, &scaledeigenvectors, eigenvectors, matrixsize) );
1092 
1093  /* set all negative eigenvalues to zero (using the property that LAPACK returns them in ascending order) */
1094  i = 0;
1095  while (i < blocksize && SCIPisLT(scip, eigenvalues[i], relaxdata->warmstartprojminevdual) )
1096  {
1097  eigenvalues[i] = relaxdata->warmstartprojminevdual;
1098  i++;
1099  }
1100 
1101  /* compute diag(lambda_i_+) * U^T */
1102  SCIP_CALL( scaleTransposedMatrix(blocksize, scaledeigenvectors, eigenvalues) );
1103 
1104  /* compute U * [diag(lambda_i_+) * U^T] (note that transposes are switched because LAPACK uses column-first-format) */
1105  SCIP_CALL( SCIPlapackMatrixMatrixMult(blocksize, blocksize, eigenvectors, TRUE, blocksize, blocksize, scaledeigenvectors,
1106  FALSE, fullZmatrix) );
1107 
1108  /* extract sparse matrix from projection */
1109  startZnblocknonz[b] = 0;
1110  epsilon = SCIPepsilon(scip);
1111  for (r = 0; r < blocksize; r++)
1112  {
1113  for (c = r; c < blocksize; c++)
1114  {
1115  matrixpos = r * blocksize + c;
1116  if ( REALABS(fullZmatrix[matrixpos]) > epsilon )
1117  {
1118  startZrow[b][startZnblocknonz[b]] = r;
1119  startZcol[b][startZnblocknonz[b]] = c;
1120  startZval[b][startZnblocknonz[b]] = fullZmatrix[matrixpos];
1121  startZnblocknonz[b]++;
1122  }
1123  }
1124  }
1125 
1126  /* free memory */
1127  SCIPfreeBufferArray(scip, &scaledeigenvectors);
1128  SCIPfreeBufferArray(scip, &eigenvectors);
1129  SCIPfreeBufferArray(scip, &eigenvalues);
1130  SCIPfreeBufferArray(scip, &fullZmatrix);
1131  }
1132 
1133  if ( relaxdata->warmstartprimaltype == 1 )
1134  {
1135  /* we set X to maxprimalentry times the identity matrix */
1136  if ( relaxdata->warmstartiptype == 1 )
1137  {
1138  startXnblocknonz[b] = blocksize;
1139  SCIP_CALL( SCIPallocBufferArray(scip, &startXrow[b], startXnblocknonz[b]) );
1140  SCIP_CALL( SCIPallocBufferArray(scip, &startXcol[b], startXnblocknonz[b]) );
1141  SCIP_CALL( SCIPallocBufferArray(scip, &startXval[b], startXnblocknonz[b]) );
1142  for (i = 0; i < startXnblocknonz[b]; i++)
1143  {
1144  startXrow[b][i] = i;
1145  startXcol[b][i] = i;
1146  startXval[b][i] = maxprimalentry;
1147  }
1148  }
1149  }
1150  else if ( relaxdata->warmstartprimaltype == 2 )
1151  {
1152  startXnblocknonz[b] = startZnblocknonz[b];
1153  SCIP_CALL( SCIPallocBufferArray(scip, &startXrow[b], startXnblocknonz[b]) );
1154  SCIP_CALL( SCIPallocBufferArray(scip, &startXcol[b], startXnblocknonz[b]) );
1155  SCIP_CALL( SCIPallocBufferArray(scip, &startXval[b], startXnblocknonz[b]) );
1156  for (i = 0; i < startZnblocknonz[b]; i++)
1157  {
1158  startXrow[b][i] = startZrow[b][i];
1159  startXcol[b][i] = startZcol[b][i];
1160  startXval[b][i] = 1 / startZval[b][i];
1161  }
1162  }
1163  else if ( relaxdata->warmstartprimaltype != 3 && relaxdata->warmstartproject != 4 )
1164  {
1165  SCIPerrorMessage("Unknown value %d for warmstartprimaltype.\n", relaxdata->warmstartprimaltype);
1166  SCIPABORT();
1167  }
1168  }
1169 
1170  if ( relaxdata->warmstartproject != 4 )
1171  {
1172  /* fill LP-block */
1173  SCIP_CALL( SCIPallocBufferArray(scip, &startZrow[b], 2 * nrows + 2 * nvars) );
1174  SCIP_CALL( SCIPallocBufferArray(scip, &startZcol[b], 2 * nrows + 2 * nvars) );
1175  SCIP_CALL( SCIPallocBufferArray(scip, &startZval[b], 2 * nrows + 2 * nvars) );
1176  SCIP_CALL( SCIPallocBufferArray(scip, &startXrow[b], 2 * nrows + 2 * nvars) );
1177  SCIP_CALL( SCIPallocBufferArray(scip, &startXcol[b], 2 * nrows + 2 * nvars) );
1178  SCIP_CALL( SCIPallocBufferArray(scip, &startXval[b], 2 * nrows + 2 * nvars) );
1179 
1180  /* to get a positive definite matrix, all the entries need to be strictly positive */
1181  startZnblocknonz[b] = 2 * nrows + 2 * nvars;
1182  startXnblocknonz[b] = 2 * nrows + 2 * nvars;
1183 
1184  for (r = 0; r < nrows; r++)
1185  {
1186  /* compute row value for current solution */
1187  rowval = 0.0;
1188  rownnonz = SCIProwGetNNonz(rows[r]);
1189  rowvals = SCIProwGetVals(rows[r]);
1190  rowcols = SCIProwGetCols(rows[r]);
1191  for (i = 0; i < rownnonz; i++)
1192  rowval += SCIPgetSolVal(scip, dualsol, SCIPcolGetVar(rowcols[i])) * rowvals[i];
1193 
1194  startZrow[b][2*r] = 2*r;
1195  startZcol[b][2*r] = 2*r;
1196  startZval[b][2*r] = rowval - (SCIProwGetLhs(rows[r]) - SCIProwGetConstant(rows[r]));
1197 
1198  if ( relaxdata->warmstartiptype == 1 && relaxdata->warmstartproject == 3 && SCIPisLT(scip, startZval[b][2*r], relaxdata->warmstartprojminevdual) )
1199  startZval[b][2*r] = relaxdata->warmstartprojminevdual;
1200  /* we only take the convex combination if the value is less than one, since the maxblockentry is equal to the value
1201  * otherwise, so taking the convex combination doesn't change anything in that case
1202  */
1203  else if ( relaxdata->warmstartiptype == 1 && SCIPisLT(scip, startZval[b][2*r], 1.0) )
1204  {
1205  /* since we want the value to be strictly positive, if the original entry is negative we just set it to warmstartipfactor */
1206  if ( SCIPisLT(scip, startZval[b][2*r], 0.0) )
1207  startZval[b][2*r] = relaxdata->warmstartipfactor;
1208  else
1209  startZval[b][2*r] = (1 - relaxdata->warmstartipfactor) * startZval[b][2*r] + relaxdata->warmstartipfactor;
1210  }
1211  else if ( relaxdata->warmstartiptype == 2 )
1212  {
1213  startZval[b][2*r] = (1 - relaxdata->warmstartipfactor) * startZval[b][2*r] + relaxdata->warmstartipfactor * relaxdata->ipZval[b][2*r];
1214 
1215  /* if this is non-positive, we shift it to a strictly positive value */
1216  if ( SCIPisLT(scip, startZval[b][2*r], WARMSTART_MINVAL) )
1217  startZval[b][2*r] = WARMSTART_MINVAL;
1218  }
1219 
1220  if ( relaxdata->warmstartpreoptsol && startZval[b][2*r] < WARMSTART_PREOPT_MIN_Z_LPVAL )
1221  startZval[b][2*r] = WARMSTART_PREOPT_MIN_Z_LPVAL;
1222 
1223  startZrow[b][2*r + 1] = 2*r + 1;
1224  startZcol[b][2*r + 1] = 2*r + 1;
1225  startZval[b][2*r + 1] = SCIProwGetRhs(rows[r]) - SCIProwGetConstant(rows[r]) - rowval;
1226 
1227  if ( relaxdata->warmstartiptype == 1 && relaxdata->warmstartproject == 3 && SCIPisLT(scip, startZval[b][2*r + 1], relaxdata->warmstartprojminevdual) )
1228  startZval[b][2*r + 1] = relaxdata->warmstartprojminevdual;
1229  else if ( relaxdata->warmstartiptype == 1 && SCIPisLT(scip, startZval[b][2*r + 1], 1.0) )
1230  {
1231  /* since we want the value to be strictly positive, if the original entry is negative we just set it to warmstartipfactor */
1232  if ( SCIPisLT(scip, startZval[b][2*r + 1], 0.0) )
1233  startZval[b][2*r + 1] = relaxdata->warmstartipfactor;
1234  else
1235  startZval[b][2*r + 1] = (1 - relaxdata->warmstartipfactor) * startZval[b][2*r + 1] + relaxdata->warmstartipfactor;
1236  }
1237  else if ( relaxdata->warmstartiptype == 2 )
1238  {
1239  startZval[b][2*r + 1] = (1 - relaxdata->warmstartipfactor) * startZval[b][2*r + 1] + relaxdata->warmstartipfactor * relaxdata->ipZval[b][2*r + 1];
1240 
1241  /* if this is non-positive, we shift it to a strictly positive value */
1242  if ( SCIPisLT(scip, startZval[b][2*r + 1], WARMSTART_MINVAL) )
1243  startZval[b][2*r + 1] = WARMSTART_MINVAL;
1244  }
1245 
1246  if ( relaxdata->warmstartpreoptsol && startZval[b][2*r + 1] < WARMSTART_PREOPT_MIN_Z_LPVAL )
1247  startZval[b][2*r + 1] = WARMSTART_PREOPT_MIN_Z_LPVAL;
1248 
1249  if ( relaxdata->warmstartprimaltype == 1 && relaxdata->warmstartiptype == 1 )
1250  {
1251  startXrow[b][2*r] = 2*r;
1252  startXcol[b][2*r] = 2*r;
1253  startXval[b][2*r] = maxprimalentry;
1254  startXrow[b][2*r + 1] = 2*r + 1;
1255  startXcol[b][2*r + 1] = 2*r + 1;
1256  startXval[b][2*r + 1] = maxprimalentry;
1257  }
1258  else if ( relaxdata->warmstartprimaltype == 2 )
1259  {
1260  startXrow[b][2*r] = startZrow[b][2*r];
1261  startXcol[b][2*r] = startZcol[b][2*r];
1262  startXval[b][2*r] = 1 / startZval[b][2*r];
1263  startXrow[b][2*r + 1] = startZrow[b][2*r + 1];
1264  startXcol[b][2*r + 1] = startZcol[b][2*r + 1];
1265  startXval[b][2*r + 1] = 1 / startZval[b][2*r + 1];
1266  }
1267  else if ( relaxdata->warmstartprimaltype != 3 && relaxdata->warmstartiptype == 1 )
1268  {
1269  SCIPerrorMessage("Unknown value %d for warmstartprimaltype.\n", relaxdata->warmstartprimaltype);
1270  SCIPABORT();
1271  }
1272  }
1273 
1274  for (v = 0; v < nvars; v++)
1275  {
1276  startZrow[b][2*nrows + 2*v] = 2*nrows + 2*v;
1277  startZcol[b][2*nrows + 2*v] = 2*nrows + 2*v;
1278  startZval[b][2*nrows + 2*v] = SCIPgetSolVal(scip, dualsol, vars[v]) - SCIPvarGetLbLocal(vars[v]);
1279  if ( relaxdata->warmstartiptype == 1 && relaxdata->warmstartproject == 3 && SCIPisLT(scip, startZval[b][2*nrows + 2*v], relaxdata->warmstartprojminevdual) )
1280  startZval[b][2*nrows + 2*v] = relaxdata->warmstartprojminevdual;
1281  else if ( relaxdata->warmstartiptype == 1 && SCIPisLT(scip, startZval[b][2*nrows + 2*v], 1.0) )
1282  {
1283  /* since we want the value to be strictly positive, if the original entry is negative we just set it to warmstartipfactor */
1284  if ( SCIPisLT(scip, startZval[b][2*nrows + 2*v], 0.0) )
1285  startZval[b][2*nrows + 2*v] = relaxdata->warmstartipfactor;
1286  else
1287  startZval[b][2*nrows + 2*v] = (1 - relaxdata->warmstartipfactor) * startZval[b][2*nrows + 2*v] + relaxdata->warmstartipfactor;
1288  }
1289  else if ( relaxdata->warmstartiptype == 2 )
1290  {
1291  startZval[b][2*nrows + 2*v] = (1 - relaxdata->warmstartipfactor) * startZval[b][2*nrows + 2*v] + relaxdata->warmstartipfactor * relaxdata->ipZval[b][2*nrows + 2*v];
1292 
1293  /* if this is non-positive, we shift it to a strictly positive value */
1294  if ( SCIPisLT(scip, startZval[b][2*nrows + 2*v], WARMSTART_MINVAL) )
1295  startZval[b][2*nrows + 2*v] = WARMSTART_MINVAL;
1296  }
1297 
1298  if ( relaxdata->warmstartpreoptsol && startZval[b][2*nrows + 2*v] < WARMSTART_PREOPT_MIN_Z_LPVAL )
1299  startZval[b][2*nrows + 2*v] = WARMSTART_PREOPT_MIN_Z_LPVAL;
1300 
1301  startZrow[b][2*nrows + 2*v + 1] = 2*nrows + 2*v + 1;
1302  startZcol[b][2*nrows + 2*v + 1] = 2*nrows + 2*v + 1;
1303  startZval[b][2*nrows + 2*v + 1] = SCIPvarGetUbLocal(vars[v]) - SCIPgetSolVal(scip, dualsol, vars[v]);
1304  if ( relaxdata->warmstartiptype == 1 && relaxdata->warmstartproject == 3 && SCIPisLT(scip, startZval[b][2*nrows + 2*v + 1], relaxdata->warmstartprojminevdual) )
1305  startZval[b][2*nrows + 2*v + 1] = relaxdata->warmstartprojminevdual;
1306  else if ( relaxdata->warmstartiptype == 1 && SCIPisLT(scip, startZval[b][2*nrows + 2*v + 1], 1.0) )
1307  {
1308  /* since we want the value to be strictly positive, if the original entry is negative we just set it to warmstartipfactor */
1309  if ( SCIPisLT(scip, startZval[b][2*nrows + 2*v + 1], 0.0) )
1310  startZval[b][2*nrows + 2*v + 1] = relaxdata->warmstartipfactor;
1311  else
1312  startZval[b][2*nrows + 2*v + 1] = (1 - relaxdata->warmstartipfactor) * startZval[b][2*nrows + 2*v + 1] + relaxdata->warmstartipfactor;
1313  }
1314  else if ( relaxdata->warmstartiptype == 2 )
1315  {
1316  startZval[b][2*nrows + 2*v + 1] = (1 - relaxdata->warmstartipfactor) * startZval[b][2*nrows + 2*v] + relaxdata->warmstartipfactor * relaxdata->ipZval[b][2*nrows + 2*v + 1];
1317 
1318  /* if this is non-positive, we shift it to a strictly positive value */
1319  if ( SCIPisLT(scip, startZval[b][2*nrows + 2*v + 1], WARMSTART_MINVAL) )
1320  startZval[b][2*nrows + 2*v + 1] = WARMSTART_MINVAL;
1321  }
1322 
1323  if ( relaxdata->warmstartpreoptsol && startZval[b][2*nrows + 2*v + 1] < WARMSTART_PREOPT_MIN_Z_LPVAL )
1324  startZval[b][2*nrows + 2*v + 1] = WARMSTART_PREOPT_MIN_Z_LPVAL;
1325 
1326  if ( relaxdata->warmstartprimaltype == 1 && relaxdata->warmstartiptype == 1 )
1327  {
1328  startXrow[b][2*nrows + 2*v] = 2*nrows + 2*v;
1329  startXcol[b][2*nrows + 2*v] = 2*nrows + 2*v;
1330  startXval[b][2*nrows + 2*v] = maxprimalentry;
1331  startXrow[b][2*nrows + 2*v + 1] = 2*nrows + 2*v + 1;
1332  startXcol[b][2*nrows + 2*v + 1] = 2*nrows + 2*v + 1;
1333  startXval[b][2*nrows + 2*v + 1] = maxprimalentry;
1334  }
1335  else if ( relaxdata->warmstartprimaltype == 2 )
1336  {
1337  startXrow[b][2*nrows + 2*v] = startZrow[b][2*nrows + 2*v];
1338  startXcol[b][2*nrows + 2*v] = startZcol[b][2*nrows + 2*v];
1339  startXval[b][2*nrows + 2*v] = 1 / startZval[b][2*nrows + 2*v];
1340  startXrow[b][2*nrows + 2*v + 1] = startZrow[b][2*nrows + 2*v + 1];
1341  startXcol[b][2*nrows + 2*v + 1] = startZcol[b][2*nrows + 2*v + 1];
1342  startXval[b][2*nrows + 2*v + 1] = 1 / startZval[b][2*nrows + 2*v + 1];
1343  }
1344  else if ( relaxdata->warmstartprimaltype != 3 && relaxdata->warmstartproject == 1 )
1345  {
1346  SCIPerrorMessage("Unknown value %d for warmstartprimaltype.\n", relaxdata->warmstartprimaltype);
1347  SCIPABORT();
1348  }
1349  }
1350  }
1351 
1352  /* Solve the primal rounding problem
1353  * \f{eqnarray*}{
1354  * \max & & \sum_{k \in K} A_0^{(k)} \bullet (V^{(k)} \text{diag}(\lambda^{(k)}) (V^{(k)})^T) + \sum_{j \in J} c_j x_j - \sum_{i \in I_u} u_i v_i + \sum_{i \in I_\ell} \ell_i w_i \\
1355  * \mbox{s.t.} & & \sum_{k \in K} A_i^{(k)} \bullet (V^{(k)} \text{diag}(\lambda^{(k)}) (V^{(k)})^T) + \sum_{j \in J} d_{ij} x_j - 1_{\{u_i < \infty\}} v_i + 1_{\{\ell_i > -\infty\}} w_i = b_i \quad \forall \ i \in I,\\
1356  * & & \lambda^{(k)}_i \geq 0 \quad \forall \ k \in K, i \leq n \\
1357  * & & x_j \geq 0 \quad \forall \ j \in J,\\
1358  * & & v_i \geq 0 \quad \forall \ i \in I_u,\\
1359  * & & w_i \geq 0 \quad \forall \ i \in I_\ell,
1360  * \f}
1361  * where \f$ V^{(k)} \text{diag}(\bar{\lambda}^{(k)}) (V^{(k)})^T \f$ is an eigenvector decomposition of the optimal primal solution
1362  * of the parent node, as well as the dual rounding problem
1363  * \f{eqnarray*}{
1364  * \min & & b^T y \\
1365  * \mbox{s.t.} & & \sum_{i \in I} d_{ij} y_i \geq c_j \quad \forall \ j \in J, \\
1366  * & & \sum_{i \in I} A_i^{(k)} y_i - A_0^{(k)} = V^{(k)} \text{diag}(\lambda^{(k)}) (V^{(k)})^T \quad \forall \ k \in K, \\
1367  * & & \ell_i \leq y_i \leq u_i \quad \forall \ i \in I, \\
1368  * & & \lambda^{(k)}_i \geq 0 \quad \forall \ k \in K, i \leq n \\
1369  * \f}
1370  * where \f$ V^{(k)} \text{diag}(\bar{\lambda}^{(k)}) (V^{(k)})^T \f$ is now an eigenvector decomposition of the optimal solution
1371  * of the parent node for the dual problem. The matrix equation is reformulated as blocksize * (blocksize + 1) /2 linear constraints
1372  * over the lower triangular entries.
1373  */
1374  if ( relaxdata->warmstartproject == 4 )
1375  {
1376  SCIP_VAR** blockvars;
1377  SCIP_LPI* lpi;
1378  SCIP_ROW* row;
1379  struct timeval starttime;
1380  struct timeval currenttime;
1381  SCIP_Real** blockval;
1382  SCIP_Real** blockeigenvalues;
1383  SCIP_Real** blockeigenvectors;
1384  SCIP_Real** blockrowvals;
1385  SCIP_Real* obj;
1386  SCIP_Real* lb;
1387  SCIP_Real* ub;
1388  SCIP_Real* lhs;
1389  SCIP_Real* rhs;
1390  SCIP_Real* val;
1391  SCIP_Real* blockconstval;
1392  SCIP_Real* scaledeigenvectors;
1393  SCIP_Real* fullXmatrix;
1394  SCIP_Real* fullZmatrix;
1395  SCIP_Real rowlhs;
1396  SCIP_Real rowrhs;
1397  SCIP_Real varobj;
1398  SCIP_Real epsilon;
1399  SCIP_Real primalroundobj;
1400  SCIP_Real dualroundobj;
1401  int** blockcol;
1402  int** blockrow;
1403  int** blockrowcols;
1404  int* beg;
1405  int* ind;
1406  int* blocknvarnonz;
1407  int* blockconstcol;
1408  int* blockconstrow;
1409  int* blocksizes;
1410  int* nblockrownonz;
1411  int* rowinds;
1412  int pos;
1413  int indpos;
1414  int startpos;
1415  int blocknvars;
1416  int blocknnonz;
1417  int arraylength;
1418  int blockconstnnonz;
1419  int varind;
1420  int roundingvars;
1421  int matrixsize;
1422  int evind;
1423  int c;
1424  int matrixpos;
1425  int nroundingrows;
1426  int j;
1427  int nremovedentries;
1428 
1429  /* since the main purpose of the rounding problem approach is detecting infeasibility through the restricted primal problem,
1430  * it doesn't make sense to use this approach unless the whole primal solution is saved */
1431  if ( relaxdata->warmstartprimaltype != 3 )
1432  {
1433  SCIPerrorMessage("Invalid parameter combination, use relax/warmstartproject = 4 only with relax/warmstartprimaltype = 3.\n");
1434  return SCIP_PARAMETERWRONGVAL;
1435  }
1436 
1437  TIMEOFDAY_CALL( gettimeofday(&starttime, NULL) );/*lint !e438, !e550, !e641 */
1438 
1439  /* since we cannot compute the number of nonzeros of the solution of the rounding problem beforehand, we allocate the maximum possible (blocksize * (blocksize + 1) / 2 */
1440  for (b = 0; b < nblocks; b++)
1441  {
1442  matrixsize = SCIPconsSdpGetBlocksize(scip, sdpblocks[b]);
1443  matrixsize *= (matrixsize + 1) * 0.5;
1444  startXnblocknonz[b] = matrixsize;
1445 
1446  SCIP_CALL( SCIPallocBufferArray(scip, &startXrow[b], matrixsize) );
1447  SCIP_CALL( SCIPallocBufferArray(scip, &startXcol[b], matrixsize) );
1448  SCIP_CALL( SCIPallocBufferArray(scip, &startXval[b], matrixsize) );
1449  }
1450 
1451  /* allocate memory for LP and variable bound block of warmstart matrix (note that we need to allocate the maximum, since additional
1452  * entries may be generated through the convex combination */
1453  SCIP_CALL( SCIPallocBufferArray(scip, &startXrow[nblocks], 2 * nvars + 2 * nrows) );
1454  SCIP_CALL( SCIPallocBufferArray(scip, &startXcol[nblocks], 2 * nvars + 2 * nrows) );
1455  SCIP_CALL( SCIPallocBufferArray(scip, &startXval[nblocks], 2 * nvars + 2 * nrows) );
1456  startXnblocknonz[nblocks] = 2 * nvars + 2 * nrows;
1457 
1458  SCIP_CALL( SCIPconsSavesdpsolGetPrimalMatrix(scip, conss[parentconsind], nblocks + 1, startXnblocknonz, startXrow, startXcol, startXval) );
1459 
1460  lpi = relaxdata->lpi;
1461 
1462  /* clear the old LP */
1463  SCIP_CALL( SCIPlpiClear(lpi) );
1464 
1465  /* we want to maximize for the primal rounding problem */
1466  SCIP_CALL( SCIPlpiChgObjsen(lpi, SCIP_OBJSEN_MAXIMIZE) );
1467 
1468  /* if the varmapper has a different number of variables than SCIP, we might get problems with empty spots in the obj/lb/ub arrays */
1469  assert( SCIPsdpVarmapperGetNVars(relaxdata->varmapper) == nvars );
1470 
1471  /* initialize the rows */
1472  SCIP_CALL( SCIPallocBufferArray(scip, &lhs, nvars) );
1473  SCIP_CALL( SCIPallocBufferArray(scip, &rhs, nvars) );
1474  for (v = 0; v < nvars; v++)
1475  {
1476  varobj = SCIPvarGetObj(vars[v]);
1477  lhs[SCIPsdpVarmapperGetSdpIndex(relaxdata->varmapper, vars[v])] = varobj;
1478  rhs[SCIPsdpVarmapperGetSdpIndex(relaxdata->varmapper, vars[v])] = varobj;
1479  }
1480 
1481  /* this vector will be used to later map the solution to the correspoding blocks */
1482  SCIP_CALL( SCIPallocBufferArray(scip, &blocksizes, nblocks + 2) );
1483  SCIP_CALL( SCIPallocBufferArray(scip, &blockeigenvalues, nblocks) );
1484  SCIP_CALL( SCIPallocBufferArray(scip, &blockeigenvectors, nblocks) );
1485 
1486  /* initialize rows; columns will be added blockwise later (note that we reenter the whole problem each time
1487  * and do not allow warmstarts, we could store the LP- and bound-constraints between nodes (TODO, but would
1488  * need to check for added/removed cuts then), but warmstarting doesn't seem to make sense since the whole
1489  * SDP part is changed, which should form the main difficulty when solving (MI)SDPs */
1490  SCIP_CALL( SCIPlpiAddRows(lpi, nvars, lhs, rhs, NULL, 0, NULL, NULL, NULL) );
1491 
1492  SCIPfreeBufferArray(scip, &rhs);
1493  SCIPfreeBufferArray(scip, &lhs);
1494 
1495  /* add columns corresponding to bound constraints (at most we get two entries [lb & ub] per variable) */
1496  SCIP_CALL( SCIPallocBufferArray(scip, &obj, 2*nvars) );
1497  SCIP_CALL( SCIPallocBufferArray(scip, &lb, 2*nvars) );
1498  SCIP_CALL( SCIPallocBufferArray(scip, &ub, 2*nvars) );
1499  SCIP_CALL( SCIPallocBufferArray(scip, &beg, 2*nvars) );
1500  SCIP_CALL( SCIPallocBufferArray(scip, &ind, 2*nvars) );
1501  SCIP_CALL( SCIPallocBufferArray(scip, &val, 2*nvars) );
1502 
1503  /* iterate over all finite variable bounds and set the corresponding entries */
1504  pos = 0;
1505  for (v = 0; v < nvars; v++)
1506  {
1507  if ( ! SCIPisInfinity(scip, -1 * SCIPvarGetLbLocal(vars[v])) )
1508  {
1509  obj[pos] = SCIPvarGetLbLocal(vars[v]);
1510  lb[pos] = 0.0;
1511  ub[pos] = SCIPlpiInfinity(lpi);
1512  beg[pos] = pos;
1513  ind[pos] = SCIPsdpVarmapperGetSdpIndex(relaxdata->varmapper, vars[v]);
1514  val[pos] = 1.0;
1515  pos++;
1516  }
1517  if ( ! SCIPisInfinity(scip, SCIPvarGetUbLocal(vars[v])) )
1518  {
1519  obj[pos] = -1 * SCIPvarGetUbLocal(vars[v]);
1520  lb[pos] = 0.0;
1521  ub[pos] = SCIPlpiInfinity(lpi);
1522  beg[pos] = pos;
1523  ind[pos] = SCIPsdpVarmapperGetSdpIndex(relaxdata->varmapper, vars[v]);
1524  val[pos] = -1.0;
1525  pos++;
1526  }
1527  }
1528 
1529  SCIP_CALL( SCIPlpiAddCols(lpi, pos, obj, lb, ub, NULL, pos, beg, ind, val) );
1530  blocksizes[0] = pos;
1531  roundingvars = pos;
1532 
1533  SCIPfreeBufferArray(scip, &val);
1534  SCIPfreeBufferArray(scip, &ind);
1535  SCIPfreeBufferArray(scip, &beg);
1536  SCIPfreeBufferArray(scip, &ub);
1537  SCIPfreeBufferArray(scip, &lb);
1538  SCIPfreeBufferArray(scip, &obj);
1539 
1540  /* add columns corresponding to linear constraints (at most we get two columns per ranged row) */
1541  SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
1542 
1543  SCIP_CALL( SCIPallocBufferArray(scip, &obj, 2*nrows) );
1544  SCIP_CALL( SCIPallocBufferArray(scip, &lb, 2*nrows) );
1545  SCIP_CALL( SCIPallocBufferArray(scip, &ub, 2*nrows) );
1546  SCIP_CALL( SCIPallocBufferArray(scip, &beg, 2*nrows) );
1547  SCIP_CALL( SCIPallocBufferArray(scip, &ind, 2*nrows*nvars) );
1548  SCIP_CALL( SCIPallocBufferArray(scip, &val, 2*nrows*nvars) );
1549 
1550  pos = 0;
1551  indpos = 0;
1552  /* iterate over all LP-ranged-rows and add corresponding entries if lhs and/or rhs is finite */
1553  for (r = 0; r < nrows; r++)
1554  {
1555  row = rows[r];
1556  assert( row != 0 );
1557  rownnonz = SCIProwGetNNonz(row);
1558 
1559  rowvals = SCIProwGetVals(row);
1560  rowcols = SCIProwGetCols(row);
1561  rowlhs = SCIProwGetLhs(row) - SCIProwGetConstant(row);
1562  rowrhs = SCIProwGetRhs(row) - SCIProwGetConstant(row);
1563 
1564  if ( ! SCIPisInfinity(scip, -1 * rowlhs) )
1565  {
1566  obj[pos] = rowlhs;
1567  lb[pos] = 0.0;
1568  ub[pos] = SCIPlpiInfinity(lpi);
1569  beg[pos] = indpos;
1570  for (i = 0; i < rownnonz; i++)
1571  {
1572  ind[indpos] = SCIPsdpVarmapperGetSdpIndex(relaxdata->varmapper, SCIPcolGetVar(rowcols[i]));
1573  val[indpos] = rowvals[i];
1574  indpos++;
1575  }
1576  pos++;
1577  }
1578  /* since we assume >= constraints in the dual, we have to multiply all entries of <= constraints by -1 */
1579  if ( ! SCIPisInfinity(scip, rowrhs) )
1580  {
1581  obj[pos] = -1 * rowrhs;
1582  lb[pos] = 0.0;
1583  ub[pos] = SCIPlpiInfinity(lpi);
1584  beg[pos] = indpos;
1585  for (i = 0; i < rownnonz; i++)
1586  {
1587  ind[indpos] = SCIPsdpVarmapperGetSdpIndex(relaxdata->varmapper, SCIPcolGetVar(rowcols[i]));
1588  val[indpos] = -1 * rowvals[i];
1589  indpos++;
1590  }
1591  pos++;
1592  }
1593  }
1594 
1595  SCIP_CALL( SCIPlpiAddCols(lpi, pos, obj, lb, ub, NULL, indpos, beg, ind, val) );
1596  blocksizes[1] = pos;
1597  roundingvars += pos;
1598 
1599  SCIPfreeBufferArray(scip, &val);
1600  SCIPfreeBufferArray(scip, &ind);
1601  SCIPfreeBufferArray(scip, &beg);
1602  SCIPfreeBufferArray(scip, &ub);
1603  SCIPfreeBufferArray(scip, &lb);
1604  SCIPfreeBufferArray(scip, &obj);
1605 
1606  /* finally add columns corresponding to SDP-constraints */
1607  for (b = 0; b < nblocks; b++)
1608  {
1609  /* get data for this SDP block */
1610  SCIP_CALL( SCIPconsSdpGetNNonz(scip, sdpblocks[b], NULL, &blockconstnnonz) );
1611  SCIP_CALL( SCIPallocBufferArray(scip, &blocknvarnonz, nvars) );
1612  SCIP_CALL( SCIPallocBufferArray(scip, &blockcol, nvars) );
1613  SCIP_CALL( SCIPallocBufferArray(scip, &blockrow, nvars) );
1614  SCIP_CALL( SCIPallocBufferArray(scip, &blockval, nvars) );
1615  SCIP_CALL( SCIPallocBufferArray(scip, &blockvars, nvars) );
1616  SCIP_CALL( SCIPallocBufferArray(scip, &blockconstcol, blockconstnnonz) );
1617  SCIP_CALL( SCIPallocBufferArray(scip, &blockconstrow, blockconstnnonz) );
1618  SCIP_CALL( SCIPallocBufferArray(scip, &blockconstval, blockconstnnonz) );
1619 
1620  arraylength = nvars;
1621  SCIP_CALL( SCIPconsSdpGetData(scip, sdpblocks[b], &blocknvars, &blocknnonz, &blocksize, &arraylength, blocknvarnonz,
1622  blockcol, blockrow, blockval, blockvars, &blockconstnnonz, blockconstcol, blockconstrow, blockconstval) );
1623  assert( arraylength == nvars ); /* arraylength should alwys be sufficient */
1624 
1625  matrixsize = blocksize * blocksize;
1626 
1627  SCIP_CALL( SCIPallocBufferArray(scip, &fullXmatrix, matrixsize) );
1628  SCIP_CALL( SCIPallocBufferArray(scip, &blockeigenvalues[b], blocksize) );
1629  SCIP_CALL( SCIPallocBufferArray(scip, &blockeigenvectors[b], matrixsize) );
1630 
1631  SCIP_CALL( expandSparseMatrix(startXnblocknonz[b], blocksize, startXrow[b], startXcol[b], startXval[b], fullXmatrix) );
1632 
1633  SCIP_CALL( SCIPlapackComputeEigenvectorDecomposition(SCIPbuffer(scip), blocksize, fullXmatrix, blockeigenvalues[b], blockeigenvectors[b]) );
1634 
1635  /* compute coefficients for rounding problems, we get blocksize many variables corresponding to the eigenvalues of X* */
1636  SCIP_CALL( SCIPallocBufferArray(scip, &obj, blocksize) );
1637  SCIP_CALL( SCIPallocBufferArray(scip, &lb, blocksize) );
1638  SCIP_CALL( SCIPallocBufferArray(scip, &ub, blocksize) );
1639  SCIP_CALL( SCIPallocBufferArray(scip, &beg, blocksize) );
1640  SCIP_CALL( SCIPallocBufferArray(scip, &ind, blocksize*nvars) );
1641  SCIP_CALL( SCIPallocBufferArray(scip, &val, blocksize*nvars) );
1642 
1643  /* initialize arrays */
1644  for (i = 0; i < blocksize; i++)
1645  {
1646  obj[i] = 0.0;
1647  beg[i] = i * nvars;
1648 
1649  for (v = 0; v < nvars; v++)
1650  {
1651  ind[i * nvars + v] = v;
1652  val[i * nvars + v] = 0.0;
1653  }
1654 
1655  /* make all eigenvalues non-negative, so that matrix stays positive semidefinite */
1656  lb[i] = 0.0;
1657  ub[i] = SCIPlpiInfinity(lpi);
1658  }
1659 
1660  /* iterate over constant entries to compute objective coefficients */
1661  for (i = 0; i < blockconstnnonz; i++)
1662  {
1663  /* for every constant matrix entry (k,l) and every eigenvector i, we get an entry A_kl * V_ki *V_li
1664  * entry V_ki corresponds to entry k of the i-th eigenvector, which is given as the i-th row of the eigenvectors array
1665  * note that we need to mulitply by two for non-diagonal entries to also account for entry (l,k) */
1666  for (evind = 0; evind < blocksize; evind++)
1667  {
1668  if ( blockconstrow[i] == blockconstcol[i] )
1669  obj[evind] += blockconstval[i] * blockeigenvectors[b][evind * blocksize + blockconstrow[i]] * blockeigenvectors[b][evind * blocksize + blockconstcol[i]];
1670  else
1671  obj[evind] += 2 * blockconstval[i] * blockeigenvectors[b][evind * blocksize + blockconstrow[i]] * blockeigenvectors[b][evind * blocksize + blockconstcol[i]];
1672  }
1673  }
1674 
1675  SCIPfreeBufferArray(scip, &blockconstval);
1676  SCIPfreeBufferArray(scip, &blockconstrow);
1677  SCIPfreeBufferArray(scip, &blockconstcol);
1678 
1679  /* compute constraint coefficients */
1680  for (v = 0; v < blocknvars; v++)
1681  {
1682  varind = SCIPsdpVarmapperGetSdpIndex(relaxdata->varmapper, blockvars[v]);
1683  for (i = 0; i < blocknvarnonz[v]; i++)
1684  {
1685  /* for every matrix entry (k,l) and every eigenvector i, we get an entry A_kl * V_kj *V_lj
1686  * entry V_kj corresponds to entry k of the j-th eigenvector, which is given as the j-th row of the eigenvectors array
1687  * note that we need to mulitply by two for non-diagonal entries to also account for entry (l,k) */
1688  for (evind = 0; evind < blocksize; evind++)
1689  {
1690  if ( blockrow[v][i] == blockcol[v][i] )
1691  val[evind * nvars + varind] += blockval[v][i] * blockeigenvectors[b][evind * blocksize + blockrow[v][i]] * blockeigenvectors[b][evind * blocksize + blockcol[v][i]];
1692  else
1693  val[evind * nvars + varind] += 2 * blockval[v][i] * blockeigenvectors[b][evind * blocksize + blockrow[v][i]] * blockeigenvectors[b][evind * blocksize + blockcol[v][i]];
1694  }
1695  }
1696  }
1697 
1698  SCIPfreeBufferArray(scip, &blockvars);
1699  SCIPfreeBufferArray(scip, &blockval);
1700  SCIPfreeBufferArray(scip, &blockrow);
1701  SCIPfreeBufferArray(scip, &blockcol);
1702  SCIPfreeBufferArray(scip, &blocknvarnonz);
1703  SCIPfreeBufferArray(scip, &fullXmatrix);
1704 
1705  /* remove zero entries */
1706  nremovedentries = 0;
1707  for (i = 0; i < blocksize; i++)
1708  {
1709  beg[i] = beg[i] - nremovedentries;
1710  for (v = 0; v < nvars; v++)
1711  {
1712  if ( REALABS(val[i * nvars + v]) < SCIPepsilon(scip) )
1713  {
1714  nremovedentries++;
1715  }
1716  else
1717  {
1718  val[i * nvars + v - nremovedentries] = val[i * nvars + v];
1719  ind[i * nvars + v - nremovedentries] = ind[i * nvars + v];
1720  }
1721  }
1722  }
1723 
1724  SCIP_CALL( SCIPlpiAddCols(lpi, blocksize, obj, lb, ub, NULL, blocksize*nvars - nremovedentries, beg, ind, val) );
1725 
1726  blocksizes[2 + b] = blocksize;
1727  roundingvars += blocksize;
1728 
1729  SCIPfreeBufferArray(scip, &val);
1730  SCIPfreeBufferArray(scip, &ind);
1731  SCIPfreeBufferArray(scip, &beg);
1732  SCIPfreeBufferArray(scip, &ub);
1733  SCIPfreeBufferArray(scip, &lb);
1734  SCIPfreeBufferArray(scip, &obj);
1735  }
1736 
1737  /* solve the problem (since we may encounter unboundedness, which sometimes causes trouble for the CPLEX interior-point solver,
1738  * we use the dual Simplex solver) */
1739  SCIP_CALL( SCIPlpiSolveDual(lpi) );
1740 
1741  /* get optimal objective value of the primal rounding problem (will be -infinity if infeasible) */
1742  SCIP_CALL( SCIPlpiGetObjval(lpi, &primalroundobj) );
1743 
1744  /* if the restricted primal problem is already dual infeasible, then the original primal has to be dual infeasible as
1745  * well, so the dual we actually want to solve is infeasible and we can cut the node off
1746  * the same is true by weak duality if the restricted primal already has a larger objective value than the current cutoff-bound */
1747  if ( SCIPlpiIsDualInfeasible(lpi) || SCIPisGE(scip, primalroundobj, SCIPgetCutoffbound(scip)) )
1748  {
1749  if ( SCIPlpiIsDualInfeasible(lpi) )
1750  {
1751  SCIPdebugMsg(scip, "Infeasibility of node %lld detected through primal rounding problem during warmstarting\n",
1752  SCIPnodeGetNumber(SCIPgetCurrentNode(scip)));
1753 
1754  relaxdata->roundingprobinf++;
1755  }
1756  else if ( SCIPisGT(scip, primalroundobj, SCIPgetCutoffbound(scip)) )
1757  {
1758  SCIPdebugMsg(scip, "Suboptimality of node %lld detected through primal rounding problem during warmstarting:"
1759  "lower bound = %f > %f = cutoffbound\n", SCIPnodeGetNumber(SCIPgetCurrentNode(scip)), primalroundobj, SCIPgetCutoffbound(scip));
1760 
1761  relaxdata->roundingcutoff++;
1762  }
1763 
1764  /* free memory */
1765  SCIPfreeBufferArrayNull(scip, &startXval[nblocks]);
1766  SCIPfreeBufferArrayNull(scip, &startXcol[nblocks]);
1767  SCIPfreeBufferArrayNull(scip, &startXrow[nblocks]);
1768  for (b = 0; b < nblocks; b++)
1769  {
1770  SCIPfreeBufferArrayNull(scip,&blockeigenvectors[b]);
1771  SCIPfreeBufferArrayNull(scip,&blockeigenvalues[b]);
1772  SCIPfreeBufferArrayNull(scip, &startXval[b]);
1773  SCIPfreeBufferArrayNull(scip, &startXcol[b]);
1774  SCIPfreeBufferArrayNull(scip, &startXrow[b]);
1775  SCIPfreeBufferArrayNull(scip, &startZval[b]);
1776  SCIPfreeBufferArrayNull(scip, &startZcol[b]);
1777  SCIPfreeBufferArrayNull(scip, &startZrow[b]);
1778  }
1779  SCIPfreeBufferArray(scip, &blocksizes);
1780  SCIPfreeBufferArray(scip, &blockeigenvectors);
1781  SCIPfreeBufferArray(scip, &blockeigenvalues);
1782  SCIPfreeBufferArrayNull(scip, &startXval);
1783  SCIPfreeBufferArrayNull(scip, &startXcol);
1784  SCIPfreeBufferArrayNull(scip, &startXrow);
1785  SCIPfreeBufferArrayNull(scip, &startXnblocknonz);
1786  SCIPfreeBufferArrayNull(scip, &startZval);
1787  SCIPfreeBufferArrayNull(scip, &startZcol);
1788  SCIPfreeBufferArrayNull(scip, &startZrow);
1789  SCIPfreeBufferArrayNull(scip, &startZnblocknonz);
1790  SCIPfreeBufferArray(scip, &starty);
1791 
1792  TIMEOFDAY_CALL( gettimeofday(&currenttime, NULL) );/*lint !e438, !e550, !e641 */
1793  relaxdata->roundingprobtime += (SCIP_Real) currenttime.tv_sec + (SCIP_Real) currenttime.tv_usec / 1e6 - (SCIP_Real) starttime.tv_sec - (SCIP_Real) starttime.tv_usec / 1e6;
1794 
1795  relaxdata->feasible = FALSE;
1796  *result = SCIP_CUTOFF;
1797  return SCIP_OKAY;
1798  }
1799  else if ( relaxdata->warmstartroundonlyinf )
1800  {
1801  /* in this case we only cared about checking infeasibility and coldstart now */
1802  SCIPfreeBufferArrayNull(scip, &startXval[nblocks]);
1803  SCIPfreeBufferArrayNull(scip, &startXcol[nblocks]);
1804  SCIPfreeBufferArrayNull(scip, &startXrow[nblocks]);
1805  for (b = 0; b < nblocks; b++)
1806  {
1807  SCIPfreeBufferArrayNull(scip, &blockeigenvectors[b]);
1808  SCIPfreeBufferArrayNull(scip, &blockeigenvalues[b]);
1809  SCIPfreeBufferArrayNull(scip, &startXval[b]);
1810  SCIPfreeBufferArrayNull(scip, &startXcol[b]);
1811  SCIPfreeBufferArrayNull(scip, &startXrow[b]);
1812  SCIPfreeBufferArrayNull(scip, &startZval[b]);
1813  SCIPfreeBufferArrayNull(scip, &startZcol[b]);
1814  SCIPfreeBufferArrayNull(scip, &startZrow[b]);
1815  }
1816  SCIPfreeBufferArray(scip, &blocksizes);
1817  SCIPfreeBufferArray(scip, &blockeigenvectors);
1818  SCIPfreeBufferArray(scip, &blockeigenvalues);
1819  SCIPfreeBufferArrayNull(scip, &startXval);
1820  SCIPfreeBufferArrayNull(scip, &startXcol);
1821  SCIPfreeBufferArrayNull(scip, &startXrow);
1822  SCIPfreeBufferArrayNull(scip, &startXnblocknonz);
1823  SCIPfreeBufferArrayNull(scip, &startZval);
1824  SCIPfreeBufferArrayNull(scip, &startZcol);
1825  SCIPfreeBufferArrayNull(scip, &startZrow);
1826  SCIPfreeBufferArrayNull(scip, &startZnblocknonz);
1827  SCIPfreeBufferArray(scip, &starty);
1828 
1829  TIMEOFDAY_CALL( gettimeofday(&currenttime, NULL) );/*lint !e438, !e550, !e641 */
1830  relaxdata->roundingprobtime += (SCIP_Real) currenttime.tv_sec + (SCIP_Real) currenttime.tv_usec / 1e6 - (SCIP_Real) starttime.tv_sec - (SCIP_Real) starttime.tv_usec / 1e6;
1831 
1832  SCIP_CALL(SCIPsdpiSolve(sdpi, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, startsetting, enforceslater, timelimit));
1833  goto solved;
1834  }
1835  else if ( ! SCIPlpiIsOptimal(lpi) )
1836  {
1837  SCIPdebugMsg(scip, "Solving without warmstart since solving of the primal rounding problem failed with status %d!\n", SCIPlpiGetInternalStatus(lpi));
1838  relaxdata->primalroundfails++;
1839 
1840  /* since warmstart computation failed, we solve without warmstart, free memory and skip the remaining warmstarting code */
1841  SCIPfreeBufferArrayNull(scip, &startXval[nblocks]);
1842  SCIPfreeBufferArrayNull(scip, &startXcol[nblocks]);
1843  SCIPfreeBufferArrayNull(scip, &startXrow[nblocks]);
1844  for (b = 0; b < nblocks; b++)
1845  {
1846  SCIPfreeBufferArrayNull(scip, &blockeigenvectors[b]);
1847  SCIPfreeBufferArrayNull(scip, &blockeigenvalues[b]);
1848  SCIPfreeBufferArrayNull(scip, &startXval[b]);
1849  SCIPfreeBufferArrayNull(scip, &startXcol[b]);
1850  SCIPfreeBufferArrayNull(scip, &startXrow[b]);
1851  SCIPfreeBufferArrayNull(scip, &startZval[b]);
1852  SCIPfreeBufferArrayNull(scip, &startZcol[b]);
1853  SCIPfreeBufferArrayNull(scip, &startZrow[b]);
1854  }
1855  SCIPfreeBufferArray(scip, &blocksizes);
1856  SCIPfreeBufferArray(scip, &blockeigenvectors);
1857  SCIPfreeBufferArray(scip, &blockeigenvalues);
1858  SCIPfreeBufferArrayNull(scip, &startXval);
1859  SCIPfreeBufferArrayNull(scip, &startXcol);
1860  SCIPfreeBufferArrayNull(scip, &startXrow);
1861  SCIPfreeBufferArrayNull(scip, &startXnblocknonz);
1862  SCIPfreeBufferArrayNull(scip, &startZval);
1863  SCIPfreeBufferArrayNull(scip, &startZcol);
1864  SCIPfreeBufferArrayNull(scip, &startZrow);
1865  SCIPfreeBufferArrayNull(scip, &startZnblocknonz);
1866  SCIPfreeBufferArray(scip, &starty);
1867 
1868  TIMEOFDAY_CALL( gettimeofday(&currenttime, NULL) );/*lint !e438, !e550, !e641 */
1869  relaxdata->roundingprobtime += (SCIP_Real) currenttime.tv_sec + (SCIP_Real) currenttime.tv_usec / 1e6 - (SCIP_Real) starttime.tv_sec - (SCIP_Real) starttime.tv_usec / 1e6;
1870 
1871  SCIP_CALL(SCIPsdpiSolve(sdpi, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, startsetting, enforceslater, timelimit));
1872  goto solved;
1873  }
1874  else
1875  {
1876  SCIP_Real* optev;
1877  int evpos;
1878 
1879  /* the problem was solved to optimality: we construct the primal matrix using the computed eigenvalues */
1880  SCIP_CALL( SCIPallocBufferArray(scip, &optev, roundingvars) );
1881 
1882  SCIP_CALL( SCIPlpiGetSol(lpi, NULL, optev, NULL, NULL, NULL) );
1883 
1884  /* build varbound block */
1885  pos = blocksizes[1]; /* to save some sorting later, the startX arrays should start with the LP block */
1886  evpos = 0;
1887  for (v = 0; v < nvars; v++)
1888  {
1889  startXrow[nblocks][pos] = 2 * nrows + 2 * v;
1890  startXcol[nblocks][pos] = 2 * nrows + 2 * v;
1891  if ( ! SCIPisInfinity(scip, -1 * SCIPvarGetLbLocal(vars[v])) )
1892  {
1893  startXval[nblocks][pos] = optev[evpos];
1894  evpos++;
1895  }
1896  else
1897  startXval[nblocks][pos] = SCIPinfinity(scip);
1898  pos++;
1899 
1900  startXrow[nblocks][pos] = 2 * nrows + 2 * v + 1;
1901  startXcol[nblocks][pos] = 2 * nrows + 2 * v + 1;
1902  if ( ! SCIPisInfinity(scip, SCIPvarGetUbLocal(vars[v])) )
1903  {
1904 
1905  startXval[nblocks][pos] = optev[evpos];
1906  evpos++;
1907  }
1908  else
1909  startXval[nblocks][pos] = SCIPinfinity(scip);
1910  pos++;
1911  }
1912  assert( evpos == blocksizes[0] );
1913 
1914  /* build LP block */
1915  pos = 0;
1916  evpos = blocksizes[0];
1917  for (r = 0; r < nrows; r++)
1918  {
1919  row = rows[r];
1920 
1921  rowlhs = SCIProwGetLhs(row) - SCIProwGetConstant(row);
1922  rowrhs = SCIProwGetRhs(row) - SCIProwGetConstant(row);
1923 
1924  startXrow[nblocks][pos] = 2 * r;
1925  startXcol[nblocks][pos] = 2 * r;
1926  if ( ! SCIPisInfinity(scip, -1 * rowlhs) )
1927  {
1928  startXval[nblocks][pos] = optev[evpos];
1929  evpos++;
1930  }
1931  else
1932  startXval[nblocks][pos] = SCIPinfinity(scip);
1933  pos++;
1934 
1935  startXrow[nblocks][pos] = 2 * r + 1;
1936  startXcol[nblocks][pos] = 2 * r + 1;
1937  if ( ! SCIPisInfinity(scip, rowrhs) )
1938  {
1939  startXval[nblocks][pos] = optev[evpos];
1940  evpos++;
1941  }
1942  else
1943  startXval[nblocks][pos] = SCIPinfinity(scip);
1944  pos++;
1945  }
1946  assert( evpos == blocksizes[0] + blocksizes[1] );
1947 
1948  startXnblocknonz[nblocks] = blocksizes[0] + blocksizes[1];
1949 
1950  /* build SDP blocks */
1951  pos = blocksizes[0] + blocksizes[1];
1952  for (b = 0; b < nblocks; b++)
1953  {
1954  blocksize = blocksizes[2 + b];
1955  matrixsize = blocksize * blocksize;
1956 
1957  /* duplicate memory of eigenvectors to compute diag(lambda_i^*) * U^T */
1958  SCIP_CALL( SCIPduplicateBufferArray(scip, &scaledeigenvectors, blockeigenvectors[b], matrixsize) );
1959 
1960  /* compute diag(lambda_i_+) * U^T */
1961  SCIP_CALL( scaleTransposedMatrix(blocksize, scaledeigenvectors, &(optev[pos])) );
1962 
1963  /* allocate memory for full X matrix */
1964  SCIP_CALL( SCIPallocBufferArray(scip, &fullXmatrix, matrixsize) );
1965 
1966  /* compute U * [diag(lambda_i_+) * U^T] (note that transposes are switched because LAPACK/Fortran uses column-first-format) */
1967  SCIP_CALL( SCIPlapackMatrixMatrixMult(blocksizes[2 + b], blocksizes[2 + b], blockeigenvectors[b], TRUE, blocksizes[2 + b], blocksizes[2 + b],
1968  scaledeigenvectors, FALSE, fullXmatrix) );
1969 
1970  /* extract sparse matrix */
1971  startXnblocknonz[b] = 0;
1972  epsilon = SCIPepsilon(scip);
1973  for (r = 0; r < blocksize; r++)
1974  {
1975  for (c = r; c < blocksize; c++)
1976  {
1977  matrixpos = r * blocksize + c;
1978  if ( REALABS(fullXmatrix[matrixpos]) > epsilon )
1979  {
1980  startXrow[b][startXnblocknonz[b]] = r;
1981  startXcol[b][startXnblocknonz[b]] = c;
1982  startXval[b][startXnblocknonz[b]] = fullXmatrix[matrixpos];
1983  startXnblocknonz[b]++;
1984  }
1985  }
1986  }
1987  pos += blocksizes[2 + b];
1988  SCIPfreeBufferArray(scip, &fullXmatrix);
1989  SCIPfreeBufferArray(scip, &scaledeigenvectors);
1990  }
1991  SCIPfreeBufferArray(scip, &optev);
1992  }
1993 
1994  /* solve dual rounding problem */
1995 
1996  /* allocate memory for LP and varbound-block (we take a worst-case guess here) */
1997  matrixsize = 2 * nvars + 2 * nrows;
1998  SCIP_CALL( SCIPallocBufferArray(scip, &startZrow[nblocks], matrixsize) );
1999  SCIP_CALL( SCIPallocBufferArray(scip, &startZcol[nblocks], matrixsize) );
2000  SCIP_CALL( SCIPallocBufferArray(scip, &startZval[nblocks], matrixsize) );
2001 
2002  /* clear the old LP */
2003  SCIP_CALL( SCIPlpiClear(lpi) );
2004 
2005  /* we want to maximize for the primal rounding problem */
2006  SCIP_CALL( SCIPlpiChgObjsen(lpi, SCIP_OBJSEN_MINIMIZE) );
2007 
2008  /* compute number of columns */
2009  roundingvars = nvars;
2010  for (b = 0; b < nblocks; b++)
2011  roundingvars += blocksizes[2 + b];
2012 
2013  SCIP_CALL( SCIPallocBufferArray(scip, &obj, roundingvars) );
2014  SCIP_CALL( SCIPallocBufferArray(scip, &lb, roundingvars) );
2015  SCIP_CALL( SCIPallocBufferArray(scip, &ub, roundingvars) );
2016 
2017  for (v = 0; v < nvars; v++)
2018  {
2019  obj[SCIPsdpVarmapperGetSdpIndex(relaxdata->varmapper, vars[v])] = SCIPvarGetObj(vars[v]);
2020  lb[SCIPsdpVarmapperGetSdpIndex(relaxdata->varmapper, vars[v])] = SCIPvarGetLbLocal(vars[v]);
2021  ub[SCIPsdpVarmapperGetSdpIndex(relaxdata->varmapper, vars[v])] = SCIPvarGetUbLocal(vars[v]);
2022  }
2023 
2024  /* the eigenvalue-variables should all be non-negative, but do not appear in the objective */
2025  for (v = nvars; v < roundingvars; v++)
2026  {
2027  obj[v] = 0.0;
2028  lb[v] = 0.0;
2029  ub[v] = SCIPlpiInfinity(lpi);
2030  }
2031 
2032  /* initialize columns; rows will be added blockwise later (note that we reenter the whole problem each time
2033  * and do not allow warmstarts, we could store the LP- and bound-constraints between nodes (TODO, but would
2034  * need to check for added/removed cuts then), but warmstarting doesn't seem to make sense since the whole
2035  * SDP part is changed, which should form the main difficulty when solving (MI)SDPs */
2036  SCIP_CALL( SCIPlpiAddCols(lpi, roundingvars, obj, lb, ub, NULL, 0, NULL, NULL, NULL) );
2037 
2038  SCIPfreeBufferArray(scip, &ub);
2039  SCIPfreeBufferArray(scip, &lb);
2040  SCIPfreeBufferArray(scip, &obj);
2041 
2042  /* add LP rows */
2043  SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
2044 
2045  for (r = 0; r < nrows; r++)
2046  {
2047  row = rows[r];
2048  assert( row != NULL );
2049  rownnonz = SCIProwGetNNonz(row);
2050 
2051  rowvals = SCIProwGetVals(row);
2052  rowcols = SCIProwGetCols(row);
2053  rowlhs = SCIProwGetLhs(row) - SCIProwGetConstant(row);
2054  rowrhs = SCIProwGetRhs(row) - SCIProwGetConstant(row);
2055 
2056  SCIP_CALL( SCIPallocBufferArray(scip, &rowinds, rownnonz) );
2057 
2058  /* iterate over rowcols and get corresponding indices */
2059  for (i = 0; i < rownnonz; i++)
2060  rowinds[i] = SCIPsdpVarmapperGetSdpIndex(relaxdata->varmapper, SCIPcolGetVar(rowcols[i]));
2061 
2062  pos = 0;
2063 
2064  SCIP_CALL( SCIPlpiAddRows(lpi, 1, &rowlhs, &rowrhs, NULL, rownnonz, &pos, rowinds, rowvals) );
2065 
2066  SCIPfreeBufferArray(scip, &rowinds);
2067  }
2068 
2069  /* for each SDP-block add constraints linking y-variables to eigenvalues of Z matrix */
2070  startpos = nvars;
2071  for (b = 0; b < nblocks; b++)
2072  {
2073  /* get data for this SDP block */
2074  SCIP_CALL( SCIPconsSdpGetNNonz(scip, sdpblocks[b], NULL, &blockconstnnonz) );
2075  SCIP_CALL( SCIPallocBufferArray(scip, &blocknvarnonz, nvars) );
2076  SCIP_CALL( SCIPallocBufferArray(scip, &blockcol, nvars) );
2077  SCIP_CALL( SCIPallocBufferArray(scip, &blockrow, nvars) );
2078  SCIP_CALL( SCIPallocBufferArray(scip, &blockval, nvars) );
2079  SCIP_CALL( SCIPallocBufferArray(scip, &blockvars, nvars) );
2080  SCIP_CALL( SCIPallocBufferArray(scip, &blockconstcol, blockconstnnonz) );
2081  SCIP_CALL( SCIPallocBufferArray(scip, &blockconstrow, blockconstnnonz) );
2082  SCIP_CALL( SCIPallocBufferArray(scip, &blockconstval, blockconstnnonz) );
2083  blocksize = blocksizes[2 + b];
2084  matrixsize = blocksize * blocksize;
2085 
2086  SCIP_CALL( SCIPallocBufferArray(scip, &fullZmatrix, matrixsize) );
2087 
2088  SCIP_CALL( expandSparseMatrix(startZnblocknonz[b], blocksize, startZrow[b], startZcol[b], startZval[b], fullZmatrix) );
2089 
2090  SCIP_CALL( SCIPlapackComputeEigenvectorDecomposition(SCIPbuffer(scip), blocksize, fullZmatrix, blockeigenvalues[b], blockeigenvectors[b]) );
2091 
2092  arraylength = nvars;
2093  SCIP_CALL( SCIPconsSdpGetData(scip, sdpblocks[b], &blocknvars, &blocknnonz, &blocksize, &arraylength, blocknvarnonz,
2094  blockcol, blockrow, blockval, blockvars, &blockconstnnonz, blockconstcol, blockconstrow, blockconstval) );
2095 
2096  nroundingrows = blocksize * (blocksize + 1) * 0.5;
2097 
2098  SCIP_CALL( SCIPallocBufferArray(scip, &lhs, nroundingrows) );
2099  SCIP_CALL( SCIPallocBufferArray(scip, &rhs, nroundingrows) );
2100  SCIP_CALL( SCIPallocBufferArray(scip, &nblockrownonz , nroundingrows) );
2101  SCIP_CALL( SCIPallocBufferArray(scip, &blockrowcols , nroundingrows) );
2102  SCIP_CALL( SCIPallocBufferArray(scip, &blockrowvals , nroundingrows) );
2103 
2104  /* initialize lhs and rhs with 0 and allocate memory for nonzeros (we take the worst case of nvars y entries and blocksize lambda entries) */
2105  for (i = 0; i < nroundingrows; i++)
2106  {
2107  lhs[i] = 0.0;
2108  rhs[i] = 0.0;
2109 
2110  nblockrownonz[i] = 0;
2111  SCIP_CALL( SCIPallocBufferArray(scip, &blockrowcols[i], nvars + blocksize) );
2112  SCIP_CALL( SCIPallocBufferArray(scip, &blockrowvals[i], nvars + blocksize) );
2113  }
2114 
2115  /* iterate over constant matrix to compute right-hand sides of equality constraints */
2116  for (i = 0; i < blockconstnnonz; i++)
2117  {
2118  assert( lhs[SCIPconsSdpCompLowerTriangPos(blockconstrow[i], blockconstcol[i])] == 0.0 ); /* there should only be a single entry per index-pair */
2119  lhs[SCIPconsSdpCompLowerTriangPos(blockconstrow[i], blockconstcol[i])] = blockconstval[i];
2120  rhs[SCIPconsSdpCompLowerTriangPos(blockconstrow[i], blockconstcol[i])] = blockconstval[i];
2121  }
2122 
2123  /* iterate over all nonzeros to add them to the roundingrows */
2124  for (v = 0; v < blocknvars; v++)
2125  {
2126  varind = SCIPsdpVarmapperGetSdpIndex(relaxdata->varmapper, blockvars[v]);
2127 
2128  for (i = 0; i < blocknvarnonz[v]; i++)
2129  {
2130  pos = SCIPconsSdpCompLowerTriangPos(blockrow[v][i], blockcol[v][i]);
2131  blockrowcols[pos][nblockrownonz[pos]] = varind;
2132  blockrowvals[pos][nblockrownonz[pos]] = blockval[v][i];
2133  nblockrownonz[pos]++;
2134  }
2135  }
2136 
2137  /* add entries corresponding to eigenvalues */
2138  for (evind = 0; evind < blocksize; evind++)
2139  {
2140  for (i = 0; i < blocksize; i++)
2141  {
2142  for (j = 0; j <= i; j++)
2143  {
2144  /* for index (i,j) and every eigenvector v, we get an entry -V_iv *V_jv (we get the -1 by transferring this to the left-hand side of the equation)
2145  * entry V_iv corresponds to entry i of the v-th eigenvector, which is given as the v-th row of the eigenvectors array */
2146  if ( SCIPisGT(scip, REALABS(-1 * blockeigenvectors[b][evind * blocksize + i] * blockeigenvectors[b][evind * blocksize + j]), 0.0) )
2147  {
2148  pos = SCIPconsSdpCompLowerTriangPos(i, j);
2149  blockrowcols[pos][nblockrownonz[pos]] = startpos + evind;
2150  blockrowvals[pos][nblockrownonz[pos]] = -1 * blockeigenvectors[b][evind * blocksize + i] * blockeigenvectors[b][evind * blocksize + j];
2151  nblockrownonz[pos]++;
2152  }
2153  }
2154  }
2155  }
2156  startpos += blocksize;
2157 
2158  pos = 0;
2159  /* add the rows one by one */
2160  for (r = 0; r < nroundingrows; r++)
2161  {
2162  SCIP_CALL( SCIPlpiAddRows(lpi, 1, &lhs[r], &rhs[r], NULL, nblockrownonz[r], &pos, blockrowcols[r], blockrowvals[r]) );
2163  SCIPfreeBufferArray(scip, &blockrowvals[r]);
2164  SCIPfreeBufferArray(scip, &blockrowcols[r]);
2165  }
2166 
2167  SCIPfreeBufferArray(scip, &blockrowvals);
2168  SCIPfreeBufferArray(scip, &blockrowcols);
2169  SCIPfreeBufferArray(scip, &nblockrownonz);
2170  SCIPfreeBufferArray(scip, &rhs);
2171  SCIPfreeBufferArray(scip, &lhs);
2172  SCIPfreeBufferArray(scip, &fullZmatrix);
2173  SCIPfreeBufferArray(scip, &blockconstval);
2174  SCIPfreeBufferArray(scip, &blockconstrow);
2175  SCIPfreeBufferArray(scip, &blockconstcol);
2176  SCIPfreeBufferArray(scip, &blockvars);
2177  SCIPfreeBufferArray(scip, &blockval);
2178  SCIPfreeBufferArray(scip, &blockrow);
2179  SCIPfreeBufferArray(scip, &blockcol);
2180  SCIPfreeBufferArray(scip, &blocknvarnonz);
2181  }
2182 
2183  /* solve the problem (for some reason dual simplex seems to work better here) */
2184  SCIP_CALL( SCIPlpiSolveDual(lpi) );
2185 
2186  if ( ! SCIPlpiIsOptimal(lpi) )
2187  {
2188  SCIPdebugMsg(scip, "Solution of dual rounding problem failed with status %d, continuing without warmstart\n", SCIPlpiGetInternalStatus(lpi));
2189  relaxdata->dualroundfails++;
2190 
2191  /* free memory */
2192  SCIPfreeBufferArrayNull(scip, &startZval[nblocks]);
2193  SCIPfreeBufferArrayNull(scip, &startZcol[nblocks]);
2194  SCIPfreeBufferArrayNull(scip, &startZrow[nblocks]);
2195  SCIPfreeBufferArrayNull(scip, &startXval[nblocks]);
2196  SCIPfreeBufferArrayNull(scip, &startXcol[nblocks]);
2197  SCIPfreeBufferArrayNull(scip, &startXrow[nblocks]);
2198  for (b = 0; b < nblocks; b++)
2199  {
2200  SCIPfreeBufferArrayNull(scip, &blockeigenvectors[b]);
2201  SCIPfreeBufferArrayNull(scip, &blockeigenvalues[b]);
2202  SCIPfreeBufferArrayNull(scip, &startZval[b]);
2203  SCIPfreeBufferArrayNull(scip, &startZcol[b]);
2204  SCIPfreeBufferArrayNull(scip, &startZrow[b]);
2205  SCIPfreeBufferArrayNull(scip, &startXval[b]);
2206  SCIPfreeBufferArrayNull(scip, &startXcol[b]);
2207  SCIPfreeBufferArrayNull(scip, &startXrow[b]);
2208  }
2209  SCIPfreeBufferArray(scip, &blocksizes);
2210  SCIPfreeBufferArray(scip, &blockeigenvectors);
2211  SCIPfreeBufferArray(scip, &blockeigenvalues);
2212  SCIPfreeBufferArrayNull(scip, &startXval);
2213  SCIPfreeBufferArrayNull(scip, &startXcol);
2214  SCIPfreeBufferArrayNull(scip, &startXrow);
2215  SCIPfreeBufferArrayNull(scip, &startXnblocknonz);
2216  SCIPfreeBufferArrayNull(scip, &startZval);
2217  SCIPfreeBufferArrayNull(scip, &startZcol);
2218  SCIPfreeBufferArrayNull(scip, &startZrow);
2219  SCIPfreeBufferArrayNull(scip, &startZnblocknonz);
2220  SCIPfreeBufferArray(scip, &starty);
2221 
2222  TIMEOFDAY_CALL( gettimeofday(&currenttime, NULL) );/*lint !e438, !e550, !e641 */
2223  relaxdata->roundingprobtime += (SCIP_Real) currenttime.tv_sec + (SCIP_Real) currenttime.tv_usec / 1e6 - (SCIP_Real) starttime.tv_sec - (SCIP_Real) starttime.tv_usec / 1e6;
2224 
2225  /* since warmstart computation failed, we solve without warmstart, free memory and skip the remaining warmstarting code */
2226  SCIP_CALL(SCIPsdpiSolve(sdpi, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, startsetting, enforceslater, timelimit));
2227 
2228  goto solved;
2229  }
2230  else
2231  {
2232  SCIP_Real* optev;
2233 
2234  relaxdata->roundstartsuccess++;
2235 
2236  /* the problem was solved to optimality: we construct the dual vector and matrix using the computed eigenvalues */
2237  SCIP_CALL( SCIPallocBufferArray(scip, &optev, nvars + roundingvars) );
2238  SCIP_CALL( SCIPlpiGetSol(lpi, &dualroundobj, optev, NULL, NULL, NULL) );
2239 
2240  /* if the objective values of the primal and dual rounding problem agree, the problem has been solved to optimality,
2241  * since both of them are respective restrictions of the original primal and dual problem */
2242  if ( SCIPisEQ(scip, primalroundobj, dualroundobj) )
2243  {
2244  SCIP_SOL* scipsol; /* TODO: eliminate this */
2245  SCIP_CONS* savedcons;
2246 
2247  SCIPdebugMsg(scip, "Node %lld solved to optimality through rounding problems with optimal objective %f\n",
2248  SCIPnodeGetNumber(SCIPgetCurrentNode(scip)), dualroundobj);
2249 
2250  relaxdata->roundingoptimal++;
2251 
2252  TIMEOFDAY_CALL( gettimeofday(&currenttime, NULL) );/*lint !e438, !e550, !e641 */
2253  relaxdata->roundingprobtime += (SCIP_Real) currenttime.tv_sec + (SCIP_Real) currenttime.tv_usec / 1e6 - (SCIP_Real) starttime.tv_sec - (SCIP_Real) starttime.tv_usec / 1e6;
2254 
2255  /* create SCIP solution (first nvars entries of optev correspond to y variables) */
2256  SCIP_CALL( SCIPcreateSol(scip, &scipsol, NULL) );
2257  SCIP_CALL( SCIPsetSolVals(scip, scipsol, nvars, vars, optev) );
2258 
2259  *lowerbound = dualroundobj;
2260  relaxdata->objval = dualroundobj;
2261 
2262  /* copy solution */
2263  SCIP_CALL( SCIPsetRelaxSolValsSol(scip, scipsol, TRUE) );
2264 
2265  relaxdata->feasible = TRUE;
2266  *result = SCIP_SUCCESS;
2267 
2268  /* save solution for warmstarts */
2269  if ( relaxdata->warmstart )
2270  {
2271  char consname[SCIP_MAXSTRLEN];
2272 #ifndef NDEBUG
2273  int snprintfreturn; /* this is used to assert that the SCIP string concatenation works */
2274 #endif
2275 
2276 #ifndef NDEBUG
2277  snprintfreturn = SCIPsnprintf(consname, SCIP_MAXSTRLEN, "saved_relax_sol_%d", SCIPnodeGetNumber(SCIPgetCurrentNode(scip)));
2278  assert( snprintfreturn < SCIP_MAXSTRLEN ); /* check whether name fit into string */
2279 #else
2280  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "saved_relax_sol_%d", SCIPnodeGetNumber(SCIPgetCurrentNode(scip)));
2281 #endif
2282  SCIP_CALL( createConsSavesdpsol(scip, &savedcons, consname, SCIPnodeGetNumber(SCIPgetCurrentNode(scip)), scipsol,
2283  maxprimalentry, nblocks + 1, startXnblocknonz, startXrow, startXcol, startXval) );
2284 
2285  SCIP_CALL( SCIPaddCons(scip, savedcons) );
2286  SCIP_CALL( SCIPreleaseCons(scip, &savedcons) );
2287  }
2288 
2289  SCIP_CALL( SCIPfreeSol(scip, &scipsol) );
2290 
2291  /* free memory */
2292  SCIPfreeBufferArray(scip, &optev);
2293  SCIPfreeBufferArrayNull(scip, &startZval[nblocks]);
2294  SCIPfreeBufferArrayNull(scip, &startZcol[nblocks]);
2295  SCIPfreeBufferArrayNull(scip, &startZrow[nblocks]);
2296  SCIPfreeBufferArrayNull(scip, &startXval[nblocks]);
2297  SCIPfreeBufferArrayNull(scip, &startXcol[nblocks]);
2298  SCIPfreeBufferArrayNull(scip, &startXrow[nblocks]);
2299  for (b = 0; b < nblocks; b++)
2300  {
2301  SCIPfreeBufferArrayNull(scip,&blockeigenvectors[b]);
2302  SCIPfreeBufferArrayNull(scip,&blockeigenvalues[b]);
2303  SCIPfreeBufferArrayNull(scip, &startXval[b]);
2304  SCIPfreeBufferArrayNull(scip, &startXcol[b]);
2305  SCIPfreeBufferArrayNull(scip, &startXrow[b]);
2306  SCIPfreeBufferArrayNull(scip, &startZval[b]);
2307  SCIPfreeBufferArrayNull(scip, &startZcol[b]);
2308  SCIPfreeBufferArrayNull(scip, &startZrow[b]);
2309  }
2310  SCIPfreeBufferArray(scip, &blocksizes);
2311  SCIPfreeBufferArray(scip, &blockeigenvectors);
2312  SCIPfreeBufferArray(scip, &blockeigenvalues);
2313  SCIPfreeBufferArrayNull(scip, &startXval);
2314  SCIPfreeBufferArrayNull(scip, &startXcol);
2315  SCIPfreeBufferArrayNull(scip, &startXrow);
2316  SCIPfreeBufferArrayNull(scip, &startXnblocknonz);
2317  SCIPfreeBufferArrayNull(scip, &startZval);
2318  SCIPfreeBufferArrayNull(scip, &startZcol);
2319  SCIPfreeBufferArrayNull(scip, &startZrow);
2320  SCIPfreeBufferArrayNull(scip, &startZnblocknonz);
2321  SCIPfreeBufferArray(scip, &starty);
2322 
2323  return SCIP_OKAY;
2324  }
2325 
2326  /* adjust dual vector */
2327  for (v = 0; v < nvars; v++)
2328  {
2329  if ( relaxdata->warmstartiptype == 1 )
2330  {
2331  /* we take a convex combination with 0, so we just scale */
2332  starty[v] = (1 - relaxdata->warmstartipfactor) * optev[v];
2333  }
2334  else if ( relaxdata->warmstartiptype == 2 )
2335  {
2336  /* take the convex combination with the saved analytic center */
2337  starty[v] = (1 - relaxdata->warmstartipfactor) * optev[v] + relaxdata->warmstartipfactor * SCIPgetSolVal(scip, relaxdata->ipy, vars[v]);
2338  }
2339  }
2340 
2341  /* build Z matrix */
2342  pos = nvars;
2343  for (b = 0; b < nblocks; b++)
2344  {
2345  blocksize = blocksizes[2 + b];
2346  matrixsize = blocksize * blocksize;
2347  /* duplicate memory of eigenvectors to compute diag(lambda_i^*) * U^T */
2348  SCIP_CALL( SCIPduplicateBufferArray(scip, &scaledeigenvectors, blockeigenvectors[b], matrixsize) );
2349 
2350  /* compute diag(lambda_i_+) * U^T */
2351  SCIP_CALL( scaleTransposedMatrix(blocksize, scaledeigenvectors, &(optev[pos])) );
2352 
2353  /* allocate memory for full Z matrix */
2354  SCIP_CALL( SCIPallocBufferArray(scip, &fullZmatrix, matrixsize) );
2355 
2356  /* compute U * [diag(lambda_i_+) * U^T] (note that transposes are switched because LAPACK uses column-first-format) */
2357  SCIP_CALL( SCIPlapackMatrixMatrixMult(blocksize, blocksize, blockeigenvectors[b], TRUE, blocksize, blocksize,
2358  scaledeigenvectors, FALSE, fullZmatrix) );
2359 
2360  /* extract sparse matrix */
2361  startZnblocknonz[b] = 0;
2362  epsilon = SCIPepsilon(scip);
2363  for (r = 0; r < blocksize; r++)
2364  {
2365  for (c = r; c < blocksize; c++)
2366  {
2367  matrixpos = r * blocksize + c;
2368  if ( REALABS(fullZmatrix[matrixpos]) > epsilon )
2369  {
2370  startZrow[b][startZnblocknonz[b]] = r;
2371  startZcol[b][startZnblocknonz[b]] = c;
2372  startZval[b][startZnblocknonz[b]] = fullZmatrix[matrixpos];
2373  startZnblocknonz[b]++;
2374  }
2375  }
2376  }
2377  pos += blocksize;
2378  SCIPfreeBufferArray(scip, &fullZmatrix);
2379  SCIPfreeBufferArray(scip, &scaledeigenvectors);
2380  SCIPfreeBufferArray(scip, &blockeigenvectors[b]);
2381  SCIPfreeBufferArray(scip, &blockeigenvalues[b]);
2382  }
2383 
2384  SCIPfreeBufferArray(scip, &optev);
2385  SCIPfreeBufferArray(scip, &blockeigenvectors);
2386  SCIPfreeBufferArray(scip, &blockeigenvalues);
2387  SCIPfreeBufferArray(scip, &blocksizes);
2388 
2389  /* build LP and varbound block of Z matrix */
2390 
2391  /* to get a positive definite matrix, all the entries need to be strictly positive */
2392  startZnblocknonz[b] = 2 * nrows + 2 * nvars;
2393 
2394  /* fill LP-block */
2395  for (r = 0; r < nrows; r++)
2396  {
2397  /* compute row value for current solution */
2398  rowval = 0.0;
2399  rownnonz = SCIProwGetNNonz(rows[r]);
2400  rowvals = SCIProwGetVals(rows[r]);
2401  rowcols = SCIProwGetCols(rows[r]);
2402 
2403  for (i = 0; i < rownnonz; i++)
2404  rowval += starty[SCIPsdpVarmapperGetSdpIndex(relaxdata->varmapper, SCIPcolGetVar(rowcols[i]))] * rowvals[i];
2405 
2406  startZrow[b][2*r] = 2*r;
2407  startZcol[b][2*r] = 2*r;
2408  startZval[b][2*r] = rowval - (SCIProwGetLhs(rows[r]) - SCIProwGetConstant(rows[r]));
2409 
2410  startZrow[b][2*r + 1] = 2*r + 1;
2411  startZcol[b][2*r + 1] = 2*r + 1;
2412  startZval[b][2*r + 1] = SCIProwGetRhs(rows[r]) - SCIProwGetConstant(rows[r]) - rowval;
2413  }
2414 
2415  /* fill varbound block */
2416  for (v = 0; v < nvars; v++)
2417  {
2418  startZrow[b][2*nrows + 2*v] = 2*nrows + 2*v;
2419  startZcol[b][2*nrows + 2*v] = 2*nrows + 2*v;
2420  startZval[b][2*nrows + 2*v] = starty[SCIPsdpVarmapperGetSdpIndex(relaxdata->varmapper, vars[v])] - SCIPvarGetLbLocal(vars[v]);
2421 
2422  startZrow[b][2*nrows + 2*v + 1] = 2*nrows + 2*v + 1;
2423  startZcol[b][2*nrows + 2*v + 1] = 2*nrows + 2*v + 1;
2424  startZval[b][2*nrows + 2*v + 1] = SCIPvarGetUbLocal(vars[v]) - starty[SCIPsdpVarmapperGetSdpIndex(relaxdata->varmapper, vars[v])];
2425  }
2426  }
2427 
2428  TIMEOFDAY_CALL( gettimeofday(&currenttime, NULL) );/*lint !e438, !e550, !e641 */
2429  relaxdata->roundingprobtime += (SCIP_Real) currenttime.tv_sec + (SCIP_Real) currenttime.tv_usec / 1e6 - (SCIP_Real) starttime.tv_sec - (SCIP_Real) starttime.tv_usec / 1e6;
2430  }
2431 
2432  /* if we saved the whole primal solution before, we can set it at once */
2433  if ( relaxdata->warmstartprimaltype == 3 )
2434  {
2435  /* if we wanted to use the rounding problem, we already created the solution and just want to do the convex combination */
2436  if ( relaxdata->warmstartproject != 4 )
2437  {
2438  SCIP_CALL( SCIPconsSavesdpsolGetPrimalMatrixNonzeros(scip, conss[parentconsind], nblocks + 1, startXnblocknonz) );
2439 
2440  /* allocate sufficient memory (memory for LP-block was already allocated); we allocate an extra blocksize for adding the diagonal matrix or analytic center */
2441  if ( relaxdata->warmstartproject == 3 )
2442  {
2443  int matrixsize;
2444 
2445  /* since we cannot compute the number of nonzeros of the projection beforehand, we allocate the maximum possible (blocksize * (blocksize + 1) / 2) */
2446  for (b = 0; b < nblocks; b++)
2447  {
2448  matrixsize = SCIPconsSdpGetBlocksize(scip, sdpblocks[b]);
2449  matrixsize *= (matrixsize + 1) * 0.5;
2450 
2451  SCIP_CALL( SCIPallocBufferArray(scip, &startXrow[b], matrixsize) );
2452  SCIP_CALL( SCIPallocBufferArray(scip, &startXcol[b], matrixsize) );
2453  SCIP_CALL( SCIPallocBufferArray(scip, &startXval[b], matrixsize) );
2454  }
2455  }
2456  else if ( relaxdata->warmstartiptype == 1 )
2457  {
2458  for (b = 0; b < nblocks; b++)
2459  {
2460  SCIP_CALL( SCIPallocBufferArray(scip, &startXrow[b], startXnblocknonz[b] + SCIPconsSdpGetBlocksize(scip, sdpblocks[b])) );
2461  SCIP_CALL( SCIPallocBufferArray(scip, &startXcol[b], startXnblocknonz[b] + SCIPconsSdpGetBlocksize(scip, sdpblocks[b])) );
2462  SCIP_CALL( SCIPallocBufferArray(scip, &startXval[b], startXnblocknonz[b] + SCIPconsSdpGetBlocksize(scip, sdpblocks[b])) );
2463  }
2464  }
2465  else if ( relaxdata->warmstartiptype == 2 )
2466  {
2467  for (b = 0; b < nblocks; b++)
2468  {
2469  SCIP_CALL( SCIPallocBufferArray(scip, &startXrow[b], startXnblocknonz[b] + relaxdata->ipXnblocknonz[b]) );
2470  SCIP_CALL( SCIPallocBufferArray(scip, &startXcol[b], startXnblocknonz[b] + relaxdata->ipXnblocknonz[b]) );
2471  SCIP_CALL( SCIPallocBufferArray(scip, &startXval[b], startXnblocknonz[b] + relaxdata->ipXnblocknonz[b]) );
2472  }
2473  }
2474 
2475  SCIP_CALL( SCIPconsSavesdpsolGetPrimalMatrix(scip, conss[parentconsind], nblocks + 1, startXnblocknonz, startXrow, startXcol, startXval) );
2476  }
2477  }
2478 
2479  /* iterate over all blocks again to compute convex combination / projection */
2480 
2481  /* in case of warmstartprojpdsame first compute a single maximum value for all primal and dual blocks */
2482  if ( relaxdata->warmstartprojpdsame && SCIPisGT(scip, relaxdata->warmstartipfactor, 0.0) )
2483  {
2484  identitydiagonal = 1.0;
2485 
2486  for (b = 0; b < nblocks; b++)
2487  {
2488  for (i = 0; i < startZnblocknonz[b]; i++)
2489  {
2490  if ( REALABS(startZval[b][i]) > identitydiagonal )
2491  identitydiagonal = REALABS(startZval[b][i]);
2492  }
2493  for (i = 0; i < startXnblocknonz[b]; i++)
2494  {
2495  if ( REALABS(startXval[b][i]) > identitydiagonal )
2496  identitydiagonal = REALABS(startXval[b][i]);
2497  }
2498  }
2499  identitydiagonal *= relaxdata->warmstartipfactor; /* the diagonal entries of the scaled identity matrix */
2500  }
2501 
2502  for (b = 0; b < nblocks; b++)
2503  {
2504  /* compute projection onto psd cone (computed as U * diag(lambda_i_+) * U^T where U consists of the eigenvectors of the matrix) */
2505  if ( relaxdata->warmstartproject == 3 )
2506  {
2507  SCIP_Real* fullXmatrix;
2508  SCIP_Real* eigenvalues;
2509  SCIP_Real* eigenvectors;
2510  SCIP_Real* scaledeigenvectors;
2511  SCIP_Real matrixsize;
2512  SCIP_Real epsilon;
2513  int c;
2514  int matrixpos;
2515 
2516  matrixsize = blocksize * blocksize;
2517 
2518  SCIP_CALL( SCIPallocBufferArray(scip, &fullXmatrix, matrixsize) );
2519  SCIP_CALL( SCIPallocBufferArray(scip, &eigenvalues, blocksize) );
2520  SCIP_CALL( SCIPallocBufferArray(scip, &eigenvectors, matrixsize) );
2521 
2522  SCIP_CALL( expandSparseMatrix(startXnblocknonz[b], blocksize, startXrow[b], startXcol[b], startXval[b], fullXmatrix) );
2523 
2524  SCIP_CALL( SCIPlapackComputeEigenvectorDecomposition(SCIPbuffer(scip), blocksize, fullXmatrix, eigenvalues, eigenvectors) );
2525 
2526  /* duplicate memory of eigenvectors to compute diag(lambda_i_+) * U^T */
2527  SCIP_CALL( SCIPduplicateBufferArray(scip, &scaledeigenvectors, eigenvectors, matrixsize) );
2528 
2529  /* set all negative eigenvalues to zero (using the property that LAPACK returns them in ascending order) */
2530  i = 0;
2531  while (i < blocksize && SCIPisLT(scip, eigenvalues[i], relaxdata->warmstartprojminevprimal) )
2532  {
2533  eigenvalues[i] = relaxdata->warmstartprojminevprimal;
2534  i++;
2535  }
2536 
2537  /* compute diag(lambda_i_+) * U^T */
2538  SCIP_CALL( scaleTransposedMatrix(blocksize, scaledeigenvectors, eigenvalues) );
2539 
2540  /* compute U * [diag(lambda_i_+) * U^T] (note that transposes are switched because LAPACK uses column-first-format) */
2541  SCIP_CALL( SCIPlapackMatrixMatrixMult(blocksize, blocksize, eigenvectors, TRUE, blocksize, blocksize, scaledeigenvectors,
2542  FALSE, fullXmatrix) );
2543 
2544  /* extract sparse matrix from projection */
2545  startXnblocknonz[b] = 0;
2546  epsilon = SCIPepsilon(scip);
2547  for (r = 0; r < blocksize; r++)
2548  {
2549  for (c = r; c < blocksize; c++)
2550  {
2551  matrixpos = r * blocksize + c;
2552  if ( REALABS(fullXmatrix[matrixpos]) > epsilon )
2553  {
2554  startXrow[b][startXnblocknonz[b]] = r;
2555  startXcol[b][startXnblocknonz[b]] = c;
2556  startXval[b][startXnblocknonz[b]] = fullXmatrix[matrixpos];
2557  startXnblocknonz[b]++;
2558  }
2559  }
2560  }
2561 
2562  /* free memory */
2563  SCIPfreeBufferArray(scip, &scaledeigenvectors);
2564  SCIPfreeBufferArray(scip, &eigenvectors);
2565  SCIPfreeBufferArray(scip, &eigenvalues);
2566  SCIPfreeBufferArray(scip, &fullXmatrix);
2567  }
2568 
2569  /* use convex combination between X and scaled identity matrix to move solution to the interior */
2570  if ( SCIPisGT(scip, relaxdata->warmstartipfactor, 0.0) )
2571  {
2572  if ( relaxdata->warmstartiptype == 1 )
2573  {
2574  /* compute maxprimalentry (should be at least one or warmstartprojminevprimal) */
2575  if ( ! relaxdata->warmstartprojpdsame )
2576  {
2577  if ( relaxdata->warmstartproject == 3 )
2578  maxprimalentry = relaxdata->warmstartprojminevprimal;
2579  else
2580  maxprimalentry = 1.0;
2581  for (i = 0; i < startXnblocknonz[b]; i++)
2582  {
2583  if ( REALABS(startXval[b][i]) > maxprimalentry )
2584  maxprimalentry = REALABS(startXval[b][i]);
2585  }
2586  identitydiagonal = relaxdata->warmstartipfactor * maxprimalentry; /* the diagonal entries of the scaled identity matrix */
2587  }
2588  blocksize = SCIPconsSdpGetBlocksize(scip, sdpblocks[b]);
2589 
2590  SCIP_CALL( SCIPallocBufferArray(scip, &diagentryexists, blocksize) ); /* TODO: could allocate this once for Z and X with max-blocksize */
2591  for (i = 0; i < blocksize; i++)
2592  diagentryexists[i] = FALSE;
2593 
2594  for (i = 0; i < startXnblocknonz[b]; i++)
2595  {
2596  if ( startXrow[b][i] == startXcol[b][i] )
2597  {
2598  startXval[b][i] = startXval[b][i] * (1 - relaxdata->warmstartipfactor) + identitydiagonal; /* add identity for diagonal entries */
2599  assert( startXval[b][i] >= 0.0 ); /* since the original matrix should have been positive semidefinite, diagonal entries should be >= 0 */
2600  diagentryexists[startXrow[b][i]] = TRUE;
2601  }
2602  else
2603  startXval[b][i] *= (1 - relaxdata->warmstartipfactor); /* since this is an off-diagonal entry, we scale towards zero */
2604  }
2605 
2606  /* if a diagonal entry was missing (because we had a zero row before), we have to add it to the end */
2607  for (i = 0; i < blocksize; i++)
2608  {
2609  if ( ! diagentryexists[i] )
2610  {
2611  startXrow[b][startXnblocknonz[b]] = i;
2612  startXcol[b][startXnblocknonz[b]] = i;
2613  startXval[b][startXnblocknonz[b]] = identitydiagonal;
2614  startXnblocknonz[b]++;
2615  }
2616  }
2617  SCIPfreeBufferArrayNull(scip, &diagentryexists);
2618  }
2619  else if ( relaxdata->warmstartiptype == 2 )
2620  {
2621  /* iterate once over all entries to multiply them with (1 - warmstartipfactor) */
2622  for (i = 0; i < startXnblocknonz[b]; i++)
2623  startXval[b][i] *= 1 - relaxdata->warmstartipfactor;
2624 
2625  /* merge the scaled interior point array into the warmstart array */
2626  SCIP_CALL( SCIPsdpVarfixerMergeArrays(SCIPblkmem(scip), SCIPepsilon(scip), relaxdata->ipXrow[b], relaxdata->ipXcol[b], relaxdata->ipXval[b], relaxdata->ipXnblocknonz[b], TRUE,
2627  relaxdata->warmstartipfactor, startXrow[b], startXcol[b], startXval[b], &(startXnblocknonz[b]), startXnblocknonz[b] + relaxdata->ipXnblocknonz[b]) );
2628  }
2629  }
2630  }
2631 
2632  for (b = 0; b < nblocks; b++)
2633  {
2634  /* use convex combination between Z and scaled identity matrix to move solution to the interior */
2635  if ( SCIPisGT(scip, relaxdata->warmstartipfactor, 0.0) )
2636  {
2637  if ( relaxdata->warmstartiptype == 1 )
2638  {
2639  if ( ! relaxdata->warmstartprojpdsame )
2640  {
2641  /* compute maxdualentry (should be at least one) */
2642  maxdualentry = 1.0;
2643  for (i = 0; i < startZnblocknonz[b]; i++)
2644  {
2645  if ( REALABS(startZval[b][i]) > maxdualentry )
2646  maxdualentry = REALABS(startZval[b][i]);
2647  }
2648  identitydiagonal = relaxdata->warmstartipfactor * maxdualentry; /* the diagonal entries of the scaled identity matrix */
2649  }
2650 
2651  SCIP_CALL( SCIPallocBufferArray(scip, &diagentryexists, blocksize) ); /* TODO: could allocate this once for Z and X with max-blocksize */
2652  for (i = 0; i < blocksize; i++)
2653  diagentryexists[i] = FALSE;
2654 
2655  for (i = 0; i < startZnblocknonz[b]; i++)
2656  {
2657  if ( startZrow[b][i] == startZcol[b][i] )
2658  {
2659  startZval[b][i] = startZval[b][i] * (1 - relaxdata->warmstartipfactor) + identitydiagonal; /* add identity for diagonal entries */
2660  assert( startZval[b][i] >= 0 ); /* since the original matrix should have been positive semidefinite, diagonal entries should be >= 0 */
2661  diagentryexists[startZrow[b][i]] = TRUE;
2662  }
2663  else
2664  startZval[b][i] *= (1 - relaxdata->warmstartipfactor); /* since this is an off-diagonal entry, we scale towards zero */
2665  }
2666 
2667  /* if a diagonal entry was missing (because we had a zero row before), we have to add it to the end */
2668  for (i = 0; i < blocksize; i++)
2669  {
2670  if ( ! diagentryexists[i] )
2671  {
2672  startZrow[b][startZnblocknonz[b]] = i;
2673  startZcol[b][startZnblocknonz[b]] = i;
2674  startZval[b][startZnblocknonz[b]] = identitydiagonal;
2675  startZnblocknonz[b]++;
2676  }
2677  }
2678 
2679  SCIPfreeBufferArrayNull(scip, &diagentryexists);
2680  }
2681  else if ( relaxdata->warmstartiptype == 2 )
2682  {
2683  /* iterate once over all entries to multiply them with (1 - warmstartipfactor) */
2684  for (i = 0; i < startZnblocknonz[b]; i++)
2685  startZval[b][i] *= 1 - relaxdata->warmstartipfactor;
2686 
2687  /* merge the scaled interior point array into the warmstart array */
2688  SCIP_CALL( SCIPsdpVarfixerMergeArrays(SCIPblkmem(scip), SCIPepsilon(scip), relaxdata->ipZrow[b], relaxdata->ipZcol[b], relaxdata->ipZval[b], relaxdata->ipZnblocknonz[b], TRUE,
2689  relaxdata->warmstartipfactor, startZrow[b], startZcol[b], startZval[b], &(startZnblocknonz[b]), startZnblocknonz[b] + relaxdata->ipZnblocknonz[b]) );
2690  }
2691  }
2692  }
2693 
2694  /* compute projection for LP block */
2695  if ( relaxdata->warmstartproject == 3 )
2696  {
2697  int nsavedentries;
2698  int lastentry;
2699  int j;
2700 
2701  /* sort indices by row/col; TODO: check if this is necessary */
2702  SCIPsortIntIntReal(startXrow[nblocks], startXcol[nblocks], startXval[nblocks], startXnblocknonz[nblocks]);
2703 
2704  /* iterate over all entries */
2705  nsavedentries = startXnblocknonz[nblocks];
2706  lastentry = 0;
2707 
2708  for (i = 0; i < nsavedentries; i++)
2709  {
2710  assert( startXrow[nblocks][i] == startXcol[nblocks][i] ); /* this is the LP-block */
2711  /* if some entries are missing, we add them at the end */
2712  for (j = lastentry + 1; j < startXrow[nblocks][i]; j++)
2713  {
2714  assert( startXnblocknonz[nblocks] < 2 * nrows + 2 * nvars );
2715  startXrow[nblocks][startXnblocknonz[nblocks]] = j;
2716  startXcol[nblocks][startXnblocknonz[nblocks]] = j;
2717  startXval[nblocks][startXnblocknonz[nblocks]] = relaxdata->warmstartprojminevprimal;
2718  startXnblocknonz[nblocks]++;
2719  }
2720  if ( SCIPisLT(scip, startXval[b][i], 1.0) )
2721  startXval[b][i] = relaxdata->warmstartprojminevprimal;
2722 
2723  lastentry = startXrow[nblocks][i];
2724  }
2725  /* add missing entries at the end */
2726  for (j = lastentry + 1; j < 2 * nrows + 2 * nvars; j++)
2727  {
2728  assert( startXnblocknonz[nblocks] < 2 * nrows + 2 * nvars );
2729  startXrow[nblocks][startXnblocknonz[nblocks]] = j;
2730  startXcol[nblocks][startXnblocknonz[nblocks]] = j;
2731  startXval[nblocks][startXnblocknonz[nblocks]] = relaxdata->warmstartprojminevprimal;
2732  startXnblocknonz[nblocks]++;
2733  }
2734  }
2735 
2736  /* take convex combination for LP block */
2737  if ( SCIPisGT(scip, relaxdata->warmstartipfactor, 0.0) )
2738  {
2739  if ( relaxdata->warmstartiptype == 1 )
2740  {
2741  int nsavedentries;
2742  int lastentry;
2743  int j;
2744 
2745  /* if warmstartprojpdsame is true we use the computed value, otherwise we use the maximum of this block, which is one */
2746  if ( ! relaxdata->warmstartprojpdsame )
2747  identitydiagonal = relaxdata->warmstartipfactor;
2748 
2749  /* sort indices by row/col; TODO: check if this is necessary */
2750  SCIPsortIntIntReal(startXrow[nblocks], startXcol[nblocks], startXval[nblocks], startXnblocknonz[nblocks]);
2751 
2752  /* iterate over all entries */
2753  nsavedentries = startXnblocknonz[nblocks];
2754  lastentry = 0;
2755 
2756  for (i = 0; i < nsavedentries; i++)
2757  {
2758  assert( startXrow[nblocks][i] == startXcol[nblocks][i] ); /* this is the LP-block */
2759  /* if some entries are missing, we add them at the end */
2760  for (j = lastentry + 1; j < startXrow[nblocks][i]; j++)
2761  {
2762  assert( startXnblocknonz[nblocks] < 2 * nrows + 2 * nvars );
2763  startXrow[nblocks][startXnblocknonz[nblocks]] = j;
2764  startXcol[nblocks][startXnblocknonz[nblocks]] = j;
2765  /* if warmstartprojpdsame is true we use the computed value, otherwise we use the maximum of this block, which is one */
2766  if ( relaxdata->warmstartprojpdsame )
2767  startXval[nblocks][startXnblocknonz[nblocks]] = identitydiagonal;
2768  else
2769  startXval[nblocks][startXnblocknonz[nblocks]] = relaxdata->warmstartipfactor;
2770  startXnblocknonz[nblocks]++;
2771  }
2772  /* we only take the convex combination if the value is less than one, since the maxblockentry is equal to the value
2773  * otherwise, so taking the convex combination doesn't change anything in that case (unless warmstarprojpdsame)
2774  */
2775  if ( relaxdata->warmstartprojpdsame )
2776  startXval[b][i] = (1 - relaxdata->warmstartipfactor) * startXval[b][i] + identitydiagonal;
2777  else if ( SCIPisLT(scip, startXval[b][i], 1.0) )
2778  startXval[b][i] = (1 - relaxdata->warmstartipfactor) * startXval[b][i] + relaxdata->warmstartipfactor;
2779 
2780  lastentry = startXrow[nblocks][i];
2781  }
2782  /* add missing entries at the end */
2783  for (j = lastentry + 1; j < 2 * nrows + 2 * nvars; j++)
2784  {
2785  assert( startXnblocknonz[nblocks] < 2 * nrows + 2 * nvars );
2786  startXrow[nblocks][startXnblocknonz[nblocks]] = j;
2787  startXcol[nblocks][startXnblocknonz[nblocks]] = j;
2788  startXval[nblocks][startXnblocknonz[nblocks]] = identitydiagonal;
2789  startXnblocknonz[nblocks]++;
2790  }
2791  }
2792  else if ( relaxdata->warmstartiptype == 2 )
2793  {
2794  /* iterate once over all entries to multiply them with (1 - warmstartipfactor) */
2795  for (i = 0; i < startXnblocknonz[nblocks]; i++)
2796  startXval[nblocks][i] *= 1 - relaxdata->warmstartipfactor;
2797 
2798  /* merge the scaled interior point array into the warmstart array */
2799  SCIP_CALL( SCIPsdpVarfixerMergeArrays(SCIPblkmem(scip), SCIPepsilon(scip), relaxdata->ipXrow[nblocks],
2800  relaxdata->ipXcol[nblocks], relaxdata->ipXval[nblocks], relaxdata->ipXnblocknonz[nblocks], TRUE,
2801  relaxdata->warmstartipfactor, startXrow[nblocks], startXcol[nblocks], startXval[nblocks],
2802  &(startXnblocknonz[nblocks]), startXnblocknonz[nblocks] + relaxdata->ipXnblocknonz[nblocks]) );
2803  }
2804 
2805  /* take the convex combination for the dual (in this case we do not need to check for missing entries since we added all of them ourselves) */
2806  if ( relaxdata->warmstartiptype == 1 )
2807  {
2808  for (r = 0; r < nrows; r++)
2809  {
2810  /* for the project we just set all values smaller than minev to minev */
2811  if ( relaxdata->warmstartiptype == 1 && relaxdata->warmstartproject == 3 && SCIPisLT(scip, startZval[b][2*r], relaxdata->warmstartprojminevdual) )
2812  startZval[nblocks][2*r] = relaxdata->warmstartprojminevdual;
2813  /* we only take the convex combination if the value is less than one, since the maxblockentry is equal to the value
2814  * otherwise, so taking the convex combination doesn't change anything in that case (unless projpdsame)
2815  */
2816  else if ( relaxdata->warmstartiptype == 1 && (SCIPisLT(scip, startZval[nblocks][2*r], 1.0) || relaxdata->warmstartprojpdsame) )
2817  {
2818  /* since we want the value to be strictly positive, if the original entry is negative we just set it to identitydiagonal */
2819  if ( SCIPisLT(scip, startZval[nblocks][2*r], 0.0) )
2820  startZval[nblocks][2*r] = identitydiagonal;
2821  else
2822  startZval[nblocks][2*r] = (1 - relaxdata->warmstartipfactor) * startZval[nblocks][2*r] + identitydiagonal;
2823  }
2824 
2825  if ( relaxdata->warmstartiptype == 1 && relaxdata->warmstartproject == 3 && SCIPisLT(scip, startZval[nblocks][2*r + 1], relaxdata->warmstartprojminevdual) )
2826  startZval[nblocks][2*r + 1] = relaxdata->warmstartprojminevdual;
2827  else if ( relaxdata->warmstartiptype == 1 && (SCIPisLT(scip, startZval[nblocks][2*r + 1], 1.0) || relaxdata->warmstartprojpdsame) )
2828  {
2829  /* since we want the value to be strictly positive, if the original entry is negative we just set it to identitydiagonal */
2830  if ( SCIPisLT(scip, startZval[nblocks][2*r + 1], 0.0) )
2831  startZval[nblocks][2*r + 1] = identitydiagonal;
2832  else
2833  startZval[nblocks][2*r + 1] = (1 - relaxdata->warmstartipfactor) * startZval[nblocks][2*r + 1] + identitydiagonal;
2834  }
2835  }
2836 
2837  for (v = 0; v < nvars; v++)
2838  {
2839  if ( relaxdata->warmstartiptype == 1 && relaxdata->warmstartproject == 3 && SCIPisLT(scip, startZval[nblocks][2*nrows + 2*v], relaxdata->warmstartprojminevdual) )
2840  startZval[nblocks][2*nrows + 2*v] = relaxdata->warmstartprojminevdual;
2841  else if ( relaxdata->warmstartiptype == 1 && (SCIPisLT(scip, startZval[nblocks][2*nrows + 2*v], 1.0) || relaxdata->warmstartprojpdsame) )
2842  {
2843  /* since we want the value to be strictly positive, if the original entry is negative we just set it to identitydiagonal */
2844  if ( SCIPisLT(scip, startZval[nblocks][2*nrows + 2*v], 0.0) )
2845  startZval[nblocks][2*nrows + 2*v] = identitydiagonal;
2846  else
2847  startZval[nblocks][2*nrows + 2*v] = (1 - relaxdata->warmstartipfactor) * startZval[nblocks][2*nrows + 2*v] + identitydiagonal;
2848  }
2849 
2850  if ( relaxdata->warmstartiptype == 1 && relaxdata->warmstartproject == 3 && SCIPisLT(scip, startZval[nblocks][2*nrows + 2*v + 1], relaxdata->warmstartprojminevdual) )
2851  startZval[nblocks][2*nrows + 2*v + 1] = relaxdata->warmstartprojminevdual;
2852  else if ( relaxdata->warmstartiptype == 1 && (SCIPisLT(scip, startZval[nblocks][2*nrows + 2*v + 1], 1.0) || relaxdata->warmstartprojpdsame) )
2853  {
2854  /* since we want the value to be strictly positive, if the original entry is negative we just set it to identitydiagonal */
2855  if ( SCIPisLT(scip, startZval[nblocks][2*nrows + 2*v + 1], 0.0) )
2856  startZval[nblocks][2*nrows + 2*v + 1] = identitydiagonal;
2857  else
2858  startZval[nblocks][2*nrows + 2*v + 1] = (1 - relaxdata->warmstartipfactor) * startZval[nblocks][2*nrows + 2*v + 1] + identitydiagonal;
2859  }
2860  }
2861  }
2862  else if ( relaxdata->warmstartiptype == 2 )
2863  {
2864  /* iterate once over all entries to multiply them with (1 - warmstartipfactor) */
2865  for (i = 0; i < startZnblocknonz[nblocks]; i++)
2866  startZval[nblocks][i] *= 1 - relaxdata->warmstartipfactor;
2867 
2868  /* merge the scaled interior point array into the warmstart array */
2869  SCIP_CALL( SCIPsdpVarfixerMergeArrays(SCIPblkmem(scip), SCIPepsilon(scip), relaxdata->ipZrow[nblocks],
2870  relaxdata->ipZcol[nblocks], relaxdata->ipZval[nblocks], relaxdata->ipZnblocknonz[nblocks], TRUE,
2871  relaxdata->warmstartipfactor, startZrow[nblocks], startZcol[nblocks], startZval[nblocks],
2872  &(startZnblocknonz[nblocks]), startZnblocknonz[nblocks] + relaxdata->ipZnblocknonz[nblocks]) );
2873  }
2874  }
2875  }
2876 
2877 #ifdef SCIP_PRINT_WARMSTART
2878  SCIPdebugMessage("warmstart using the following point:\n");
2879  nblocks = SCIPconshdlrGetNConss(SCIPfindConshdlr(scip, "SDP"));
2880  for (i = 0; i < nvars; i++)
2881  SCIPdebugMessage("y[%d]=%f\n", i, starty[i]);
2882 
2884  {
2885  for (b = 0; b < nblocks + 1; b++)
2886  {
2887  SCIPdebugMessage("dual block %d\n", b);
2888  for (i = 0; i < startZnblocknonz[b]; i++)
2889  {
2890  SCIPdebugMessage("Z(%d,%d)=%f\n", startZrow[b][i], startZcol[b][i], startZval[b][i]);
2891  }
2892  }
2893  for (b = 0; b < nblocks + 1; b++)
2894  {
2895  SCIPdebugMessage("primal block %d\n", b);
2896  for (i = 0; i < startXnblocknonz[b]; i++)
2897  {
2898  SCIPdebugMessage("X(%d,%d)=%f\n", startXrow[b][i], startXcol[b][i], startXval[b][i]);
2899  }
2900  }
2901  }
2902 #endif
2903 
2904  /* solve with given starting point */
2905  SCIP_CALL(SCIPsdpiSolve(sdpi, starty, startZnblocknonz, startZrow, startZcol, startZval, startXnblocknonz, startXrow,
2906  startXcol, startXval, startsetting, enforceslater, timelimit));
2907 
2909  {
2910  SCIP_CONSHDLR* sdpconshdlr;
2911 
2912  sdpconshdlr = SCIPfindConshdlr(scip, "SDP");
2913  nblocks = SCIPconshdlrGetNConss(sdpconshdlr) + 1; /* +1 for LP block */
2914 
2915  /* free memory */
2916  for (b = 0; b < nblocks; b++)
2917  {
2918  SCIPfreeBufferArray(scip, &startXval[b]);
2919  SCIPfreeBufferArray(scip, &startXcol[b]);
2920  SCIPfreeBufferArray(scip, &startXrow[b]);
2921  SCIPfreeBufferArray(scip, &startZval[b]);
2922  SCIPfreeBufferArray(scip, &startZcol[b]);
2923  SCIPfreeBufferArray(scip, &startZrow[b]);
2924  }
2925 
2926  SCIPfreeBufferArray(scip, &startXval);
2927  SCIPfreeBufferArray(scip, &startXcol);
2928  SCIPfreeBufferArray(scip, &startXrow);
2929  SCIPfreeBufferArray(scip, &startXnblocknonz);
2930  SCIPfreeBufferArray(scip, &startZval);
2931  SCIPfreeBufferArray(scip, &startZcol);
2932  SCIPfreeBufferArray(scip, &startZrow);
2933  SCIPfreeBufferArray(scip, &startZnblocknonz);
2934  }
2935  SCIPfreeBufferArray(scip, &starty);
2936  }
2937  }
2938 
2939  solved:
2940 
2941  relaxdata->lastsdpnode = SCIPnodeGetNumber(SCIPgetCurrentNode(scip));
2942 
2943  /* update calls, iterations and stability numbers (only if the SDP-solver was actually called) */
2944  relaxdata->sdpinterfacecalls++;
2945  naddedsdpcalls = 0;
2946  SCIP_CALL( SCIPsdpiGetSdpCalls(relaxdata->sdpi, &naddedsdpcalls) );
2947  usedsetting = SCIP_SDPSOLVERSETTING_UNSOLVED;
2948  if ( naddedsdpcalls )
2949  {
2950  relaxdata->sdpcalls += naddedsdpcalls;
2951  naddediters = 0;
2952  SCIP_CALL( SCIPsdpiGetIterations(relaxdata->sdpi, &naddediters) );
2953  relaxdata->sdpiterations += naddediters;
2954 
2955  SCIP_CALL( SCIPsdpiSettingsUsed(relaxdata->sdpi, &usedsetting) );
2956 
2957  switch( usedsetting )/*lint --e{788}*/
2958  {
2960  relaxdata->solvedpenalty++;
2961  break;
2963  relaxdata->solvedfast++;
2964  break;
2966  relaxdata->solvedmedium++;
2967  break;
2969  relaxdata->solvedstable++;
2970  break;
2972  relaxdata->unsolved++;
2973  break;
2974  default:
2975  break;
2976  }
2977  primalslater = SCIP_SDPSLATER_NOINFO;
2978  dualslater = SCIP_SDPSLATER_NOINFO;
2979  SCIP_CALL( SCIPsdpiSlater(relaxdata->sdpi, &primalslater, &dualslater) );
2980  switch( primalslater )/*lint --e{788}*/
2981  {
2982  case SCIP_SDPSLATER_NOINFO:
2983  relaxdata->npslatercheckfailed++;
2984  switch( dualslater )/*lint --e{788}*/
2985  {
2986  case SCIP_SDPSLATER_NOINFO:
2987  relaxdata->ndslatercheckfailed++;
2988  relaxdata->nslatercheckfailed++;
2989  break;
2990  case SCIP_SDPSLATER_NOT:
2991  relaxdata->ndnoslater++;
2992  relaxdata->nnoslater++;
2993  break;
2994  case SCIP_SDPSLATER_HOLDS:
2995  relaxdata->ndslaterholds++;
2996  relaxdata->nslatercheckfailed++;
2997  break;
2998  case SCIP_SDPSLATER_INF:
2999  relaxdata->nslaterinfeasible++;
3000  break;
3001  default:
3002  relaxdata->ndslatercheckfailed++;
3003  relaxdata->nslatercheckfailed++;
3004  break;
3005  }
3006  break;
3007  case SCIP_SDPSLATER_NOT:
3008  relaxdata->npnoslater++;
3009  switch( dualslater )/*lint --e{788}*/
3010  {
3011  case SCIP_SDPSLATER_NOINFO:
3012  relaxdata->ndslatercheckfailed++;
3013  relaxdata->nnoslater++;
3014  break;
3015  case SCIP_SDPSLATER_NOT:
3016  relaxdata->ndnoslater++;
3017  relaxdata->nnoslater++;
3018  break;
3019  case SCIP_SDPSLATER_HOLDS:
3020  relaxdata->ndslaterholds++;
3021  relaxdata->nnoslater++;
3022  break;
3023  case SCIP_SDPSLATER_INF:
3024  relaxdata->nslaterinfeasible++;
3025  break;
3026  default:
3027  relaxdata->ndslatercheckfailed++;
3028  relaxdata->nnoslater++;
3029  break;
3030  }
3031  break;
3032  case SCIP_SDPSLATER_HOLDS:
3033  relaxdata->npslaterholds++;
3034  switch( dualslater )/*lint --e{788}*/
3035  {
3036  case SCIP_SDPSLATER_NOINFO:
3037  relaxdata->ndslatercheckfailed++;
3038  relaxdata->nslatercheckfailed++;
3039  break;
3040  case SCIP_SDPSLATER_NOT:
3041  relaxdata->ndnoslater++;
3042  relaxdata->nnoslater++;
3043  break;
3044  case SCIP_SDPSLATER_HOLDS:
3045  relaxdata->ndslaterholds++;
3046  relaxdata->nslaterholds++;
3047  break;
3048  case SCIP_SDPSLATER_INF:
3049  relaxdata->nslaterinfeasible++;
3050  break;
3051  default:
3052  relaxdata->ndslatercheckfailed++;
3053  relaxdata->nslatercheckfailed++;
3054  break;
3055  }
3056  break;
3057  default:
3058  relaxdata->npslatercheckfailed++;
3059  relaxdata->ndslatercheckfailed++;
3060  relaxdata->nslatercheckfailed++;
3061  break;
3062  }
3063  slatersetting = SCIP_SDPSLATERSETTING_NOINFO;
3064  SCIP_CALL( SCIPsdpiSlaterSettings(relaxdata->sdpi, &slatersetting) );
3065  switch( slatersetting )/*lint --e{788}*/
3066  {
3068  relaxdata->stablewslater++;
3069  break;
3071  relaxdata->unstablewslater++;
3072  break;
3074  relaxdata->penaltywslater++;
3075  break;
3077  relaxdata->boundedwslater++;
3078  break;
3080  relaxdata->unsolvedwslater++;
3081  break;
3083  relaxdata->stablenoslater++;
3084  break;
3086  relaxdata->unstablenoslater++;
3087  break;
3089  relaxdata->penaltynoslater++;
3090  break;
3092  relaxdata->boundednoslater++;
3093  break;
3095  relaxdata->unsolvednoslater++;
3096  break;
3098  relaxdata->stableinfeasible++;
3099  break;
3101  relaxdata->unstableinfeasible++;
3102  break;
3104  relaxdata->penaltyinfeasible++;
3105  break;
3107  relaxdata->boundedinfeasible++;
3108  break;
3110  relaxdata->unsolvedinfeasible++;
3111  break;
3112  default:
3113  break;
3114  }
3115  }
3116 
3117  /* remember settings */
3118  if ( ! (strcmp(SCIPsdpiGetSolverName(), "DSDP") == 0) && ! (strstr(SCIPsdpiGetSolverName(), "MOSEK") != NULL) )
3119  {
3120  (void) SCIPsnprintf(saveconsname, SCIP_MAXSTRLEN, "savedsettings_node_%d", SCIPnodeGetNumber(SCIPgetCurrentNode(scip)));
3121  SCIP_CALL( createConsSavedsdpsettings(scip, &savedsetting, saveconsname, usedsetting) );
3122  SCIP_CALL( SCIPaddCons(scip, savedsetting) );
3123  SCIP_CALL( SCIPreleaseCons(scip, &savedsetting) );
3124  }
3125 
3126  if ( ! SCIPsdpiWasSolved(sdpi) )
3127  relaxdata->feasible = FALSE;
3128 
3129  if ( SCIPinProbing(scip) )
3130  relaxdata->probingsolved = SCIPsdpiWasSolved(sdpi);
3131  else
3132  relaxdata->origsolved = SCIPsdpiSolvedOrig(sdpi);
3133 
3134  if ( SCIPsdpiIsAcceptable(sdpi) )
3135  {
3136 #ifdef SCIP_MORE_DEBUG /* print the optimal solution */
3137  {
3138  int sollength;
3139  SCIP_CALL( SCIPallocBufferArray(scip, &solforscip, nvars) );
3140  sollength = nvars;
3141  SCIP_CALL( SCIPsdpiGetSol(sdpi, &objforscip, solforscip, &sollength) ); /* get both the objective and the solution from the SDP solver */
3142 
3143  assert( sollength == nvars ); /* If this isn't true any longer, the getSol-call was unsuccessfull, because the given array wasn't long enough,
3144  * but this can't happen, because the array has enough space for all SDP variables. */
3145 
3146  if ( SCIPsdpiFeasibilityKnown(sdpi) )
3147  {
3148  SCIPdebugMessage("optimal solution: objective = %f, dual feasible: %u, primal feasible: %u.\n",
3149  objforscip, SCIPsdpiIsDualFeasible(sdpi), SCIPsdpiIsPrimalFeasible(sdpi));
3150  }
3151  else
3152  {
3153  SCIPdebugMessage("The solver could not determine feasibility ! ");
3154  }
3155 
3156  /* output solution */
3157  for (i = 0; i < nvars; ++i)
3158  {
3159  SCIPdebugMessage("<%s> = %f\n", SCIPvarGetName(vars[i]), solforscip[i]);
3160  }
3161  SCIPfreeBufferArray(scip, &solforscip);
3162  }
3163 #endif
3164 
3165  if ( SCIPsdpiIsDualInfeasible(sdpi) )
3166  {
3167  SCIPdebugMessage("Node cut off due to infeasibility.\n");
3168  relaxdata->feasible = FALSE;
3169  *result = SCIP_CUTOFF;
3170  return SCIP_OKAY;
3171  }
3172  else if ( SCIPsdpiIsObjlimExc(sdpi) )
3173  {
3174  SCIPdebugMessage("Node cut off due to objective limit.\n");
3175  relaxdata->feasible = FALSE;
3176  *result = SCIP_CUTOFF;
3177  return SCIP_OKAY;
3178  }
3179  else if ( SCIPsdpiIsDualUnbounded(sdpi) )
3180  {
3181  SCIPdebugMessage("Node unbounded.");
3182  relaxdata->feasible = TRUE;
3183  *result = SCIP_SUCCESS;
3184  *lowerbound = -SCIPinfinity(scip);
3185  return SCIP_OKAY;
3186  }
3187  else if ( SCIPsdpiIsPrimalFeasible(sdpi) && SCIPsdpiIsDualFeasible(sdpi) )
3188  {
3189  SCIP_SOL* scipsol; /* TODO: eliminate this from warmstart and save array instead */
3190  SCIP_SOL* preoptimalsol;
3191  SCIP_CONS* savedcons;
3192  int slength;
3193  SCIP_Bool preoptimalsolsuccess;
3194 
3195  /* get solution w.r.t. SCIP variables */
3196  SCIP_CALL( SCIPallocBufferArray(scip, &solforscip, nvars) );
3197  slength = nvars;
3198  SCIP_CALL( SCIPsdpiGetSol(sdpi, &objforscip, solforscip, &slength) ); /* get both the objective and the solution from the SDP solver */
3199 
3200  assert( slength == nvars ); /* If this isn't true any longer, the getSol-Call was unsuccessfull, because the given array wasn't long enough,
3201  * but this can't happen, because the array has enough space for all sdp variables. */
3202 
3203  /* create SCIP solution */
3204  SCIP_CALL( SCIPcreateSol(scip, &scipsol, NULL) );
3205  SCIP_CALL( SCIPsetSolVals(scip, scipsol, nvars, vars, solforscip) );
3206 
3207  *lowerbound = objforscip;
3208  relaxdata->objval = objforscip;
3209 
3210  /* copy solution */
3211  SCIP_CALL( SCIPsetRelaxSolVals(scip, nvars, vars, solforscip, TRUE) );
3212 
3213  relaxdata->feasible = TRUE;
3214  *result = SCIP_SUCCESS;
3215  preoptimalsolsuccess = FALSE;
3216 
3217  /* save solution for warmstarts (only if we did not use the penalty formulation, since this would change the problem structure) */
3218  if ( relaxdata->warmstart && SCIPsdpiSolvedOrig(relaxdata->sdpi) )
3219  {
3220  SCIP_Real maxprimalentry;
3221  int* startXnblocknonz;
3222  int** startXrow;
3223  int** startXcol;
3224  SCIP_Real** startXval;
3225  char consname[SCIP_MAXSTRLEN];
3226 #ifndef NDEBUG
3227  int snprintfreturn; /* this is used to assert that the SCIP string concatenation works */
3228 #endif
3229 
3230  startXnblocknonz = NULL;
3231  startXrow = NULL;
3232  startXcol = NULL;
3233  startXval = NULL;
3234 
3235  /* use preoptimal solution if using DSDP and parameter is set accordingly */
3236  if ( relaxdata->warmstartpreoptsol )
3237  {
3238  if ( strcmp(SCIPsdpiGetSolverName(), "DSDP") == 0.0 || strcmp(SCIPsdpiGetSolverName(), "SDPA") == 0.0 )
3239  {
3240  SCIP_Real* preoptimalvec;
3241  int nvarsgiven;
3242 
3243  SCIP_CALL( SCIPallocBufferArray(scip, &preoptimalvec, nvars) );
3244  nvarsgiven = nvars;
3245 
3247  {
3248  maxprimalentry = 0.0;
3249  if ( relaxdata->warmstartprimaltype == 3 )
3250  {
3251  nblocks = SCIPconshdlrGetNConss(SCIPfindConshdlr(scip, "SDP")) + 1; /* +1 for the LP part */
3252  SCIP_CALL( SCIPallocBufferArray(scip, &startXnblocknonz, nblocks) );
3253 
3254  /* get amount of memory to allocate for row/col/val from sdpi */
3255  SCIP_CALL( SCIPsdpiGetPreoptimalPrimalNonzeros(relaxdata->sdpi, nblocks, startXnblocknonz) );
3256 
3257  /* check if the primal matrix exists, otherwise skip creation of the savedsol contraint */
3258  if ( startXnblocknonz[0] > -1 )
3259  {
3260  preoptimalsolsuccess = TRUE;
3261 
3262  SCIP_CALL( SCIPallocBufferArray(scip, &startXrow, nblocks) );
3263  SCIP_CALL( SCIPallocBufferArray(scip, &startXcol, nblocks) );
3264  SCIP_CALL( SCIPallocBufferArray(scip, &startXval, nblocks) );
3265 
3266  /* allocate memory for different blocks in row/col/val */
3267  for (b = 0; b < nblocks; b++)
3268  {
3269  SCIP_CALL( SCIPallocBufferArray(scip, &startXrow[b], startXnblocknonz[b]) );
3270  SCIP_CALL( SCIPallocBufferArray(scip, &startXcol[b], startXnblocknonz[b]) );
3271  SCIP_CALL( SCIPallocBufferArray(scip, &startXval[b], startXnblocknonz[b]) );
3272  }
3273 
3274  SCIP_CALL( SCIPsdpiGetPreoptimalSol(relaxdata->sdpi, &preoptimalsolsuccess, preoptimalvec, &nvarsgiven,
3275  nblocks, startXnblocknonz, startXrow, startXcol, startXval) );
3276  }
3277  else
3278  preoptimalsolsuccess = FALSE;
3279  }
3280  else
3281  {
3282  nblocks = 0;
3283  maxprimalentry = SCIPsdpiGetMaxPrimalEntry(relaxdata->sdpi);
3284  }
3285  }
3286  else
3287  {
3288  maxprimalentry = 0.0;
3289  SCIP_CALL( SCIPsdpiGetPreoptimalSol(relaxdata->sdpi, &preoptimalsolsuccess, preoptimalvec, &nvarsgiven,
3290  -1, NULL, NULL, NULL, NULL) );
3291  nblocks = 0;
3292  }
3293 
3294  if ( preoptimalsolsuccess )
3295  {
3296  assert( nvarsgiven == nvars ); /* length of solution should be nvars */
3297 
3298  /* create SCIP solution */
3299  SCIP_CALL( SCIPcreateSol(scip, &preoptimalsol, NULL) );
3300  SCIP_CALL( SCIPsetSolVals(scip, preoptimalsol, nvars, vars, preoptimalvec) );
3301  }
3302 
3303  SCIPfreeBufferArray(scip, &preoptimalvec);
3304  }
3305  else
3306  {
3307  SCIPerrorMessage("Warmstarting with preoptimal solutions currently only supported for DSDP and SDPA \n");
3308  return SCIP_LPERROR;
3309  }
3310  }
3311  else if ( SCIPsdpiDoesWarmstartNeedPrimal() )
3312  {
3313  maxprimalentry = 0.0;
3314  if ( relaxdata->warmstartprimaltype == 3 )
3315  {
3316  nblocks = SCIPconshdlrGetNConss(SCIPfindConshdlr(scip, "SDP")) + 1; /* +1 for the LP part */
3317  SCIP_CALL( SCIPallocBufferArray(scip, &startXnblocknonz, nblocks) );
3318  SCIP_CALL( SCIPallocBufferArray(scip, &startXrow, nblocks) );
3319  SCIP_CALL( SCIPallocBufferArray(scip, &startXcol, nblocks) );
3320  SCIP_CALL( SCIPallocBufferArray(scip, &startXval, nblocks) );
3321 
3322  /* get amount of memory to allocate for row/col/val from sdpi */
3323  SCIP_CALL( SCIPsdpiGetPrimalNonzeros(relaxdata->sdpi, nblocks, startXnblocknonz) );
3324 
3325  /* allocate memory for different blocks in row/col/val */
3326  for (b = 0; b < nblocks; b++)
3327  {
3328  SCIP_CALL( SCIPallocBufferArray(scip, &startXrow[b], startXnblocknonz[b]) );
3329  SCIP_CALL( SCIPallocBufferArray(scip, &startXcol[b], startXnblocknonz[b]) );
3330  SCIP_CALL( SCIPallocBufferArray(scip, &startXval[b], startXnblocknonz[b]) );
3331  }
3332  SCIP_CALL( SCIPsdpiGetPrimalMatrix(sdpi, nblocks, startXnblocknonz, startXrow, startXcol, startXval) );
3333  }
3334  else
3335  {
3336  nblocks = 0;
3337  maxprimalentry = SCIPsdpiGetMaxPrimalEntry(relaxdata->sdpi);
3338  }
3339  }
3340  else
3341  {
3342  maxprimalentry = 0.0;
3343  nblocks = 0;
3344  }
3345 #ifndef NDEBUG
3346  snprintfreturn = SCIPsnprintf(consname, SCIP_MAXSTRLEN, "saved_relax_sol_%d", SCIPnodeGetNumber(SCIPgetCurrentNode(scip)));
3347  assert( snprintfreturn < SCIP_MAXSTRLEN ); /* check whether name fit into string */
3348 #else
3349  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "saved_relax_sol_%d", SCIPnodeGetNumber(SCIPgetCurrentNode(scip)));
3350 #endif
3351  if ( relaxdata->warmstartpreoptsol )
3352  {
3353  /* only create constraint if the preoptimal solution exists, otherwise we don't want to warmstart at all */
3354  if ( preoptimalsolsuccess )
3355  {
3356  SCIP_CALL( createConsSavesdpsol(scip, &savedcons, consname, SCIPnodeGetNumber(SCIPgetCurrentNode(scip)), preoptimalsol,
3357  maxprimalentry, nblocks, startXnblocknonz, startXrow, startXcol, startXval) );
3358 
3359  SCIP_CALL( SCIPaddCons(scip, savedcons) );
3360  SCIP_CALL( SCIPreleaseCons(scip, &savedcons) );
3361  }
3362  }
3363  else
3364  {
3365  SCIP_CALL( createConsSavesdpsol(scip, &savedcons, consname, SCIPnodeGetNumber(SCIPgetCurrentNode(scip)), scipsol,
3366  maxprimalentry, nblocks, startXnblocknonz, startXrow, startXcol, startXval) );
3367 
3368  SCIP_CALL( SCIPaddCons(scip, savedcons) );
3369  SCIP_CALL( SCIPreleaseCons(scip, &savedcons) );
3370  }
3371 
3372  if ( SCIPsdpiDoesWarmstartNeedPrimal() && relaxdata->warmstartprimaltype == 3 )
3373  {
3374  /* free memory for primal matrix */
3375  if ( startXnblocknonz[0] > 1 ) /* no memory was allocated if computation of preoptimal solution failed */
3376  {
3377  for (b = 0; b < nblocks; b++)
3378  {
3379  SCIPfreeBufferArrayNull(scip, &startXval[b]);
3380  SCIPfreeBufferArrayNull(scip, &startXcol[b]);
3381  SCIPfreeBufferArrayNull(scip, &startXrow[b]);
3382  }
3383  SCIPfreeBufferArrayNull(scip, &startXval);
3384  SCIPfreeBufferArrayNull(scip, &startXcol);
3385  SCIPfreeBufferArrayNull(scip, &startXrow);
3386  }
3387  SCIPfreeBufferArrayNull(scip, &startXnblocknonz);
3388  }
3389  }
3390 
3391  SCIPfreeBufferArray(scip, &solforscip);
3392  SCIP_CALL( SCIPfreeSol(scip, &scipsol) );
3393  if ( preoptimalsolsuccess )
3394  {
3395  SCIP_CALL( SCIPfreeSol(scip, &preoptimalsol) );
3396  }
3397  }
3398  }
3399  else
3400  {
3401  SCIP_Real objlb;
3402 
3403  if ( SCIPsdpiIsTimelimExc(relaxdata->sdpi) )
3404  {
3405  *result = SCIP_DIDNOTRUN;
3406  return SCIP_OKAY;
3407  }
3408 
3409  /* if we used the penalty approach, we might have calculated a good lower bound, even if we did not produce a feasible solution, otherwise we
3410  * keep the current bound, if the current bound is -infty, we abort */
3411  objlb = -SCIPinfinity(scip);
3412  SCIP_CALL( SCIPsdpiGetLowerObjbound(relaxdata->sdpi, &objlb) );
3413  if ( ! SCIPisInfinity(scip, objlb) )
3414  {
3415  *lowerbound = objlb;
3416  SCIPdebugMessage("The relaxation could not be solved, using best computed bound from penalty formulation.\n");
3417  }
3418  else if ( ! SCIPisInfinity(scip, -1 * SCIPnodeGetLowerbound(SCIPgetCurrentNode(scip))) )
3419  {
3420  *lowerbound = SCIPnodeGetLowerbound(SCIPgetCurrentNode(scip));
3421  SCIPdebugMessage("The relaxation could not be solved, keeping old bound.\n");
3422  }
3423  else
3424  {
3425  *result = SCIP_SUSPENDED;
3426  SCIPerrorMessage("The relaxation of the root node could not be solved, so there is no hope to solve this instance.\n");
3427  return SCIP_ERROR;
3428  }
3429 
3430  *result = SCIP_SUCCESS;
3431  return SCIP_OKAY;
3432  }
3433 
3434  return SCIP_OKAY;
3435 }
3436 
3438 static
3439 SCIP_Bool allVarsFixed(
3440  SCIP* scip
3441  )
3442 {
3443  SCIP_VAR** vars;
3444  int i;
3445 
3446  assert( scip != NULL );
3447 
3448  vars = SCIPgetVars(scip);
3449 
3450  /* try to find a variable that is not fixed */
3451  for (i = 0; i < SCIPgetNVars(scip); i++)
3452  {
3453  if ( SCIPisLT(scip, SCIPvarGetLbLocal(vars[i]), SCIPvarGetUbLocal(vars[i])) )
3454  return FALSE;
3455  }
3456 
3457  /* if no variable with lower bound strictly lower than upper bound has been found, all variables are fixed */
3458  return TRUE;
3459 }
3460 
3462 static
3463 SCIP_DECL_RELAXEXEC(relaxExecSdp)
3464 {
3465  SCIP_RELAXDATA* relaxdata;
3466  SCIP_VAR** vars;
3467  SCIP_Real* ubs;
3468  SCIP_Bool cutoff;
3469  SCIP_SOL* scipsol; /* TODO: eliminate this */
3470  int nconss;
3471  int nvars;
3472  int i;
3473 #ifdef SCIP_EVEN_MORE_DEBUG
3474  SCIP_VAR** varsfordebug = SCIPgetVars(scip);
3475  const int nvarsfordebug = SCIPgetNVars(scip);
3476 #endif
3477 
3478  SCIPdebugMessage("Calling relaxExecSdp.\n");
3479 
3480  relaxdata = SCIPrelaxGetData(relax);
3481  vars = SCIPgetVars(scip);
3482  nvars = SCIPgetNVars(scip);
3483 
3484  /* don't run again if we already solved the current node (except during probing), and we solved the correct problem */
3485  if ( (relaxdata->lastsdpnode == SCIPnodeGetNumber(SCIPgetCurrentNode(scip)) && ( ! SCIPinProbing(scip) ) ) && relaxdata->origsolved && ! relaxdata->resolve )
3486  {
3487  SCIP_COL** cols;
3488  SCIP_Real objforscip;
3489  SCIP_Real* solforscip;
3490  int ncols;
3491  int slength;
3492 
3493  SCIPdebugMessage("Already solved SDP-relaxation for node %ld, returning with SCIP_SUCCESS so that no other relaxator is called.\n",
3494  SCIPrelaxGetData(relax)->lastsdpnode);
3495 
3496  if ( SCIPsdpiIsDualUnbounded(relaxdata->sdpi) )
3497  {
3498  relaxdata->feasible = TRUE;
3499  *result = SCIP_SUCCESS;
3500  *lowerbound = -SCIPinfinity(scip);
3501  return SCIP_OKAY;
3502  }
3503 
3504  /* get solution w.r.t. SCIP variables */
3505  SCIP_CALL( SCIPallocBufferArray(scip, &solforscip, nvars) );
3506  slength = nvars;
3507  SCIP_CALL( SCIPsdpiGetSol(relaxdata->sdpi, &objforscip, solforscip, &slength) ); /* get both the objective and the solution from the SDP solver */
3508 
3509  assert( slength == nvars ); /* If this isn't true any longer, the getSol-Call was unsuccessfull, because the given array wasn't long enough,
3510  * but this can't happen, because the array has enough space for all sdp variables. */
3511 
3512  /* create SCIP solution */
3513  SCIP_CALL( SCIPcreateSol(scip, &scipsol, NULL) );
3514  SCIP_CALL( SCIPsetRelaxSolVals(scip, nvars, vars, solforscip, TRUE) );
3515 
3516  *lowerbound = objforscip;
3517 
3518  /* copy solution */
3519  SCIP_CALL( SCIPgetLPColsData(scip, &cols, &ncols) );
3520  for (i = 0; i < ncols; i++)
3521  {
3522  SCIP_CALL( SCIPsetRelaxSolVal(scip, SCIPcolGetVar(cols[i]), SCIPgetSolVal(scip, scipsol, SCIPcolGetVar(cols[i]))) );
3523  }
3524 
3525  SCIP_CALL( SCIPmarkRelaxSolValid(scip, TRUE) );
3526  *result = SCIP_SUCCESS;
3527 
3528  SCIPfreeBufferArray(scip, &solforscip);
3529  SCIP_CALL( SCIPfreeSol(scip, &scipsol) );
3530 
3531  *result = SCIP_SUCCESS;
3532  return SCIP_OKAY;
3533  }
3534 
3535  /* if we are solving a probing SDP, remember that we didn't solve the original problem */
3536  relaxdata->origsolved = FALSE;
3537 
3538  /* construct the lp and make sure, that everything is where it should be */
3539  SCIP_CALL( SCIPconstructLP(scip, &cutoff) );
3540 
3541  if ( cutoff )
3542  {
3543  relaxdata->feasible = FALSE;
3544  *result = SCIP_CUTOFF;
3545  return SCIP_OKAY;
3546  }
3547 
3548  /* very important to call flushLP */
3549  SCIP_CALL( SCIPflushLP(scip) );
3550 
3551  /* get varmapper */
3552  nconss = SCIPgetNConss(scip);
3553 
3554 #ifdef SCIP_EVEN_MORE_DEBUG
3555  for (i = 0; i < nvarsfordebug; i++)
3556  {
3557  SCIPdebugMessage("variable %s: status = %u, integral = %u, bounds = [%f, %f] \n", SCIPvarGetName(varsfordebug[i]), SCIPvarGetStatus(varsfordebug[i]),
3558  SCIPvarIsIntegral(varsfordebug[i]), SCIPvarGetLbLocal(varsfordebug[i]), SCIPvarGetUbLocal(varsfordebug[i]));
3559  }
3560 #endif
3561 
3562  if ( nconss == 0 )
3563  {
3564  /* if there are no constraints, there is nothing to do */
3565  relaxdata->feasible = TRUE;
3566  *result = SCIP_DIDNOTRUN;
3567  return SCIP_OKAY;
3568  }
3569 
3570  if ( allVarsFixed(scip) )
3571  {
3572  SCIP_Bool feasible;
3573 
3574  /* if all variables, really all, are fixed, we give this fixed solution to SCIP */
3575 
3576  SCIP_CALL( SCIPallocBufferArray(scip, &ubs, nvars) );
3577 
3578  *lowerbound = 0.0;
3579  for (i = 0; i < nvars; i++)
3580  {
3581  ubs[i] = SCIPvarGetUbLocal(vars[i]);
3582  *lowerbound += SCIPvarGetObj(vars[i]) * ubs[i];
3583  assert( SCIPisFeasEQ(scip, SCIPvarGetUbLocal(vars[i]), SCIPvarGetLbLocal(vars[i])));
3584  }
3585 
3586  SCIPdebugMessage("EVERYTHING IS FIXED, objective value = %f\n", *lowerbound);
3587 
3588  SCIP_CALL( SCIPcreateSol(scip, &scipsol, NULL) );
3589  SCIP_CALL( SCIPsetSolVals(scip, scipsol, nvars, vars, ubs) );
3590 
3591  /* set the relaxation solution */
3592  for (i = 0; i < nvars; i++)
3593  {
3594  SCIP_CALL( SCIPsetRelaxSolVal(scip, vars[i], SCIPvarGetLbLocal(vars[i])) );
3595  }
3596  SCIP_CALL( SCIPmarkRelaxSolValid(scip, TRUE) );
3597 
3598  /* check if the solution really is feasible */
3599  SCIP_CALL( SCIPcheckSol(scip, scipsol, FALSE, TRUE, TRUE, TRUE, TRUE, &feasible) );
3600 
3601  relaxdata->feasible = feasible;
3602 
3603  SCIP_CALL( SCIPfreeSol(scip, &scipsol) );
3604 
3605  SCIPfreeBufferArray(scip, &ubs);
3606 
3607  *result = SCIP_SUCCESS;
3608  return SCIP_OKAY;
3609  }
3610 
3611  /* update LP Data in Interface */
3612  SCIP_CALL( putLpDataInInterface(scip, relaxdata->sdpi, relaxdata->varmapper, TRUE, TRUE) );
3613 
3614  SCIP_CALL( calcRelax(scip, relaxdata, result, lowerbound));
3615 
3616  return SCIP_OKAY;
3617 }
3618 
3619 
3622 static
3623 SCIP_DECL_RELAXINITSOL(relaxInitSolSdp)
3624 {
3625  SCIP_RELAXDATA* relaxdata;
3626  SCIP_RETCODE retcode;
3627  SCIP_VAR** vars;
3628  SCIP_Real gaptol;
3629  SCIP_Real feastol;
3630  SCIP_Real penaltyparam;
3631  SCIP_Real maxpenaltyparam;
3632  int npenaltyincr;
3633  SCIP_Bool sdpinfo;
3634  SCIP_Real givenpenaltyparam;
3635  SCIP_Real projminevprimal;
3636  SCIP_Real projminevdual;
3637  SCIP_Real preoptgap;
3638  int nthreads;
3639  int slatercheck;
3640  int nvars;
3641 
3642  assert( relax != NULL );
3643 
3644  relaxdata = SCIPrelaxGetData(relax);
3645  assert( relaxdata != NULL );
3646 
3647  relaxdata->objval = 0.0;
3648  relaxdata->origsolved = FALSE;
3649  relaxdata->probingsolved = FALSE;
3650  relaxdata->sdpcalls = 0;
3651  relaxdata->sdpinterfacecalls = 0;
3652  relaxdata->sdpiterations = 0;
3653  relaxdata->solvedfast = 0;
3654  relaxdata->solvedmedium = 0;
3655  relaxdata->solvedstable = 0;
3656  relaxdata->solvedpenalty = 0;
3657  relaxdata->stablewslater = 0;
3658  relaxdata->unstablewslater = 0;
3659  relaxdata->boundedwslater = 0;
3660  relaxdata->unsolvedwslater = 0;
3661  relaxdata->stablenoslater = 0;
3662  relaxdata->unsolvednoslater = 0;
3663  relaxdata->boundednoslater = 0;
3664  relaxdata->unsolvednoslater = 0;
3665  relaxdata->nslaterholds = 0;
3666  relaxdata->nnoslater = 0;
3667  relaxdata->nslatercheckfailed = 0;
3668  relaxdata->npslaterholds = 0;
3669  relaxdata->npnoslater = 0;
3670  relaxdata->npslatercheckfailed = 0;
3671  relaxdata->ndslaterholds = 0;
3672  relaxdata->ndnoslater = 0;
3673  relaxdata->ndslatercheckfailed = 0;
3674  relaxdata->nslaterinfeasible = 0;
3675  relaxdata->stableinfeasible = 0;
3676  relaxdata->unstableinfeasible = 0;
3677  relaxdata->penaltyinfeasible = 0;
3678  relaxdata->boundedinfeasible = 0;
3679  relaxdata->unsolvedinfeasible = 0;
3680  relaxdata->roundingprobinf = 0;
3681  relaxdata->primalroundfails = 0;
3682  relaxdata->dualroundfails = 0;
3683  relaxdata->roundstartsuccess = 0;
3684  relaxdata->roundingoptimal = 0;
3685  relaxdata->roundingcutoff = 0;
3686  relaxdata->roundingprobtime = 0.0;
3687  relaxdata->unsolved = 0;
3688  relaxdata->feasible = FALSE;
3689 
3690  nvars = SCIPgetNVars(scip);
3691  vars = SCIPgetVars(scip);
3692 
3693  /* all SCIPvars will be added to this list, and 3/4 seems like a good load factor (java uses this factor) */
3694  SCIP_CALL( SCIPsdpVarmapperCreate(scip, &(relaxdata->varmapper), (int) ceil(1.33 * nvars)) );
3695  SCIP_CALL( SCIPsdpVarmapperAddVars(scip, relaxdata->varmapper, nvars, vars) );
3696 
3697  if ( nvars > 0 )
3698  {
3699  SCIP_CALL( putSdpDataInInterface(scip, relaxdata->sdpi, relaxdata->varmapper, TRUE, FALSE) );
3700  }
3701 
3702  /* set the parameters of the SDP-Solver */
3703  SCIP_CALL( SCIPgetRealParam(scip, "relaxing/SDP/sdpsolvergaptol", &gaptol) );
3704  retcode = SCIPsdpiSetRealpar(relaxdata->sdpi, SCIP_SDPPAR_GAPTOL, gaptol);
3705  if ( retcode == SCIP_PARAMETERUNKNOWN )
3706  {
3707  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL,
3708  "SDP Solver <%s>: gaptol setting not available -- SCIP parameter has no effect.\n",
3710  }
3711  else
3712  {
3713  SCIP_CALL( retcode );
3714  }
3715 
3716  SCIP_CALL( SCIPgetRealParam(scip, "relaxing/SDP/sdpsolverfeastol", &feastol) );
3717  retcode = SCIPsdpiSetRealpar(relaxdata->sdpi, SCIP_SDPPAR_SDPSOLVERFEASTOL, feastol);
3718  if ( retcode == SCIP_PARAMETERUNKNOWN )
3719  {
3720  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL,
3721  "SDP Solver <%s>: sdpsolverfeastol setting not available -- SCIP parameter has no effect.\n",
3723  }
3724  else
3725  {
3726  SCIP_CALL( retcode );
3727  }
3728 
3729  retcode = SCIPsdpiSetRealpar(relaxdata->sdpi, SCIP_SDPPAR_EPSILON, SCIPepsilon(scip));
3730  if ( retcode == SCIP_PARAMETERUNKNOWN )
3731  {
3732  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL,
3733  "SDP Solver <%s>: epsilon setting not available -- SCIP parameter has no effect.\n",
3735  }
3736  else
3737  {
3738  SCIP_CALL( retcode );
3739  }
3740 
3741  retcode = SCIPsdpiSetRealpar(relaxdata->sdpi, SCIP_SDPPAR_FEASTOL, SCIPfeastol(scip));
3742  if ( retcode == SCIP_PARAMETERUNKNOWN )
3743  {
3744  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL,
3745  "SDP Solver <%s>: feastol setting not available -- SCIP parameter has no effect.\n",
3747  }
3748  else
3749  {
3750  SCIP_CALL( retcode );
3751  }
3752 
3753  /* set/compute the starting penalty parameter */
3754  SCIP_CALL( SCIPgetRealParam(scip, "relaxing/SDP/penaltyparam", &penaltyparam) );
3755  if ( SCIPisGE(scip, penaltyparam, 0.0) )
3756  {
3757  retcode = SCIPsdpiSetRealpar(relaxdata->sdpi, SCIP_SDPPAR_PENALTYPARAM, penaltyparam);
3758  givenpenaltyparam = penaltyparam;
3759  if ( retcode == SCIP_PARAMETERUNKNOWN )
3760  {
3761  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL,
3762  "SDP Solver <%s>: penaltyparam setting not available -- SCIP parameter has no effect\n",
3764  }
3765  else
3766  {
3767  SCIP_CALL( retcode );
3768  }
3769  }
3770  else
3771  {
3772  SCIP_Real maxcoeff;
3773  int v;
3774 
3775  /* compute the maximum coefficient in the objective */
3776  maxcoeff = 0.0;
3777  for (v = 0; v < nvars; v++)
3778  {
3779  if ( SCIPisGT(scip, REALABS(SCIPvarGetObj(vars[v])), maxcoeff) )
3780  maxcoeff = REALABS(SCIPvarGetObj(vars[v]));
3781  }
3782 
3783  SCIP_CALL( SCIPsdpiComputePenaltyparam(relaxdata->sdpi, maxcoeff, &givenpenaltyparam) );
3784  }
3785 
3786  /* set/compute the maximum penalty parameter */
3787  SCIP_CALL( SCIPgetRealParam(scip, "relaxing/SDP/maxpenaltyparam", &maxpenaltyparam) );
3788  if ( SCIPisGE(scip, maxpenaltyparam, 0.0) )
3789  {
3790  retcode = SCIPsdpiSetRealpar(relaxdata->sdpi, SCIP_SDPPAR_MAXPENALTYPARAM, maxpenaltyparam);
3791 
3792  if ( retcode == SCIP_PARAMETERUNKNOWN )
3793  {
3794  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL,
3795  "SDP Solver <%s>: maxpenaltyparam setting not available -- SCIP parameter has no effect.\n",
3797  }
3798  else
3799  {
3800  SCIP_CALL( retcode );
3801  }
3802 
3803  /* check if the starting value is not bigger than the maximum one, otherwise update it */
3804  if ( SCIPisLT(scip, givenpenaltyparam, maxpenaltyparam) )
3805  {
3806  SCIPdebugMessage("Penalty parameter %f overwritten by maxpenaltyparam %f! \n", givenpenaltyparam, maxpenaltyparam);
3807  SCIP_CALL( SCIPsdpiSetRealpar(relaxdata->sdpi, SCIP_SDPPAR_PENALTYPARAM, maxpenaltyparam) );
3808  }
3809  }
3810  else
3811  {
3812  SCIP_Real givenmaxpenaltyparam;
3813 
3814  SCIP_CALL( SCIPsdpiComputeMaxPenaltyparam(relaxdata->sdpi, givenpenaltyparam, &givenmaxpenaltyparam) );
3815  }
3816 
3817  /* set maximum number of penalty increasing rounds */
3818  SCIP_CALL( SCIPgetIntParam(scip, "relaxing/SDP/npenaltyincr", &npenaltyincr) );
3819  retcode = SCIPsdpiSetIntpar(relaxdata->sdpi, SCIP_SDPPAR_NPENALTYINCR, npenaltyincr);
3820  if ( retcode == SCIP_PARAMETERUNKNOWN )
3821  {
3822  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL,
3823  "SDP Solver <%s>: npenaltyincr setting not available -- SCIP parameter has no effect.\n",
3825  }
3826  else
3827  {
3828  SCIP_CALL( retcode );
3829  }
3830 
3831 
3832  /* set/compute lambda star if SDPA is used as the SDP-Solver */
3833  if ( strcmp(SCIPsdpiGetSolverName(), "SDPA") == 0.0 )
3834  {
3835  SCIP_Real lambdastar;
3836 
3837  SCIP_CALL( SCIPgetRealParam(scip, "relaxing/SDP/lambdastar", &lambdastar) );
3838  if ( SCIPisGE(scip, lambdastar, 0.0) )
3839  {
3840  retcode = SCIPsdpiSetRealpar(relaxdata->sdpi, SCIP_SDPPAR_LAMBDASTAR, lambdastar);
3841  }
3842  else
3843  {
3844  SCIP_Real guess;
3845  SCIP_Real maxguess;
3846  SCIP_CONS** conss;
3847  int nconss;
3848  int c;
3849 
3850  /* iterate over all SDP-constraints to compute the biggest guess for lambdastar */
3851  conss = SCIPgetConss(scip);
3852  nconss = SCIPgetNConss(scip);
3853  maxguess = 0.0;
3854 
3855  for (c = 0; c < nconss; c++)
3856  {
3857  /* only check the SDP constraints */
3858  if ( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(conss[c])), "SDP") == 0 )
3859  {
3860  SCIP_CALL( SCIPconsSdpGuessInitialPoint(scip, conss[c], &guess) );
3861  if ( (! SCIPisInfinity(scip, maxguess) ) && SCIPisGT(scip, guess, maxguess) )
3862  maxguess = guess;
3863  }
3864  }
3865 
3866  SCIP_CALL( SCIPsdpiComputeLambdastar(relaxdata->sdpi, maxguess) );
3867  }
3868  retcode = SCIPsdpiGetRealpar(relaxdata->sdpi, SCIP_SDPPAR_LAMBDASTAR, &relaxdata->lambdastar);
3869  }
3870  else
3871  relaxdata->lambdastar = 1.0;
3872 
3873  if ( retcode == SCIP_PARAMETERUNKNOWN )
3874  {
3875  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL,
3876  "SDP Solver <%s>: lambdastar setting not available -- SCIP parameter has no effect.\n",
3878  }
3879  else
3880  {
3881  SCIP_CALL( retcode );
3882  }
3883 
3884  /* set/compute minimum eigenvalue for projecting warmstarting points */
3885  SCIP_CALL( SCIPgetRealParam(scip, "relaxing/SDP/warmstartprminevpri", &projminevprimal) );
3886  SCIP_CALL( SCIPgetRealParam(scip, "relaxing/SDP/warmstartprminevdu", &projminevdual) );
3887 
3888  if ( SCIPisGE(scip, projminevprimal, 0.0) && SCIPisGE(scip, projminevdual, 0.0) )
3889  {
3890  relaxdata->warmstartprojminevprimal = projminevprimal;
3891  relaxdata->warmstartprojminevdual = projminevdual;
3892  }
3893  else if ( SCIPisGE(scip, projminevprimal, 0.0) && relaxdata->warmstartprojpdsame )
3894  {
3895  relaxdata->warmstartprojminevprimal = projminevprimal;
3896  relaxdata->warmstartprojminevdual = projminevprimal;
3897  }
3898  else if ( SCIPisGE(scip, projminevdual, 0.0) && relaxdata->warmstartprojpdsame )
3899  {
3900  relaxdata->warmstartprojminevprimal = projminevdual;
3901  relaxdata->warmstartprojminevdual = projminevdual;
3902  }
3903  else
3904  {
3905  SCIP_CONSHDLR* sdpconshdlr;
3906  SCIP_CONS** sdpblocks;
3907  int nsdpblocks;
3908  int b;
3909  int v;
3910  SCIP_Real maxsdprhs; /* note that we only take the maximum value of the SDP constraints, since these tend to be the most problematic */
3911  SCIP_Real maxobj;
3912  SCIP_Real maxsdpcoef; /* note that we only take the maximum value of the SDP constraints, since these tend to be the most problematic */
3913  SCIP_Real maxval;
3914  SCIP_Real sdpcoef;
3915 
3916  /* compute value as WARMSTART_PROJ_FACTOR * max{maxrhs, maxobj, maxsdpcoef} */
3917  sdpconshdlr = SCIPfindConshdlr(scip, "SDP");
3918  nsdpblocks = SCIPconshdlrGetNConss(sdpconshdlr);
3919  sdpblocks = SCIPconshdlrGetConss(sdpconshdlr);
3920 
3921  /* compute maxsdpcoef */
3922  maxsdpcoef = WARMSTART_PROJ_MINRHSOBJ;
3923  for (b = 0; b < nsdpblocks; b++)
3924  {
3925  sdpcoef = SCIPconsSdpGetMaxSdpCoef(scip, sdpblocks[b]);
3926  if ( SCIPisGT(scip, sdpcoef, maxsdpcoef) )
3927  maxsdpcoef = sdpcoef;
3928  }
3929  maxsdpcoef *= WARMSTART_PROJ_FACTOR_LHS; /* multiply by additional factor to account for summation of lhs entries */
3930 
3931  /* compute maxsdprhs */
3932  maxsdprhs = WARMSTART_PROJ_MINRHSOBJ;
3933  for (b = 0; b < nsdpblocks; b++)
3934  {
3935  if ( SCIPisGT(scip, SCIPconsSdpGetMaxConstEntry(scip, sdpblocks[b]), maxsdprhs) )
3936  maxsdprhs = SCIPconsSdpGetMaxConstEntry(scip, sdpblocks[b]);
3937  }
3938 
3939  /* compute maxobj */
3940  maxobj = WARMSTART_PROJ_MINRHSOBJ;
3941  for (v = 0; v < nvars; v++)
3942  {
3943  if ( SCIPisGT(scip, REALABS(SCIPvarGetObj(vars[v])), maxobj) )
3944  maxobj = REALABS(SCIPvarGetObj(vars[v]));
3945  }
3946 
3947  if ( relaxdata->warmstartprojpdsame )
3948  {
3949  maxval = SCIPisGT(scip, maxsdprhs, maxobj) ? maxsdprhs : maxobj;
3950  maxval = SCIPisGT(scip, maxsdpcoef, maxval) ? maxsdpcoef : maxval;
3951 
3952  relaxdata->warmstartprojminevprimal = WARMSTART_PROJ_FACTOR * maxval;
3953  relaxdata->warmstartprojminevdual = WARMSTART_PROJ_FACTOR * maxval;
3954 
3955  SCIPdebugMsg(scip, "Setting warmstartprojminev to %f\n", relaxdata->warmstartprojminevdual);
3956  }
3957  else
3958  {
3959  if ( ! SCIPisGE(scip, projminevprimal, 0.0) )
3960  {
3961  relaxdata->warmstartprojminevprimal = WARMSTART_PROJ_FACTOR_PRIMAL * (SCIPisGT(scip, maxobj, maxsdpcoef) ? maxobj : maxsdpcoef);
3962 
3963  SCIPdebugMsg(scip, "Setting warmstartprojminevprimal to %f\n", relaxdata->warmstartprojminevprimal);
3964  }
3965 
3966  if ( ! SCIPisGE(scip, projminevdual, 0.0) )
3967  {
3968  relaxdata->warmstartprojminevdual = WARMSTART_PROJ_FACTOR_PRIMAL * (SCIPisGT(scip, maxsdprhs, maxsdpcoef) ? maxsdprhs : maxsdpcoef);
3969 
3970  SCIPdebugMsg(scip, "Setting warmstartprojminevdual to %f\n", relaxdata->warmstartprojminevdual);
3971  }
3972  }
3973  }
3974 
3975  SCIP_CALL( SCIPgetBoolParam(scip, "relaxing/SDP/sdpinfo", &sdpinfo) );
3976  retcode = SCIPsdpiSetIntpar(relaxdata->sdpi, SCIP_SDPPAR_SDPINFO, (int) sdpinfo);
3977  if ( retcode == SCIP_PARAMETERUNKNOWN )
3978  {
3979  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL,
3980  "SDP Solver <%s>: sdpinfo setting not available -- SCIP parameter has no effect.\n",
3982  }
3983  else
3984  {
3985  SCIP_CALL( retcode );
3986  }
3987 
3988  SCIP_CALL( SCIPgetIntParam(scip, "relaxing/SDP/sdpsolverthreads", &nthreads) );
3989  /* only try to set nthreads if the value differs from the default to prevent unnecessary warning messages for unknown parameter */
3990  if ( nthreads != DEFAULT_SDPSOLVERTHREADS )
3991  {
3992  retcode = SCIPsdpiSetIntpar(relaxdata->sdpi, SCIP_SDPPAR_NTHREADS, nthreads);
3993  if ( retcode == SCIP_PARAMETERUNKNOWN )
3994  {
3995  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL,
3996  "SDP Solver <%s>: nthreads setting not available -- SCIP parameter has no effect.\n",
3998  }
3999  else
4000  {
4001  SCIP_CALL( retcode );
4002  }
4003  }
4004 
4005  SCIP_CALL( SCIPgetIntParam(scip, "relaxing/SDP/slatercheck", &slatercheck) );
4006  retcode = SCIPsdpiSetIntpar(relaxdata->sdpi, SCIP_SDPPAR_SLATERCHECK, slatercheck);
4007  if ( retcode == SCIP_PARAMETERUNKNOWN )
4008  {
4009  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL,
4010  "SDP Solver <%s>: slatercheck setting not available -- SCIP parameter has no effect.\n",
4012  }
4013  else
4014  {
4015  SCIP_CALL( retcode );
4016  }
4017 
4018  /* initialize objective limit in case it was set in an earlier optimize call */
4019  SCIP_CALL( SCIPsdpiSetRealpar(relaxdata->sdpi, SCIP_SDPPAR_OBJLIMIT, SCIPsdpiInfinity(relaxdata->sdpi)) );
4020 
4021  /* set warmstartpreoptimal gap if DSDP is used as the SDP-Solver and preoptimal solutions should be saved */
4022  if ( relaxdata->warmstartpreoptsol && (strcmp(SCIPsdpiGetSolverName(), "DSDP") == 0.0 || strcmp(SCIPsdpiGetSolverName(), "SDPA") == 0.0) )
4023  {
4024  SCIP_CALL( SCIPgetRealParam(scip, "relaxing/SDP/warmstartpreoptgap", &preoptgap) );
4025  retcode = SCIPsdpiSetRealpar(relaxdata->sdpi, SCIP_SDPPAR_WARMSTARTPOGAP, preoptgap);
4026  if ( retcode == SCIP_PARAMETERUNKNOWN )
4027  {
4028  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL,
4029  "SDP Solver <%s>: warmstartpreoptgap setting not available -- SCIP parameter has no effect.\n",
4031  }
4032  else
4033  {
4034  SCIP_CALL( retcode );
4035  }
4036  }
4037 
4038  return SCIP_OKAY;
4039 }
4040 
4042 static
4043 SCIP_DECL_RELAXCOPY(relaxCopySdp)
4044 {
4045  assert( scip != NULL );
4046  assert( relax != NULL );
4047  assert( strcmp(SCIPrelaxGetName(relax), RELAX_NAME) == 0 );
4048 
4049  SCIP_CALL( SCIPincludeRelaxSdp(scip) );
4050 
4051  return SCIP_OKAY;
4052 }
4053 
4055 static
4056 SCIP_DECL_RELAXEXIT(relaxExitSdp)
4057 {
4058  SCIP_RELAXDATA* relaxdata;
4059 
4060  assert( scip != NULL );
4061  assert( relax != NULL );
4062 
4063  relaxdata = SCIPrelaxGetData(relax);
4064  assert( relaxdata != NULL );
4065 
4066  SCIPdebugMessage("Exiting Relaxation Handler.\n");
4067 
4068  if ( relaxdata->displaystat && SCIPgetSubscipDepth(scip) == 0 )
4069  {
4070  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "\nSDP iterations:\t\t\t\t%6d\n", relaxdata->sdpiterations);
4071  if ( relaxdata->sdpcalls )
4072  {
4073  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Average SDP-iterations:\t\t\t%6.2f \n", (SCIP_Real) relaxdata->sdpiterations / (SCIP_Real) relaxdata->sdpcalls );
4074  }
4075  if ( relaxdata->sdpinterfacecalls )
4076  {
4077  if ( strcmp(SCIPsdpiGetSolverName(), "SDPA") == 0 )
4078  {
4079  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'fastest settings' solved:\t%6.2f \n", 100.0 * (SCIP_Real) relaxdata->solvedfast / (SCIP_Real) relaxdata->sdpinterfacecalls);
4080  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'medium settings' solved:\t%6.2f \n", 100.0 * (SCIP_Real) relaxdata->solvedmedium / (SCIP_Real) relaxdata->sdpinterfacecalls);
4081  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'stable settings' solved:\t%6.2f \n", 100.0 * (SCIP_Real) relaxdata->solvedstable / (SCIP_Real) relaxdata->sdpinterfacecalls);
4082  }
4083  else
4084  {
4085  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'default formulation' solved:\t%6.2f \n", 100.0 * (SCIP_Real) relaxdata->solvedfast / (SCIP_Real) relaxdata->sdpinterfacecalls);
4086  }
4087  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage penalty formulation used:\t%6.2f \n", 100.0 * (SCIP_Real) relaxdata->solvedpenalty / (SCIP_Real) relaxdata->sdpinterfacecalls);
4088  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage unsolved even with penalty:\t%6.2f \n", 100.0 * (SCIP_Real) relaxdata->unsolved / (SCIP_Real) relaxdata->sdpinterfacecalls);
4089  }
4090  if ( relaxdata->slatercheck )
4091  {
4092  if ( relaxdata->sdpinterfacecalls )
4093  {
4094  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage primal Slater condition held:\t%6.2f \n", 100.0 * (SCIP_Real) relaxdata->npslaterholds / (SCIP_Real) relaxdata->sdpinterfacecalls);
4095  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage primal Slater condition did not hold:\t%6.2f \n", 100.0 * (SCIP_Real) relaxdata->npnoslater / (SCIP_Real) relaxdata->sdpinterfacecalls);
4096  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage primal Slater check failed:\t%6.2f \n", 100.0 * (SCIP_Real) relaxdata->npslatercheckfailed / (SCIP_Real) relaxdata->sdpinterfacecalls);
4097 
4098  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage dual Slater condition held:\t%6.2f \n", 100.0 * (SCIP_Real) relaxdata->ndslaterholds / (SCIP_Real) relaxdata->sdpinterfacecalls);
4099  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage dual Slater condition did not hold:\t%6.2f \n", 100.0 * (SCIP_Real) relaxdata->ndnoslater / (SCIP_Real) relaxdata->sdpinterfacecalls);
4100  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage dual Slater check failed:\t%6.2f \n", 100.0 * (SCIP_Real) relaxdata->ndslatercheckfailed / (SCIP_Real) relaxdata->sdpinterfacecalls);
4101  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage dual Slater check detected infeasibility:\t%6.2f \n", 100.0 * (SCIP_Real) relaxdata->nslaterinfeasible / (SCIP_Real) relaxdata->sdpinterfacecalls);
4102  }
4103  if ( relaxdata->nslaterholds )
4104  {
4105  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'fastest settings' with primal and dual slater holding:\t%6.2f \n",
4106  100.0 * (SCIP_Real) relaxdata->stablewslater / (SCIP_Real) relaxdata->nslaterholds);
4107  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'stable settings' with primal and dual slater holding:\t%6.2f \n",
4108  100.0 * (SCIP_Real) relaxdata->unstablewslater / (SCIP_Real) relaxdata->nslaterholds);
4109  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'penalty' with primal and dual slater holding:\t%6.2f \n",
4110  100.0 * (SCIP_Real) relaxdata->penaltywslater / (SCIP_Real) relaxdata->nslaterholds);
4111  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'computed infeasible lower bound' with primal and dual slater holding:\t%6.2f \n",
4112  100.0 * (SCIP_Real) relaxdata->boundedwslater / (SCIP_Real) relaxdata->nslaterholds);
4113  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'unsolved' with primal and dual slater holding:\t%6.2f \n",
4114  100.0 * (SCIP_Real) relaxdata->unsolvedwslater / (SCIP_Real) relaxdata->nslaterholds);
4115  }
4116  if ( relaxdata->nnoslater )
4117  {
4118  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'fastest settings' with either primal or dual slater not holding:\t%6.2f \n",
4119  100.0 * (SCIP_Real) relaxdata->stablenoslater / (SCIP_Real) relaxdata->nnoslater);
4120  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'stable settings' with either primal or dual slater not holding:\t%6.2f \n",
4121  100.0 * (SCIP_Real) relaxdata->unstablenoslater / (SCIP_Real) relaxdata->nnoslater);
4122  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'penalty' with either primal or dual slater not holding:\t%6.2f \n",
4123  100.0 * (SCIP_Real) relaxdata->penaltynoslater / (SCIP_Real) relaxdata->nnoslater);
4124  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'computed infeasible lower bound' with either primal or dual slater not holding:\t%6.2f \n",
4125  100.0 * (SCIP_Real) relaxdata->boundednoslater / (SCIP_Real) relaxdata->nnoslater);
4126  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'unsolved' with either primal or dual slater not holding:\t%6.2f \n",
4127  100.0 * (SCIP_Real) relaxdata->unsolvednoslater / (SCIP_Real) relaxdata->nnoslater);
4128  }
4129  if ( relaxdata->nslaterinfeasible )
4130  {
4131  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'fastest settings' with slater check showing infeasibility:\t%6.2f \n",
4132  100.0 * (SCIP_Real) relaxdata->stableinfeasible / (SCIP_Real) relaxdata->nslaterinfeasible);
4133  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'stable settings' with slater check showing infeasibility:\t%6.2f \n",
4134  100.0 * (SCIP_Real) relaxdata->unstableinfeasible / (SCIP_Real) relaxdata->nslaterinfeasible);
4135  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'penalty' with slater check showing infeasibility:\t%6.2f \n",
4136  100.0 * (SCIP_Real) relaxdata->penaltyinfeasible / (SCIP_Real) relaxdata->nslaterinfeasible);
4137  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'computed infeasible lower bound' with slater check showing infeasibility:\t%6.2f \n",
4138  100.0 * (SCIP_Real) relaxdata->boundedinfeasible / (SCIP_Real) relaxdata->nslaterinfeasible);
4139  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'unsolved' with slater check showing infeasibility:\t%6.2f \n",
4140  100.0 * (SCIP_Real) relaxdata->unsolvedinfeasible / (SCIP_Real) relaxdata->nslaterinfeasible);
4141  }
4142 #ifdef SLATERSOLVED_ABSOLUTE
4143  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes with primal and dual slater holding:\t%d \n", relaxdata->nslaterholds);
4144  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes with 'fastest settings' and primal and dual slater holding:\t%d \n", relaxdata->stablewslater);
4145  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes with 'stable settings' and primal and dual slater holding:\t%d \n", relaxdata->unstablewslater);
4146  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes with 'penalty' and primal and dual slater holding:\t%d \n", relaxdata->penaltywslater);
4147  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes with 'computed infeasible lower bound' and primal and dual slater holding:\t%d \n", relaxdata->boundedwslater);
4148  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes with 'unsolved' and primal and dual slater holding:\t%d \n", relaxdata->unsolvedwslater);
4149 
4150  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes with either primal or dual slater not holding:\t%d \n", relaxdata->nnoslater);
4151  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes with 'fastest settings' and either primal or dual slater not holding:\t%d \n", relaxdata->stablenoslater);
4152  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes with 'stable settings' and either primal or dual slater not holding:\t%d \n", relaxdata->unstablenoslater);
4153  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes with 'penalty' and either primal or dual slater not holding:\t%d \n", relaxdata->penaltynoslater);
4154  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes with 'computed infeasible lower bound' and either primal or dual slater not holding:\t%d \n", relaxdata->boundednoslater);
4155  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes with 'unsolved' and either primal or dual slater not holding:\t%d \n", relaxdata->unsolvednoslater);
4156 
4157  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of infeasible nodes:\t%d \n", relaxdata->nslaterinfeasible);
4158  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of infeasible nodes with 'fastest settings':\t%d \n", relaxdata->stableinfeasible);
4159  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of infeasible nodes with 'stable settings':\t%d \n", relaxdata->unstableinfeasible);
4160  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of infeasible nodes with 'penalty':\t%d \n", relaxdata->penaltyinfeasible);
4161  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of infeasible nodes with 'computed infeasible lower bound':\t%d \n", relaxdata->boundedinfeasible);
4162  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of infeasible nodes with 'unsolved':\t%d \n", relaxdata->unsolvedinfeasible);
4163 #endif
4164  }
4165  if ( relaxdata->warmstart && relaxdata->warmstartproject == 4 )
4166  {
4167  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes detected infeasible through primal rounding problem:\t%d \n", relaxdata->roundingprobinf);
4168  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes that were successfully warmstarted using the rounding problems:\t%d \n", relaxdata->roundstartsuccess);
4169  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes where the primal rounding problem failed:\t%d \n", relaxdata->primalroundfails);
4170  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes where the dual rounding problem failed:\t%d \n", relaxdata->dualroundfails);
4171  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes where the optimal solution was determined by the rounding problem:\t%d \n", relaxdata->roundingoptimal);
4172  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes cut off through bounding by the rounding problem:\t%d \n", relaxdata->roundingcutoff);
4173  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Time spent in rounding problems for warmstarting / detecting infeasibility:\t%f s \n", relaxdata->roundingprobtime);
4174  }
4175  }
4176 
4177  if ( relaxdata->varmapper != NULL )
4178  {
4179  SCIP_CALL( SCIPsdpVarmapperFree(scip, &(relaxdata->varmapper)) );
4180  }
4181 
4182  /* free warmstart data (the nblocks > 0 check is only needed in case the parameter was changed after initsol) */
4183  if ( relaxdata->warmstart && SCIPisGT(scip, relaxdata->warmstartipfactor, 0.0) && relaxdata->nblocks > 0 )
4184  {
4185  int b;
4186 
4187  for (b = 0; b < relaxdata->nblocks; b++)
4188  {
4189  if ( relaxdata->warmstartprimaltype != 2 && SCIPsdpiDoesWarmstartNeedPrimal() && relaxdata->ipXnblocknonz[b] > 0 )
4190  {
4191  SCIPfreeBlockMemoryArrayNull(scip, &(relaxdata->ipXval[b]), relaxdata->ipXnblocknonz[b]);
4192  SCIPfreeBlockMemoryArrayNull(scip, &(relaxdata->ipXcol[b]), relaxdata->ipXnblocknonz[b]);
4193  SCIPfreeBlockMemoryArrayNull(scip, &(relaxdata->ipXrow[b]), relaxdata->ipXnblocknonz[b]);
4194  }
4195  if ( relaxdata->ipZnblocknonz[b] > 0 )
4196  {
4197  SCIPfreeBlockMemoryArrayNull(scip, &(relaxdata->ipZval[b]), relaxdata->ipZnblocknonz[b]);
4198  SCIPfreeBlockMemoryArrayNull(scip, &(relaxdata->ipZcol[b]), relaxdata->ipZnblocknonz[b]);
4199  SCIPfreeBlockMemoryArrayNull(scip, &(relaxdata->ipZrow[b]), relaxdata->ipZnblocknonz[b]);
4200  }
4201  }
4202  if ( relaxdata->warmstartprimaltype != 2 && SCIPsdpiDoesWarmstartNeedPrimal() )
4203  {
4204  SCIPfreeBlockMemoryArrayNull(scip, &relaxdata->ipXval, relaxdata->nblocks);
4205  SCIPfreeBlockMemoryArrayNull(scip, &relaxdata->ipXcol, relaxdata->nblocks);
4206  SCIPfreeBlockMemoryArrayNull(scip, &relaxdata->ipXrow, relaxdata->nblocks);
4207  SCIPfreeBlockMemoryArrayNull(scip, &relaxdata->ipXnblocknonz, relaxdata->nblocks);
4208  }
4209  SCIPfreeBlockMemoryArrayNull(scip, &relaxdata->ipZval, relaxdata->nblocks);
4210  SCIPfreeBlockMemoryArrayNull(scip, &relaxdata->ipZcol, relaxdata->nblocks);
4211  SCIPfreeBlockMemoryArrayNull(scip, &relaxdata->ipZrow, relaxdata->nblocks);
4212  SCIPfreeBlockMemoryArrayNull(scip, &relaxdata->ipZnblocknonz, relaxdata->nblocks);
4213  SCIP_CALL( SCIPfreeSol(scip, &relaxdata->ipy) );
4214  }
4215 
4216  relaxdata->objval = 0.0;
4217  relaxdata->origsolved = FALSE;
4218  relaxdata->probingsolved = FALSE;
4219  relaxdata->feasible = FALSE;
4220  relaxdata->sdpiterations = 0;
4221  relaxdata->sdpcalls = 0;
4222  relaxdata->sdpinterfacecalls = 0;
4223  relaxdata->lastsdpnode = 0;
4224  SCIP_CALL( SCIPsdpiClear(relaxdata->sdpi) );
4225 
4226  return SCIP_OKAY;
4227 }
4228 
4230 static
4231 SCIP_DECL_RELAXFREE(relaxFreeSdp)
4232 {/*lint --e{715}*/
4233  SCIP_RELAXDATA* relaxdata;
4234 
4235  relaxdata = SCIPrelaxGetData(relax);
4236  assert(relaxdata != NULL);
4237 
4238  if ( relaxdata->sdpi != NULL )
4239  {
4240  SCIP_CALL( SCIPsdpiFree(&(relaxdata->sdpi)) );
4241  }
4242  if ( relaxdata->lpi != NULL )
4243  {
4244  SCIP_CALL( SCIPlpiFree(&(relaxdata->lpi)) );
4245  }
4246 
4247  SCIPfreeMemory(scip, &relaxdata);
4248 
4249  SCIPrelaxSetData(relax, NULL);
4250 
4251  return SCIP_OKAY;
4252 }
4253 
4255 SCIP_RETCODE SCIPincludeRelaxSdp(
4256  SCIP* scip
4257  )
4258 {
4259  SCIP_RELAXDATA* relaxdata = NULL;
4260  SCIP_RELAX* relax;
4261  SCIP_SDPI* sdpi;
4262  SCIP_LPI* lpi;
4263 
4264  assert( scip != NULL );
4265 
4266  /* create SDP-relaxator data */
4267  SCIP_CALL( SCIPallocMemory(scip, &relaxdata) );
4268  SCIP_CALL( SCIPsdpiCreate(&sdpi, SCIPgetMessagehdlr(scip), SCIPblkmem(scip), SCIPbuffer(scip)) );
4269  SCIP_CALL( SCIPlpiCreate(&lpi, SCIPgetMessagehdlr(scip), "SDProundingProb", SCIP_OBJSEN_MINIMIZE) );
4270 
4271  relaxdata->sdpi = sdpi;
4272  relaxdata->lpi = lpi;
4273  relaxdata->lastsdpnode = -1;
4274  relaxdata->nblocks = 0;
4275  relaxdata->ipXexists = FALSE;
4276  relaxdata->ipZexists = FALSE;
4277 
4278  /* include relaxator */
4279  SCIP_CALL( SCIPincludeRelaxBasic(scip, &relax, RELAX_NAME, RELAX_DESC, RELAX_PRIORITY, RELAX_FREQ, relaxExecSdp, relaxdata) );
4280  assert( relax != NULL );
4281 
4282  /* include additional callbacks */
4283  SCIP_CALL( SCIPsetRelaxInitsol(scip, relax, relaxInitSolSdp) );
4284  SCIP_CALL( SCIPsetRelaxExit(scip, relax, relaxExitSdp) );
4285  SCIP_CALL( SCIPsetRelaxFree(scip, relax, relaxFreeSdp) );
4286  SCIP_CALL( SCIPsetRelaxCopy(scip, relax, relaxCopySdp) );
4287 
4288  /* add parameters for SDP-solver */
4289  SCIP_CALL( SCIPaddRealParam(scip, "relaxing/SDP/sdpsolvergaptol",
4290  "the stopping criterion for the duality gap the sdpsolver should use",
4291  &(relaxdata->sdpsolvergaptol), TRUE, SCIPsdpiGetDefaultSdpiSolverGaptol(), 1e-20, 0.001, NULL, NULL) );
4292 
4293  SCIP_CALL( SCIPaddRealParam(scip, "relaxing/SDP/sdpsolverfeastol",
4294  "the feasibility tolerance for the SDP solver",
4295  &(relaxdata->sdpsolverfeastol), TRUE, SCIPsdpiGetDefaultSdpiSolverFeastol(), 1e-17, 0.001, NULL, NULL) );
4296 
4297  SCIP_CALL( SCIPaddRealParam(scip, "relaxing/SDP/penaltyparam",
4298  "the starting value of the penalty parameter Gamma used for the penalty formulation if the "
4299  "SDP solver didn't converge; set this to a negative value to compute the parameter depending on the given problem", &(relaxdata->penaltyparam),
4300  TRUE, DEFAULT_PENALTYPARAM, -1.0, 1e+20, NULL, NULL) );
4301 
4302  SCIP_CALL( SCIPaddRealParam(scip, "relaxing/SDP/maxpenaltyparam",
4303  "the maximum value of the penalty parameter Gamma used for the penalty formulation if the "
4304  "SDP solver didn't converge; set this to a negative value to compute the parameter depending on the given problem", &(relaxdata->maxpenaltyparam),
4305  TRUE, DEFAULT_MAXPENALTYPARAM, -1.0, 1e+20, NULL, NULL) );
4306 
4307  SCIP_CALL( SCIPaddRealParam(scip, "relaxing/SDP/warmstartipfactor",
4308  "factor for interior point in convexcombination of IP and parent solution, if warmstarts are enabled", &(relaxdata->warmstartipfactor),
4309  TRUE, DEFAULT_WARMSTARTIPFACTOR, 0.0, 1.0, NULL, NULL) );
4310 
4311  SCIP_CALL( SCIPaddIntParam(scip, "relaxing/SDP/warmstartprimaltype",
4312  "how to warmstart the primal problem? 1: scaled identity/analytic center, 2: elementwise reciprocal, 3: saved primal sol", &(relaxdata->warmstartprimaltype), TRUE,
4313  DEFAULT_WARMSTARTPRIMALTYPE, 1, 3, NULL, NULL) );
4314 
4315  SCIP_CALL( SCIPaddIntParam(scip, "relaxing/SDP/warmstartiptype",
4316  "which interior point to use for convex combination for warmstarts? 1: scaled identity, 2: analytic center", &(relaxdata->warmstartiptype), TRUE,
4317  DEFAULT_WARMSTARTIPTYPE, 1, 2, NULL, NULL) );
4318 
4319  SCIP_CALL( SCIPaddIntParam(scip, "relaxing/SDP/warmstartproject",
4320  "how to update dual matrix for new bounds? 1: use old bounds, 2: use new bounds, 3: use new bounds and project on psd cone, 4: use new bounds and solve rounding problem", &(relaxdata->warmstartproject), TRUE,
4321  DEFAULT_WARMSTARTPROJECT, 1, 4, NULL, NULL) );
4322 
4323  SCIP_CALL( SCIPaddRealParam(scip, "relaxing/SDP/warmstartprminevpri",
4324  "minimum eigenvalue to allow when projecting primal matrices onto the positive (semi-)definite cone for warmstarting; -1 to compute automatically", &(relaxdata->warmstartpmevprimalpar),
4325  TRUE, DEFAULT_WARMSTARTPROJMINEV, -1.0, 1e+20, NULL, NULL) );
4326 
4327  SCIP_CALL( SCIPaddRealParam(scip, "relaxing/SDP/warmstartprminevdu",
4328  "minimum eigenvalue to allow when projecting dual matrices onto the positive (semi-)definite cone for warmstarting; -1 to compute automatically", &(relaxdata->warmstartpmevdualpar),
4329  TRUE, DEFAULT_WARMSTARTPROJMINEV, -1.0, 1e+20, NULL, NULL) );
4330 
4331  SCIP_CALL( SCIPaddBoolParam(scip, "relaxing/SDP/warmstartprojpdsame",
4332  "Should one shared minimum eigenvalue respectively maximum entry be computed for primal and dual problem instead of different ones for primal and dual and each block for projection or convex combination ?",
4333  &(relaxdata->warmstartprojpdsame), TRUE, DEFAULT_WARMSTARTPROJPDSAME, NULL, NULL) );
4334 
4335  SCIP_CALL( SCIPaddBoolParam(scip, "relaxing/SDP/warmstartpreoptsol",
4336  "Should a preoptimal solution (with larger gap) instead of the optimal solution be used for warmstarts",
4337  &(relaxdata->warmstartpreoptsol), TRUE, DEFAULT_WARMSTART_PREOPTIMAL_SOL, NULL, NULL) );
4338 
4339  SCIP_CALL( SCIPaddRealParam(scip, "relaxing/SDP/warmstartpreoptgap",
4340  "If warmstartpreoptsol is TRUE, this is the gap where the preoptimal solution will be saved", &(relaxdata->warmstartpreoptgap),
4341  TRUE, DEFAULT_WARMSTARTPREOPTGAP, 0.0, 1e+20, NULL, NULL) );
4342 
4343  SCIP_CALL( SCIPaddBoolParam(scip, "relaxing/SDP/warmstartroundonlyinf",
4344  "Only use solution of roundingproblem to detect infeasibility (only has an effect for warmstartproject = 4)",
4345  &(relaxdata->warmstartroundonlyinf), TRUE, DEFAULT_WARMSTARTROUNDONLYINF, NULL, NULL) );
4346 
4347  SCIP_CALL( SCIPaddIntParam(scip, "relaxing/SDP/npenaltyincr",
4348  "maximum number of times the penalty parameter will be increased if the penalty formulation failed", &(relaxdata->npenaltyincr), TRUE,
4349  SCIPsdpiGetDefaultSdpiSolverNpenaltyIncreases(), 0, INT_MAX, NULL, NULL) );
4350 
4351  SCIP_CALL( SCIPaddRealParam(scip, "relaxing/SDP/lambdastar",
4352  "the parameter lambda star used by SDPA to set the initial point;"
4353  "set this to a negative value to compute the parameter depending on the given problem", &(relaxdata->lambdastar),
4354  TRUE, DEFAULT_LAMBDASTAR, -1.0, 1e+20, NULL, NULL) );
4355 
4356  SCIP_CALL( SCIPaddIntParam(scip, "relaxing/SDP/slatercheck",
4357  "Should the Slater condition for the primal and dual problem be checked ahead of solving each SDP? 0: no, 1: yes but only for statistics, 2: yes and print warning for "
4358  "every problem not satisfying primal and dual Slater condition", &(relaxdata->slatercheck), TRUE, DEFAULT_SLATERCHECK, 0, 2, NULL, NULL) );
4359 
4360  SCIP_CALL( SCIPaddBoolParam(scip, "relaxing/SDP/sdpinfo",
4361  "Should the SDP solver output information to the screen?",
4362  &(relaxdata->sdpinfo), TRUE, DEFAULT_SDPINFO, NULL, NULL) );
4363 
4364  SCIP_CALL( SCIPaddBoolParam(scip, "relaxing/SDP/warmstart",
4365  "Should the SDP solver try to use warmstarts?",
4366  &(relaxdata->warmstart), TRUE, DEFAULT_WARMSTART, NULL, NULL) );
4367 
4368  SCIP_CALL( SCIPaddBoolParam(scip, "relaxing/SDP/objlimit",
4369  "Should an objective limit be given to the SDP-Solver?",
4370  &(relaxdata->objlimit), TRUE, DEFAULT_OBJLIMIT, NULL, NULL) );
4371 
4372  SCIP_CALL( SCIPaddBoolParam(scip, "relaxing/SDP/resolve",
4373  "Should the relaxation be resolved after bound-tightenings were found during propagation (outside of probing)?",
4374  &(relaxdata->resolve), TRUE, DEFAULT_RESOLVE, NULL, NULL) );
4375 
4376  SCIP_CALL( SCIPaddBoolParam(scip, "relaxing/SDP/tightenvb",
4377  "Should Big-Ms in varbound-like constraints be tightened before giving them to the SDP-solver ?",
4378  &(relaxdata->tightenvb), TRUE, DEFAULT_TIGHTENVB, NULL, NULL) );
4379 
4380  SCIP_CALL( SCIPaddBoolParam(scip, "relaxing/SDP/displaystatistics",
4381  "Should statistics about SDP iterations and solver settings/success be printed after quitting SCIP-SDP ?",
4382  &(relaxdata->displaystat), TRUE, DEFAULT_DISPLAYSTAT, NULL, NULL) );
4383 
4384  SCIP_CALL( SCIPaddIntParam(scip, "relaxing/SDP/settingsresetfreq",
4385  "frequency for resetting parameters in SDP solver and trying again with fastest settings (-1: never, 0: only at depth settingsresetofs);"
4386  "currently only supported for SDPA",
4387  &(relaxdata->settingsresetfreq), TRUE, DEFAULT_SETTINGSRESETFREQ, -1, INT_MAX, NULL, NULL) );
4388 
4389  SCIP_CALL( SCIPaddIntParam(scip, "relaxing/SDP/settingsresetofs",
4390  "frequency offset for resetting parameters in SDP solver and trying again with fastest settings; currently only supported for SDPA",
4391  &(relaxdata->settingsresetofs), TRUE, DEFAULT_SETTINGSRESETOFS, 0, INT_MAX, NULL, NULL) );
4392 
4393  SCIP_CALL( SCIPaddIntParam(scip, "relaxing/SDP/sdpsolverthreads",
4394  "number of threads the SDP solver should use (-1 = number of cores); currently only supported for MOSEK",
4395  &(relaxdata->sdpsolverthreads), TRUE, DEFAULT_SDPSOLVERTHREADS, -1, INT_MAX, NULL, NULL) );
4396 
4397 
4398  /* add description of SDP-solver */
4399  SCIP_CALL( SCIPincludeExternalCodeInformation(scip, SCIPsdpiGetSolverName(), SCIPsdpiGetSolverDesc()) );
4400 
4401  return SCIP_OKAY;
4402 }
4403 
4404 
4405 /* external functions */
4406 
4411  SCIP* scip,
4412  SCIP_RELAX* relax
4413  )
4414 {
4415  SCIP_CONSHDLR* sdpconshdlr;
4416  SCIP_RELAXDATA* relaxdata;
4417 
4418  assert( scip != NULL );
4419  assert( relax != NULL );
4420  assert( SCIPgetStage(scip) == SCIP_STAGE_SOLVING );
4421 
4422  SCIPdebugMsg(scip, "computing analytic centers for warmstarting\n");
4423 
4424  relaxdata = SCIPrelaxGetData(relax);
4425 
4426  /* this function should only be executed once */
4427  if ( relaxdata->ipXexists || relaxdata->ipZexists )
4428  {
4429  SCIPdebugMsg(scip, "aborting SCIPrelaxSdpComputeAnalyticCenters since analytic centers have already been computed\n");
4430  return SCIP_OKAY;
4431  }
4432 
4433  sdpconshdlr = SCIPfindConshdlr(scip, "SDP");
4434 
4435  /* if we want to warmstart using the analytic center, compute it now */
4436  if ( relaxdata->warmstart && (relaxdata->warmstartiptype == 2) && SCIPisGT(scip, relaxdata->warmstartipfactor, 0.0) && (SCIPconshdlrGetNConss(sdpconshdlr) + SCIPgetNLPRows(scip) > 0 ) )
4437  {
4438  int b;
4439 
4440  relaxdata->nblocks = SCIPgetNLPRows(scip) + SCIPgetNVars(scip) > 0 ? SCIPconshdlrGetNConss(sdpconshdlr) + 1 : SCIPconshdlrGetNConss(sdpconshdlr);
4441 
4442  if ( SCIPgetNVars(scip) > 0 )
4443  {
4444  SCIP_ROW** rows;
4445  SCIP_COL** rowcols;
4446  SCIP_CONS** sdpblocks;
4447  SCIP_Real* solforscip;
4448  SCIP_Real* rowvals;
4449  SCIP_Real timelimit;
4450  SCIP_Real rowval;
4451  int slength;
4452  int arraylength;
4453  int nrows;
4454  int rownnonz;
4455  int i;
4456  int r;
4457  int v;
4458  SCIP_SDPSOLVERSETTING usedsetting;
4459  SCIP_SDPSLATERSETTING slatersetting;
4460  SCIP_SDPSLATER primalslater;
4461  SCIP_SDPSLATER dualslater;
4462  int naddediters;
4463  int naddedsdpcalls;
4464 
4465  /* first solve SDP with primal objective (dual constant part) set to zero to compute analytic center of primal feasible set */
4466  if ( relaxdata->warmstartprimaltype != 2 && SCIPsdpiDoesWarmstartNeedPrimal() )
4467  {
4468  SCIP_CALL( putSdpDataInInterface(scip, relaxdata->sdpi, relaxdata->varmapper, FALSE, TRUE) );
4469  SCIP_CALL( putLpDataInInterface(scip, relaxdata->sdpi, relaxdata->varmapper, FALSE, TRUE) );
4470 
4471  /* set time limit */
4472  SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
4473  if ( ! SCIPisInfinity(scip, timelimit) )
4474  {
4475  timelimit -= SCIPgetSolvingTime(scip);
4476  if ( timelimit <= 0.0 )
4477  return SCIP_OKAY;
4478  }
4479 
4480  /* TODO: might want to add an additional parameter to solve to disable penalty, since we cannot use that here anyways */
4481  SCIP_CALL(SCIPsdpiSolve(relaxdata->sdpi, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, SCIP_SDPSOLVERSETTING_UNSOLVED, FALSE, timelimit));
4482 
4483  /* update calls, iterations and stability numbers (only if the SDP-solver was actually called) */
4484  relaxdata->sdpinterfacecalls++;
4485  naddedsdpcalls = 0;
4486  SCIP_CALL( SCIPsdpiGetSdpCalls(relaxdata->sdpi, &naddedsdpcalls) );
4487  usedsetting = SCIP_SDPSOLVERSETTING_UNSOLVED;
4488  if ( naddedsdpcalls )
4489  {
4490  relaxdata->sdpcalls += naddedsdpcalls;
4491  naddediters = 0;
4492  SCIP_CALL( SCIPsdpiGetIterations(relaxdata->sdpi, &naddediters) );
4493  relaxdata->sdpiterations += naddediters;
4494 
4495  SCIP_CALL( SCIPsdpiSettingsUsed(relaxdata->sdpi, &usedsetting) );
4496 
4497  switch( usedsetting )/*lint --e{788}*/
4498  {
4500  relaxdata->solvedpenalty++;
4501  break;
4503  relaxdata->solvedfast++;
4504  break;
4506  relaxdata->solvedmedium++;
4507  break;
4509  relaxdata->solvedstable++;
4510  break;
4512  relaxdata->unsolved++;
4513  break;
4514  default:
4515  break;
4516  }
4517  primalslater = SCIP_SDPSLATER_NOINFO;
4518  dualslater = SCIP_SDPSLATER_NOINFO;
4519  SCIP_CALL( SCIPsdpiSlater(relaxdata->sdpi, &primalslater, &dualslater) );
4520  switch( primalslater )/*lint --e{788}*/
4521  {
4522  case SCIP_SDPSLATER_NOINFO:
4523  relaxdata->npslatercheckfailed++;
4524  switch( dualslater )/*lint --e{788}*/
4525  {
4526  case SCIP_SDPSLATER_NOINFO:
4527  relaxdata->ndslatercheckfailed++;
4528  relaxdata->nslatercheckfailed++;
4529  break;
4530  case SCIP_SDPSLATER_NOT:
4531  relaxdata->ndnoslater++;
4532  relaxdata->nnoslater++;
4533  break;
4534  case SCIP_SDPSLATER_HOLDS:
4535  relaxdata->ndslaterholds++;
4536  relaxdata->nslatercheckfailed++;
4537  break;
4538  case SCIP_SDPSLATER_INF:
4539  relaxdata->nslaterinfeasible++;
4540  break;
4541  default:
4542  relaxdata->ndslatercheckfailed++;
4543  relaxdata->nslatercheckfailed++;
4544  break;
4545  }
4546  break;
4547  case SCIP_SDPSLATER_NOT:
4548  relaxdata->npnoslater++;
4549  switch( dualslater )/*lint --e{788}*/
4550  {
4551  case SCIP_SDPSLATER_NOINFO:
4552  relaxdata->ndslatercheckfailed++;
4553  relaxdata->nnoslater++;
4554  break;
4555  case SCIP_SDPSLATER_NOT:
4556  relaxdata->ndnoslater++;
4557  relaxdata->nnoslater++;
4558  break;
4559  case SCIP_SDPSLATER_HOLDS:
4560  relaxdata->ndslaterholds++;
4561  relaxdata->nnoslater++;
4562  break;
4563  case SCIP_SDPSLATER_INF:
4564  relaxdata->nslaterinfeasible++;
4565  break;
4566  default:
4567  relaxdata->ndslatercheckfailed++;
4568  relaxdata->nnoslater++;
4569  break;
4570  }
4571  break;
4572  case SCIP_SDPSLATER_HOLDS:
4573  relaxdata->npslaterholds++;
4574  switch( dualslater )/*lint --e{788}*/
4575  {
4576  case SCIP_SDPSLATER_NOINFO:
4577  relaxdata->ndslatercheckfailed++;
4578  relaxdata->nslatercheckfailed++;
4579  break;
4580  case SCIP_SDPSLATER_NOT:
4581  relaxdata->ndnoslater++;
4582  relaxdata->nnoslater++;
4583  break;
4584  case SCIP_SDPSLATER_HOLDS:
4585  relaxdata->ndslaterholds++;
4586  relaxdata->nslaterholds++;
4587  break;
4588  case SCIP_SDPSLATER_INF:
4589  relaxdata->nslaterinfeasible++;
4590  break;
4591  default:
4592  relaxdata->ndslatercheckfailed++;
4593  relaxdata->nslatercheckfailed++;
4594  break;
4595  }
4596  break;
4597  default:
4598  relaxdata->npslatercheckfailed++;
4599  relaxdata->ndslatercheckfailed++;
4600  relaxdata->nslatercheckfailed++;
4601  break;
4602  }
4603  slatersetting = SCIP_SDPSLATERSETTING_NOINFO;
4604  SCIP_CALL( SCIPsdpiSlaterSettings(relaxdata->sdpi, &slatersetting) );
4605  switch( slatersetting )/*lint --e{788}*/
4606  {
4608  relaxdata->stablewslater++;
4609  break;
4611  relaxdata->unstablewslater++;
4612  break;
4614  relaxdata->penaltywslater++;
4615  break;
4617  relaxdata->boundedwslater++;
4618  break;
4620  relaxdata->unsolvedwslater++;
4621  break;
4623  relaxdata->stablenoslater++;
4624  break;
4626  relaxdata->unstablenoslater++;
4627  break;
4629  relaxdata->penaltynoslater++;
4630  break;
4632  relaxdata->boundednoslater++;
4633  break;
4635  relaxdata->unsolvednoslater++;
4636  break;
4638  relaxdata->stableinfeasible++;
4639  break;
4641  relaxdata->unstableinfeasible++;
4642  break;
4644  relaxdata->penaltyinfeasible++;
4645  break;
4647  relaxdata->boundedinfeasible++;
4648  break;
4650  relaxdata->unsolvedinfeasible++;
4651  break;
4652  default:
4653  break;
4654  }
4655  }
4656 
4657  if ( SCIPsdpiWasSolved(relaxdata->sdpi) && SCIPsdpiSolvedOrig(relaxdata->sdpi) && SCIPsdpiIsPrimalFeasible(relaxdata->sdpi) )
4658  {
4659  int npenaltybounds = 0;
4660 
4661  relaxdata->ipXexists = TRUE;
4662 
4663  /* allocate memory (for the different blocks the neccessary anount first needs to be computed) */
4664  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXnblocknonz, relaxdata->nblocks) );
4665  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXrow, relaxdata->nblocks) );
4666  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXcol, relaxdata->nblocks) );
4667  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXval, relaxdata->nblocks) );
4668 
4669  SCIP_CALL(SCIPsdpiGetPrimalNonzeros(relaxdata->sdpi, relaxdata->nblocks, relaxdata->ipXnblocknonz));
4670  for (b = 0; b < relaxdata->nblocks; b++)
4671  {
4672  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXrow[b], relaxdata->ipXnblocknonz[b]) );
4673  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXcol[b], relaxdata->ipXnblocknonz[b]) );
4674  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXval[b], relaxdata->ipXnblocknonz[b]) );
4675  }
4676 
4677  /* get primal solution */
4678  SCIP_CALL( SCIPsdpiGetPrimalMatrix(relaxdata->sdpi, relaxdata->nblocks, relaxdata->ipXnblocknonz,
4679  relaxdata->ipXrow, relaxdata->ipXcol, relaxdata->ipXval) );
4680 
4681  /* count the number of primal entries corresponding to bounds of the penalty variable and remove them */
4682  for (i = 0; i < relaxdata->ipXnblocknonz[relaxdata->nblocks - 1]; i++)
4683  {
4684  if ( relaxdata->ipXrow[relaxdata->nblocks - 1][i] == SCIPsdpVarmapperGetNVars(relaxdata->varmapper) )
4685  npenaltybounds++;
4686  }
4687 
4688  if ( npenaltybounds > 0 )
4689  {
4690  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &relaxdata->ipXrow[relaxdata->nblocks - 1],
4691  relaxdata->ipXnblocknonz[relaxdata->nblocks - 1], relaxdata->ipXnblocknonz[relaxdata->nblocks - 1] - npenaltybounds) );
4692  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &relaxdata->ipXcol[relaxdata->nblocks - 1],
4693  relaxdata->ipXnblocknonz[relaxdata->nblocks - 1], relaxdata->ipXnblocknonz[relaxdata->nblocks - 1] - npenaltybounds) );
4694  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &relaxdata->ipXval[relaxdata->nblocks - 1],
4695  relaxdata->ipXnblocknonz[relaxdata->nblocks - 1], relaxdata->ipXnblocknonz[relaxdata->nblocks - 1] - npenaltybounds) );
4696  relaxdata->ipXnblocknonz[relaxdata->nblocks - 1] = relaxdata->ipXnblocknonz[relaxdata->nblocks - 1] - npenaltybounds;
4697  }
4698 
4699  for (b = 0; b < relaxdata->nblocks; b++)
4700  {
4701  /* TODO check if they are already sorted (sorting is needed since they will later be merged into warmstart arrays) */
4702  SCIPsdpVarfixerSortRowCol(relaxdata->ipXrow[b], relaxdata->ipXcol[b], relaxdata->ipXval[b], relaxdata->ipXnblocknonz[b]);
4703  }
4704 
4705 #ifdef SCIP_PRINT_WARMSTART
4706  SCIPdebugMessage("Computed primal analytic center:\n");
4707  for (b = 0; b < relaxdata->nblocks; b++)
4708  {
4709  SCIPdebugMessage("primal matrix, block %d:\n", b);
4710  for (i = 0; i < relaxdata->ipXnblocknonz[b]; i++)
4711  {
4712  SCIPdebugMessage("X_%d[%d,%d]: %f\n", b, relaxdata->ipXrow[b][i], relaxdata->ipXcol[b][i], relaxdata->ipXval[b][i]);
4713  }
4714  }
4715 #endif
4716  }
4717  else
4718  {
4719  relaxdata->ipXexists = TRUE;
4720 
4721  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXnblocknonz, relaxdata->nblocks) );
4722  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXrow, relaxdata->nblocks) );
4723  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXcol, relaxdata->nblocks) );
4724  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXval, relaxdata->nblocks) );
4725 
4726  sdpblocks = SCIPconshdlrGetConss(sdpconshdlr);
4727 
4728  for (b = 0; b < relaxdata->nblocks; b++)
4729  {
4730  if ( b < relaxdata->nblocks - 1 )
4731  {
4732  /* SDP block */
4733  relaxdata->ipXnblocknonz[b] = SCIPconsSdpGetBlocksize(scip, sdpblocks[b]);
4734  }
4735  else
4736  {
4737  /* LP block */
4738  relaxdata->ipXnblocknonz[b] = SCIPgetNLPRows(scip) + 2 * SCIPgetNVars(scip);
4739  }
4740  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXrow[b], relaxdata->ipXnblocknonz[b]) );
4741  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXcol[b], relaxdata->ipXnblocknonz[b]) );
4742  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXval[b], relaxdata->ipXnblocknonz[b]) );
4743 
4744  for (i = 0; i < relaxdata->ipXnblocknonz[b]; i++)
4745  {
4746  relaxdata->ipXrow[b][i] = i;
4747  relaxdata->ipXcol[b][i] = i;
4748  relaxdata->ipXval[b][i] = relaxdata->lambdastar;
4749  }
4750  }
4751 
4752  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL, "Failed to compute analytic center of primal feasible set, using scaled identity instead.\n");
4753  }
4754  }
4755 
4756  /* set dual objective coefficients to zero to compute analytic center of dual feasible set */
4757  SCIP_CALL( putSdpDataInInterface(scip, relaxdata->sdpi, relaxdata->varmapper, TRUE, FALSE) );
4758  SCIP_CALL( putLpDataInInterface(scip, relaxdata->sdpi, relaxdata->varmapper, TRUE, FALSE) );
4759 
4760  /* set time limit */
4761  SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
4762  if ( ! SCIPisInfinity(scip, timelimit) )
4763  {
4764  timelimit -= SCIPgetSolvingTime(scip);
4765  if ( timelimit <= 0.0 )
4766  return SCIP_OKAY;
4767  }
4768 
4769  /* TODO: might want to add an additional parameter to solve to disable penalty, since we cannot use that here anyways */
4770  SCIP_CALL(SCIPsdpiSolve(relaxdata->sdpi, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, SCIP_SDPSOLVERSETTING_UNSOLVED, FALSE, timelimit));
4771 
4772  /* update calls, iterations and stability numbers (only if the SDP-solver was actually called) */
4773  naddedsdpcalls = 0;
4774  SCIP_CALL( SCIPsdpiGetSdpCalls(relaxdata->sdpi, &naddedsdpcalls) );
4775  usedsetting = SCIP_SDPSOLVERSETTING_UNSOLVED;
4776  if ( naddedsdpcalls )
4777  {
4778  relaxdata->sdpinterfacecalls++;
4779  relaxdata->sdpcalls += naddedsdpcalls;
4780  naddediters = 0;
4781  SCIP_CALL( SCIPsdpiGetIterations(relaxdata->sdpi, &naddediters) );
4782  relaxdata->sdpiterations += naddediters;
4783 
4784  SCIP_CALL( SCIPsdpiSettingsUsed(relaxdata->sdpi, &usedsetting) );
4785 
4786  switch( usedsetting )/*lint --e{788}*/
4787  {
4789  relaxdata->solvedpenalty++;
4790  break;
4792  relaxdata->solvedfast++;
4793  break;
4795  relaxdata->solvedmedium++;
4796  break;
4798  relaxdata->solvedstable++;
4799  break;
4801  relaxdata->unsolved++;
4802  break;
4803  default:
4804  break;
4805  }
4806  primalslater = SCIP_SDPSLATER_NOINFO;
4807  dualslater = SCIP_SDPSLATER_NOINFO;
4808  SCIP_CALL( SCIPsdpiSlater(relaxdata->sdpi, &primalslater, &dualslater) );
4809  switch( primalslater )/*lint --e{788}*/
4810  {
4811  case SCIP_SDPSLATER_NOINFO:
4812  relaxdata->npslatercheckfailed++;
4813  switch( dualslater )/*lint --e{788}*/
4814  {
4815  case SCIP_SDPSLATER_NOINFO:
4816  relaxdata->ndslatercheckfailed++;
4817  relaxdata->nslatercheckfailed++;
4818  break;
4819  case SCIP_SDPSLATER_NOT:
4820  relaxdata->ndnoslater++;
4821  relaxdata->nnoslater++;
4822  break;
4823  case SCIP_SDPSLATER_HOLDS:
4824  relaxdata->ndslaterholds++;
4825  relaxdata->nslatercheckfailed++;
4826  break;
4827  case SCIP_SDPSLATER_INF:
4828  relaxdata->nslaterinfeasible++;
4829  break;
4830  default:
4831  relaxdata->ndslatercheckfailed++;
4832  relaxdata->nslatercheckfailed++;
4833  break;
4834  }
4835  break;
4836  case SCIP_SDPSLATER_NOT:
4837  relaxdata->npnoslater++;
4838  switch( dualslater )/*lint --e{788}*/
4839  {
4840  case SCIP_SDPSLATER_NOINFO:
4841  relaxdata->ndslatercheckfailed++;
4842  relaxdata->nnoslater++;
4843  break;
4844  case SCIP_SDPSLATER_NOT:
4845  relaxdata->ndnoslater++;
4846  relaxdata->nnoslater++;
4847  break;
4848  case SCIP_SDPSLATER_HOLDS:
4849  relaxdata->ndslaterholds++;
4850  relaxdata->nnoslater++;
4851  break;
4852  case SCIP_SDPSLATER_INF:
4853  relaxdata->nslaterinfeasible++;
4854  break;
4855  default:
4856  relaxdata->ndslatercheckfailed++;
4857  relaxdata->nnoslater++;
4858  break;
4859  }
4860  break;
4861  case SCIP_SDPSLATER_HOLDS:
4862  relaxdata->npslaterholds++;
4863  switch( dualslater )/*lint --e{788}*/
4864  {
4865  case SCIP_SDPSLATER_NOINFO:
4866  relaxdata->ndslatercheckfailed++;
4867  relaxdata->nslatercheckfailed++;
4868  break;
4869  case SCIP_SDPSLATER_NOT:
4870  relaxdata->ndnoslater++;
4871  relaxdata->nnoslater++;
4872  break;
4873  case SCIP_SDPSLATER_HOLDS:
4874  relaxdata->ndslaterholds++;
4875  relaxdata->nslaterholds++;
4876  break;
4877  case SCIP_SDPSLATER_INF:
4878  relaxdata->nslaterinfeasible++;
4879  break;
4880  default:
4881  relaxdata->ndslatercheckfailed++;
4882  relaxdata->nslatercheckfailed++;
4883  break;
4884  }
4885  break;
4886  default:
4887  relaxdata->npslatercheckfailed++;
4888  relaxdata->ndslatercheckfailed++;
4889  relaxdata->nslatercheckfailed++;
4890  break;
4891  }
4892  slatersetting = SCIP_SDPSLATERSETTING_NOINFO;
4893  SCIP_CALL( SCIPsdpiSlaterSettings(relaxdata->sdpi, &slatersetting) );
4894  switch( slatersetting )/*lint --e{788}*/
4895  {
4897  relaxdata->stablewslater++;
4898  break;
4900  relaxdata->unstablewslater++;
4901  break;
4903  relaxdata->penaltywslater++;
4904  break;
4906  relaxdata->boundedwslater++;
4907  break;
4909  relaxdata->unsolvedwslater++;
4910  break;
4912  relaxdata->stablenoslater++;
4913  break;
4915  relaxdata->unstablenoslater++;
4916  break;
4918  relaxdata->penaltynoslater++;
4919  break;
4921  relaxdata->boundednoslater++;
4922  break;
4924  relaxdata->unsolvednoslater++;
4925  break;
4927  relaxdata->stableinfeasible++;
4928  break;
4930  relaxdata->unstableinfeasible++;
4931  break;
4933  relaxdata->penaltyinfeasible++;
4934  break;
4936  relaxdata->boundedinfeasible++;
4937  break;
4939  relaxdata->unsolvedinfeasible++;
4940  break;
4941  default:
4942  break;
4943  }
4944  }
4945 
4946  if ( SCIPsdpiWasSolved(relaxdata->sdpi) && SCIPsdpiSolvedOrig(relaxdata->sdpi) && SCIPsdpiIsDualFeasible(relaxdata->sdpi) )
4947  {
4948  int nvars;
4949  SCIP_VAR** vars;
4950 
4951  relaxdata->ipZexists = TRUE;
4952 
4953  nvars = SCIPgetNVars(scip);
4954  vars = SCIPgetVars(scip);
4955 
4956  /* allocate memory */
4957  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZnblocknonz, relaxdata->nblocks) );
4958  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZrow, relaxdata->nblocks) );
4959  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZcol, relaxdata->nblocks) );
4960  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZval, relaxdata->nblocks) );
4961 
4962  /* get solution w.r.t. SCIP variables */
4963  SCIP_CALL( SCIPallocBufferArray(scip, &solforscip, nvars) );
4964  slength = nvars;
4965 
4966  SCIP_CALL( SCIPsdpiGetSol(relaxdata->sdpi, NULL, solforscip, &slength) ); /* get the solution from the SDP solver */
4967 
4968  assert( slength == nvars ); /* If this isn't true any longer, the getSol-Call was unsuccessfull, because the given array wasn't long enough,
4969  * but this can't happen, because the array has enough space for all sdp variables. */
4970 
4971  /* create SCIP solution */
4972  SCIP_CALL( SCIPcreateSol(scip, &relaxdata->ipy, NULL) );
4973  SCIP_CALL( SCIPsetSolVals(scip, relaxdata->ipy, nvars, vars, solforscip) );
4974 #ifdef SCIP_PRINT_WARMSTART
4975  SCIPdebugMessage("Computed dual analytic center:\n");
4976  for (i = 0; i < nvars; i++)
4977  {
4978  SCIPdebugMessage("y[%d] = %f\n", i, solforscip[i]);
4979  }
4980 #endif
4981 
4982  SCIPfreeBufferArray(scip, &solforscip);
4983 
4984  /* compute SDP blocks of dual analytic center */
4985  sdpblocks = SCIPconshdlrGetConss(sdpconshdlr);
4986  for (b = 0; b < relaxdata->nblocks - 1; b++)
4987  {
4988  relaxdata->ipZnblocknonz[b] = SCIPconsSdpComputeUbSparseSdpMatrixLength(scip, sdpblocks[b]);
4989  arraylength = relaxdata->ipZnblocknonz[b];
4990 
4991  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZrow[b], relaxdata->ipZnblocknonz[b]) );
4992  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZcol[b], relaxdata->ipZnblocknonz[b]) );
4993  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZval[b], relaxdata->ipZnblocknonz[b]) );
4994 
4995  /* compute Z matrix */
4996  SCIP_CALL( SCIPconsSdpComputeSparseSdpMatrix(scip, sdpblocks[b], relaxdata->ipy, &(relaxdata->ipZnblocknonz[b]), relaxdata->ipZrow[b], relaxdata->ipZcol[b], relaxdata->ipZval[b]) );
4997 
4998  assert( relaxdata->ipZnblocknonz[b] <= arraylength );
4999 
5000  if ( relaxdata->ipZnblocknonz[b] < arraylength )
5001  {
5002  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &relaxdata->ipZrow[b], arraylength, relaxdata->ipZnblocknonz[b]) );
5003  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &relaxdata->ipZcol[b], arraylength, relaxdata->ipZnblocknonz[b]) );
5004  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &relaxdata->ipZval[b], arraylength, relaxdata->ipZnblocknonz[b]) );
5005  }
5006 
5007  /* TODO check if they are already sorted (sorting is needed since they will later be merged into warmstart arrays) */
5008  SCIPsdpVarfixerSortRowCol(relaxdata->ipZrow[b], relaxdata->ipZcol[b], relaxdata->ipZval[b], relaxdata->ipZnblocknonz[b]);
5009  }
5010 
5011  /* compute LP block */
5012  SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
5013  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZrow[b], 2 * nrows + 2 * nvars) );
5014  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZcol[b], 2 * nrows + 2 * nvars) );
5015  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZval[b], 2 * nrows + 2 * nvars) );
5016 
5017  /* for the analytic center all the entries should be strictly positive */
5018  relaxdata->ipZnblocknonz[b] = 2 * nrows + 2 * nvars;
5019 
5020  for (r = 0; r < nrows; r++)
5021  {
5022  /* compute row value for current solution */
5023  rowval = 0.0;
5024  rownnonz = SCIProwGetNNonz(rows[r]);
5025  rowvals = SCIProwGetVals(rows[r]);
5026  rowcols = SCIProwGetCols(rows[r]);
5027  for (i = 0; i < rownnonz; i++)
5028  rowval += SCIPgetSolVal(scip, relaxdata->ipy, SCIPcolGetVar(rowcols[i])) * rowvals[i];
5029 
5030  relaxdata->ipZrow[b][2*r] = 2*r;
5031  relaxdata->ipZcol[b][2*r] = 2*r;
5032  relaxdata->ipZval[b][2*r] = rowval - (SCIProwGetLhs(rows[r]) - SCIProwGetConstant(rows[r]));
5033  relaxdata->ipZrow[b][2*r + 1] = 2*r + 1;
5034  relaxdata->ipZcol[b][2*r + 1] = 2*r + 1;
5035  relaxdata->ipZval[b][2*r + 1] = SCIProwGetRhs(rows[r]) - SCIProwGetConstant(rows[r]) - rowval;
5036  }
5037 
5038  for (v = 0; v < nvars; v++)
5039  {
5040  relaxdata->ipZrow[b][2*nrows + 2*v] = 2*nrows + 2*v;
5041  relaxdata->ipZcol[b][2*nrows + 2*v] = 2*nrows + 2*v;
5042  relaxdata->ipZval[b][2*nrows + 2*v] = SCIPgetSolVal(scip, relaxdata->ipy, vars[v]) - SCIPvarGetLbLocal(vars[v]);
5043  relaxdata->ipZrow[b][2*nrows + 2*v + 1] = 2*nrows + 2*v + 1;
5044  relaxdata->ipZcol[b][2*nrows + 2*v + 1] = 2*nrows + 2*v + 1;
5045  relaxdata->ipZval[b][2*nrows + 2*v + 1] = SCIPvarGetUbLocal(vars[v]) - SCIPgetSolVal(scip, relaxdata->ipy, vars[v]);
5046  }
5047 #ifdef SCIP_PRINT_WARMSTART
5048  for (b = 0; b < relaxdata->nblocks - 1; b++)
5049  {
5050  SCIPdebugMessage("dual matrix, block %d:\n", b);
5051  for (i = 0; i < relaxdata->ipZnblocknonz[b]; i++)
5052  {
5053  SCIPdebugMessage("Z_%d[%d,%d]: %f\n", b, relaxdata->ipZrow[b][i], relaxdata->ipZcol[b][i], relaxdata->ipZval[b][i]);
5054  }
5055  }
5056  SCIPdebugMessage("dual matrix, LP constraints:\n");
5057  for (r = 0; r < nrows; r++)
5058  {
5059  SCIPdebugMessage("Z_%d[%d,%d]: %f\n", relaxdata->nblocks, relaxdata->ipZrow[b][2*r], relaxdata->ipZcol[b][2*r], relaxdata->ipZval[b][2*r]);
5060  SCIPdebugMessage("Z_%d[%d,%d]: %f\n", relaxdata->nblocks, relaxdata->ipZrow[b][2*r+1], relaxdata->ipZcol[b][2*r+1], relaxdata->ipZval[b][2*r+1]);
5061  }
5062  for (v = 0; v < nvars; v++)
5063  {
5064  SCIPdebugMessage("Z_%d[%d,%d]: %f\n", relaxdata->nblocks,
5065  relaxdata->ipZrow[b][2*nrows + 2*v], relaxdata->ipZcol[b][2*nrows + 2*v], relaxdata->ipZval[b][2*nrows + 2*v]);
5066  SCIPdebugMessage("Z_%d[%d,%d]: %f\n", relaxdata->nblocks,
5067  relaxdata->ipZrow[b][2*nrows + 2*v + 1], relaxdata->ipZcol[b][2*nrows + 2*v + 1], relaxdata->ipZval[b][2*nrows + 2*v + 1]);
5068  }
5069 #endif
5070  }
5071  else
5072  {
5073  /* use a scaled identity matrix (and y=0) if the computation of the dual analytic center failed */
5074  relaxdata->ipZexists = TRUE;
5075 
5076  /* y is set to the zero vector */
5077  SCIP_CALL( SCIPcreateSol(scip, &relaxdata->ipy, NULL) );
5078 
5079  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZnblocknonz, relaxdata->nblocks) );
5080  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZrow, relaxdata->nblocks) );
5081  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZcol, relaxdata->nblocks) );
5082  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZval, relaxdata->nblocks) );
5083 
5084  sdpblocks = SCIPconshdlrGetConss(sdpconshdlr);
5085 
5086  for (b = 0; b < relaxdata->nblocks; b++)
5087  {
5088  if ( b < relaxdata->nblocks - 1 )
5089  {
5090  /* SDP block */
5091  relaxdata->ipZnblocknonz[b] = SCIPconsSdpGetBlocksize(scip, sdpblocks[b]);
5092  }
5093  else
5094  {
5095  /* LP block */
5096  relaxdata->ipZnblocknonz[b] = SCIPgetNLPRows(scip) + 2 * SCIPgetNVars(scip);
5097  }
5098  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZrow[b], relaxdata->ipZnblocknonz[b]) );
5099  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZcol[b], relaxdata->ipZnblocknonz[b]) );
5100  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZval[b], relaxdata->ipZnblocknonz[b]) );
5101 
5102  for (i = 0; i < relaxdata->ipXnblocknonz[b]; i++)
5103  {
5104  relaxdata->ipZrow[b][i] = i;
5105  relaxdata->ipZcol[b][i] = i;
5106  relaxdata->ipZval[b][i] = relaxdata->lambdastar;
5107  }
5108  }
5109 
5110  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL, "Failed to compute analytic center of dual feasible set, using scaled identity instead.\n");
5111  }
5112  }
5113  }
5114  return SCIP_OKAY;
5115 }
5116 
5126  SCIP_RELAX* relax,
5127  SCIP_Real* lbvars,
5128  SCIP_Real* ubvars,
5129  int* arraylength
5131  )
5132 {
5133  SCIP_RELAXDATA* relaxdata;
5134 
5135  assert( relax != NULL );
5136  assert( lbvars != NULL );
5137  assert( ubvars != NULL );
5138  assert( arraylength != NULL );
5139  assert( *arraylength >= 0 );
5140 
5141  relaxdata = SCIPrelaxGetData(relax);
5142  assert( relaxdata != NULL );
5143 
5144  SCIP_CALL( SCIPsdpiGetPrimalBoundVars(relaxdata->sdpi, lbvars, ubvars, arraylength) );
5145 
5146  return SCIP_OKAY;
5147 }
5148 
5151  SCIP_RELAX* relax,
5152  SCIP_Bool* success,
5153  SCIP_Real* objval
5154  )
5155 {
5156  SCIP_RELAXDATA* relaxdata;
5157 
5158  assert( relax != NULL );
5159  assert( success != NULL );
5160  assert( objval != NULL );
5161 
5162  relaxdata = SCIPrelaxGetData(relax);
5163  assert( relaxdata != NULL );
5164 
5165  *success = relaxdata->origsolved;
5166  *objval = relaxdata->objval;
5167 
5168  return SCIP_OKAY;
5169 }
5170 
5173  SCIP* scip,
5174  SCIP_RELAX* relax,
5175  SCIP_Bool* success,
5176  SCIP_Real* solarray,
5177  int* sollength
5178  )
5179 {
5180  SCIP_RELAXDATA* relaxdata;
5181 
5182  assert( relax != NULL );
5183  assert( success != NULL );
5184  assert( solarray != NULL );
5185 
5186  relaxdata = SCIPrelaxGetData(relax);
5187  assert( relaxdata != NULL );
5188 
5189  *success = relaxdata->origsolved;
5190 
5191  if ( *sollength >= SCIPgetNVars(scip) )
5192  {
5193  SCIP_CALL( SCIPsdpiGetSol(relaxdata->sdpi, NULL, solarray, sollength) );
5194  }
5195  else
5196  {
5197  SCIPdebugMessage("Called SCIPrelaxSdpGetRelaxSol with an array that wasn't big enough, needed length %d, given %d!\n", SCIPgetNVars(scip), *sollength);
5198  *sollength = SCIPgetNVars(scip);
5199  }
5200 
5201  return SCIP_OKAY;
5202 }
5203 
5206  SCIP_RELAX* relax
5207  )
5208 {
5209  assert( relax != NULL );
5210  assert( SCIPrelaxGetData(relax) != NULL );
5211 
5212  return SCIPrelaxGetData(relax)->lastsdpnode;
5213 }
5214 
5217  SCIP_RELAX* relax
5218  )
5219 {
5220  SCIP_RELAXDATA* relaxdata;
5221 
5222  assert( relax != NULL );
5223 
5224  relaxdata = SCIPrelaxGetData(relax);
5225 
5226  assert( relaxdata != NULL );
5227  assert( relaxdata->sdpi != NULL );
5228 
5229  return relaxdata->origsolved && SCIPsdpiSolvedOrig(relaxdata->sdpi);
5230 }
5231 
5234  SCIP_RELAX* relax
5235  )
5236 {
5237  SCIP_RELAXDATA* relaxdata;
5238 
5239  assert( relax != NULL );
5240 
5241  relaxdata = SCIPrelaxGetData(relax);
5242 
5243  assert( relaxdata != NULL );
5244  assert( relaxdata->sdpi != NULL );
5245 
5246  return relaxdata->probingsolved;
5247 }
5248 
5251  SCIP_RELAX* relax
5252  )
5253 {
5254  assert( relax != NULL );
5255  assert( SCIPrelaxGetData(relax) != NULL );
5256 
5257  return ( SCIPrelaxGetData(relax)->feasible );
5258 }
5259 
5262  SCIP_RELAX* relax
5263  )
5264 {
5265  assert( relax != NULL );
5266  assert( SCIPrelaxGetData(relax) != NULL );
5267 
5268  return SCIPrelaxGetData(relax)->sdpiterations;
5269 }
5270 
5273  SCIP_RELAX* relax
5274  )
5275 {
5276  assert( relax != NULL );
5277  assert( SCIPrelaxGetData(relax) != NULL );
5278 
5279  return ( SCIPrelaxGetData(relax)->sdpcalls );
5280 }
5281 
5284  SCIP_RELAX* relax
5285  )
5286 {
5287  assert( relax != NULL );
5288  assert( SCIPrelaxGetData(relax) != NULL );
5289 
5290  return ( SCIPrelaxGetData(relax)->sdpinterfacecalls );
5291 }
5292 
5295  SCIP_RELAX* relax
5296  )
5297 {
5298  assert( relax != NULL );
5299  assert( SCIPrelaxGetData(relax) != NULL );
5300 
5301  return ( SCIPrelaxGetData(relax)->solvedfast );
5302 }
5303 
5306  SCIP_RELAX* relax
5307  )
5308 {
5309  assert( relax != NULL );
5310  assert( SCIPrelaxGetData(relax) != NULL );
5311 
5312  return ( SCIPrelaxGetData(relax)->solvedmedium );
5313 }
5314 
5317  SCIP_RELAX* relax
5318  )
5319 {
5320  assert( relax != NULL );
5321  assert( SCIPrelaxGetData(relax) != NULL );
5322 
5323  return ( SCIPrelaxGetData(relax)->solvedstable );
5324 }
5325 
5328  SCIP_RELAX* relax
5329  )
5330 {
5331  assert( relax != NULL );
5332  assert( SCIPrelaxGetData(relax) != NULL );
5333 
5334  return ( SCIPrelaxGetData(relax)->solvedpenalty );
5335 }
5336 
5339  SCIP_RELAX* relax
5340  )
5341 {
5342  assert( relax != NULL );
5343  assert( SCIPrelaxGetData(relax) != NULL );
5344 
5345  return ( SCIPrelaxGetData(relax)->unsolved );
5346 }
5347 
5350  SCIP_RELAX* relax
5351  )
5352 {
5353  assert( relax != NULL );
5354  assert( SCIPrelaxGetData(relax) != NULL );
5355 
5356  return ( SCIPrelaxGetData(relax)->ndslaterholds );
5357 }
5358 
5361  SCIP_RELAX* relax
5362  )
5363 {
5364  assert( relax != NULL );
5365  assert( SCIPrelaxGetData(relax) != NULL );
5366 
5367  return ( SCIPrelaxGetData(relax)->ndnoslater );
5368 }
5369 
5372  SCIP_RELAX* relax
5373  )
5374 {
5375  assert( relax != NULL );
5376  assert( SCIPrelaxGetData(relax) != NULL );
5377 
5378  return ( SCIPrelaxGetData(relax)->nslaterinfeasible );
5379 }
5380 
5383  SCIP_RELAX* relax
5384  )
5385 {
5386  assert( relax != NULL );
5387  assert( SCIPrelaxGetData(relax) != NULL );
5388 
5389  return ( SCIPrelaxGetData(relax)->ndslatercheckfailed );
5390 }
5391 
5394  SCIP_RELAX* relax
5395  )
5396 {
5397  assert( relax != NULL );
5398  assert( SCIPrelaxGetData(relax) != NULL );
5399 
5400  return ( SCIPrelaxGetData(relax)->npslaterholds );
5401 }
5402 
5405  SCIP_RELAX* relax
5406  )
5407 {
5408  assert( relax != NULL );
5409  assert( SCIPrelaxGetData(relax) != NULL );
5410 
5411  return ( SCIPrelaxGetData(relax)->npnoslater );
5412 }
5413 
5416  SCIP_RELAX* relax
5417  )
5418 {
5419  assert( relax != NULL );
5420  assert( SCIPrelaxGetData(relax) != NULL );
5421 
5422  return ( SCIPrelaxGetData(relax)->npslatercheckfailed );
5423 }
5424 
5427  SCIP_RELAX* relax
5428  )
5429 {
5430  assert( relax != NULL );
5431  assert( SCIPrelaxGetData(relax) != NULL );
5432 
5433  return ( SCIPrelaxGetData(relax)->nslaterholds );
5434 }
5435 
5438  SCIP_RELAX* relax
5439  )
5440 {
5441  assert( relax != NULL );
5442  assert( SCIPrelaxGetData(relax) != NULL );
5443 
5444  return ( SCIPrelaxGetData(relax)->stablewslater );
5445 }
5446 
5449  SCIP_RELAX* relax
5450  )
5451 {
5452  assert( relax != NULL );
5453  assert( SCIPrelaxGetData(relax) != NULL );
5454 
5455  return ( SCIPrelaxGetData(relax)->unstablewslater );
5456 }
5457 
5460  SCIP_RELAX* relax
5461  )
5462 {
5463  assert( relax != NULL );
5464  assert( SCIPrelaxGetData(relax) != NULL );
5465 
5466  return ( SCIPrelaxGetData(relax)->penaltywslater );
5467 }
5468 
5471  SCIP_RELAX* relax
5472  )
5473 {
5474  assert( relax != NULL );
5475  assert( SCIPrelaxGetData(relax) != NULL );
5476 
5477  return ( SCIPrelaxGetData(relax)->boundedwslater );
5478 }
5479 
5482  SCIP_RELAX* relax
5483  )
5484 {
5485  assert( relax != NULL );
5486  assert( SCIPrelaxGetData(relax) != NULL );
5487 
5488  return ( SCIPrelaxGetData(relax)->unsolvedwslater );
5489 }
5490 
5493  SCIP_RELAX* relax
5494  )
5495 {
5496  assert( relax != NULL );
5497  assert( SCIPrelaxGetData(relax) != NULL );
5498 
5499  return ( SCIPrelaxGetData(relax)->nnoslater );
5500 }
5501 
5504  SCIP_RELAX* relax
5505  )
5506 {
5507  assert( relax != NULL );
5508  assert( SCIPrelaxGetData(relax) != NULL );
5509 
5510  return ( SCIPrelaxGetData(relax)->stablenoslater );
5511 }
5512 
5515  SCIP_RELAX* relax
5516  )
5517 {
5518  assert( relax != NULL );
5519  assert( SCIPrelaxGetData(relax) != NULL );
5520 
5521  return ( SCIPrelaxGetData(relax)->unstablenoslater );
5522 }
5523 
5526  SCIP_RELAX* relax
5527  )
5528 {
5529  assert( relax != NULL );
5530  assert( SCIPrelaxGetData(relax) != NULL );
5531 
5532  return ( SCIPrelaxGetData(relax)->penaltynoslater );
5533 }
5534 
5537  SCIP_RELAX* relax
5538  )
5539 {
5540  assert( relax != NULL );
5541  assert( SCIPrelaxGetData(relax) != NULL );
5542 
5543  return ( SCIPrelaxGetData(relax)->boundednoslater );
5544 }
5545 
5548  SCIP_RELAX* relax
5549  )
5550 {
5551  assert( relax != NULL );
5552  assert( SCIPrelaxGetData(relax) != NULL );
5553 
5554  return ( SCIPrelaxGetData(relax)->unsolvednoslater );
5555 }
5556 
5559  SCIP_RELAX* relax
5560  )
5561 {
5562  assert( relax != NULL );
5563  assert( SCIPrelaxGetData(relax) != NULL );
5564 
5565  return ( SCIPrelaxGetData(relax)->stableinfeasible );
5566 }
5567 
5570  SCIP_RELAX* relax
5571  )
5572 {
5573  assert( relax != NULL );
5574  assert( SCIPrelaxGetData(relax) != NULL );
5575 
5576  return ( SCIPrelaxGetData(relax)->unstableinfeasible );
5577 }
5578 
5581  SCIP_RELAX* relax
5582  )
5583 {
5584  assert( relax != NULL );
5585  assert( SCIPrelaxGetData(relax) != NULL );
5586 
5587  return ( SCIPrelaxGetData(relax)->penaltyinfeasible );
5588 }
5589 
5592  SCIP_RELAX* relax
5593  )
5594 {
5595  assert( relax != NULL );
5596  assert( SCIPrelaxGetData(relax) != NULL );
5597 
5598  return ( SCIPrelaxGetData(relax)->boundedinfeasible );
5599 }
5600 
5603  SCIP_RELAX* relax
5604  )
5605 {
5606  assert( relax != NULL );
5607  assert( SCIPrelaxGetData(relax) != NULL );
5608 
5609  return ( SCIPrelaxGetData(relax)->unsolvedinfeasible );
5610 }
SCIP_Real SCIPconsSdpGetMaxConstEntry(SCIP *scip, SCIP_CONS *cons)
Definition: cons_sdp.c:2855
#define RELAX_DESC
Definition: relax_sdp.c:65
SCIP_RETCODE SCIPsdpiFree(SCIP_SDPI **sdpi)
Definition: sdpi.c:1512
#define WARMSTART_PROJ_FACTOR_PRIMAL
Definition: relax_sdp.c:97
SCIP_Bool SCIPsdpiIsDualUnbounded(SCIP_SDPI *sdpi)
Definition: sdpi.c:2981
SCIP_RETCODE SCIPsdpiDelLPRows(SCIP_SDPI *sdpi, int firstrow, int lastrow)
Definition: sdpi.c:1982
int SCIPrelaxSdpGetNSlaterHoldsStable(SCIP_RELAX *relax)
Definition: relax_sdp.c:5448
#define WARMSTART_MINVAL
Definition: relax_sdp.c:93
int SCIPrelaxSdpGetNSlaterInfeasibleFast(SCIP_RELAX *relax)
Definition: relax_sdp.c:5558
SCIP_RETCODE SCIPsdpiGetSdpCalls(SCIP_SDPI *sdpi, int *calls)
Definition: sdpi.c:3582
static SCIP_RETCODE calcRelax(SCIP *scip, SCIP_RELAXDATA *relaxdata, SCIP_RESULT *result, SCIP_Real *lowerbound)
Definition: relax_sdp.c:756
SCIP_Bool SCIPsdpiDoesWarmstartNeedPrimal(void)
Definition: sdpi.c:1426
static SCIP_DECL_RELAXCOPY(relaxCopySdp)
Definition: relax_sdp.c:4043
SCIP_RETCODE SCIPsdpVarmapperAddVars(SCIP *scip, SdpVarmapper *varmapper, int nvars, SCIP_VAR **vars)
Definition: SdpVarmapper.c:108
int SCIPrelaxSdpGetNSlaterFailsBounded(SCIP_RELAX *relax)
Definition: relax_sdp.c:5536
#define TIMEOFDAY_CALL(x)
Definition: relax_sdp.c:102
int SCIPrelaxSdpGetNprimalSlaterHolds(SCIP_RELAX *relax)
Definition: relax_sdp.c:5393
SCIP_Real SCIPconsSavesdpsolGetMaxPrimalEntry(SCIP *scip, SCIP_CONS *cons)
static SCIP_Bool allVarsFixed(SCIP *scip)
Definition: relax_sdp.c:3439
#define DEFAULT_SLATERCHECK
Definition: relax_sdp.c:82
#define WARMSTART_PREOPT_MIN_Z_LPVAL
Definition: relax_sdp.c:99
int SCIPrelaxSdpGetNSdpPenalty(SCIP_RELAX *relax)
Definition: relax_sdp.c:5327
void SCIPsdpVarfixerSortRowCol(int *row, int *col, SCIP_Real *val, int length)
Definition: SdpVarfixer.c:50
SCIP_RETCODE SCIPsdpiGetPrimalMatrix(SCIP_SDPI *sdpi, int nblocks, int *startXnblocknonz, int **startXrow, int **startXcol, SCIP_Real **startXval)
Definition: sdpi.c:3529
enum SCIP_SDPSolverSetting SCIP_SDPSOLVERSETTING
Definition: type_sdpi.h:79
static SCIP_DECL_RELAXEXIT(relaxExitSdp)
Definition: relax_sdp.c:4056
SCIP_RETCODE SCIPconsSavesdpsolGetPrimalMatrixNonzeros(SCIP *scip, SCIP_CONS *cons, int nblocks, int *startXnblocknonz)
EXTERN SCIP_RETCODE SCIPlapackComputeEigenvectorDecomposition(BMS_BUFMEM *bufmem, int n, SCIP_Real *A, SCIP_Real *eigenvalues, SCIP_Real *eigenvectors)
Definition: lapack_dsdp.c:219
int SCIPrelaxSdpGetNdualSlaterHolds(SCIP_RELAX *relax)
Definition: relax_sdp.c:5349
const char * SCIPsdpiGetSolverName(void)
Definition: sdpi.c:1373
SCIP_RETCODE SCIPsdpiGetSol(SCIP_SDPI *sdpi, SCIP_Real *objval, SCIP_Real *dualsol, int *dualsollength)
Definition: sdpi.c:3309
SDP-relaxator.
#define RELAX_PRIORITY
Definition: relax_sdp.c:66
int SCIPrelaxSdpGetNSdpUnsolved(SCIP_RELAX *relax)
Definition: relax_sdp.c:5338
#define DEFAULT_PENALTYPARAM
Definition: relax_sdp.c:70
SCIP_RETCODE createConsSavesdpsol(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_Longint node, SCIP_SOL *sol, SCIP_Real maxprimalentry, int nblocks, int *startXnblocknonz, int **startXrow, int **startXcol, SCIP_Real **startXval)
SCIP_RETCODE SCIPsdpiSolve(SCIP_SDPI *sdpi, SCIP_Real *starty, int *startZnblocknonz, int **startZrow, int **startZcol, SCIP_Real **startZval, int *startXnblocknonz, int **startXrow, int **startXcol, SCIP_Real **startXval, SCIP_SDPSOLVERSETTING startsettings, SCIP_Bool enforceslatercheck, SCIP_Real timelimit)
Definition: sdpi.c:2451
SCIP_Bool SCIPsdpiFeasibilityKnown(SCIP_SDPI *sdpi)
Definition: sdpi.c:2869
SCIP_RETCODE SCIPsdpiLoadSDP(SCIP_SDPI *sdpi, 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 nlpcons, SCIP_Real *lplhs, SCIP_Real *lprhs, int lpnnonz, int *lprow, int *lpcol, SCIP_Real *lpval)
Definition: sdpi.c:1697
SCIP_RETCODE SCIPsdpiComputeLambdastar(SCIP_SDPI *sdpi, SCIP_Real maxguess)
Definition: sdpi.c:4161
SCIP_RETCODE SCIPsdpiGetPrimalNonzeros(SCIP_SDPI *sdpi, int nblocks, int *startXnblocknonz)
Definition: sdpi.c:3501
SCIP_RETCODE createConsSavedsdpsettings(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_SDPSOLVERSETTING settings)
SCIP_SOL * SCIPconsSavesdpsolGetDualVector(SCIP *scip, SCIP_CONS *cons)
#define DEFAULT_TIGHTENVB
Definition: relax_sdp.c:85
static SCIP_DECL_RELAXEXEC(relaxExecSdp)
Definition: relax_sdp.c:3463
SCIP_VAR * SCIPsdpVarmapperGetSCIPvar(SdpVarmapper *varmapper, int ind)
Definition: SdpVarmapper.c:237
SCIP_RETCODE SCIPsdpiGetIterations(SCIP_SDPI *sdpi, int *iterations)
Definition: sdpi.c:3568
#define DEFAULT_SETTINGSRESETFREQ
Definition: relax_sdp.c:89
SCIP_RETCODE SCIPsdpiSettingsUsed(SCIP_SDPI *sdpi, SCIP_SDPSOLVERSETTING *usedsetting)
Definition: sdpi.c:3596
SCIP_RETCODE SCIPsdpiSlaterSettings(SCIP_SDPI *sdpi, SCIP_SDPSLATERSETTING *slatersetting)
Definition: sdpi.c:3633
int SCIPrelaxSdpGetNdualSlaterFails(SCIP_RELAX *relax)
Definition: relax_sdp.c:5360
SCIP_Bool SCIPsdpiIsAcceptable(SCIP_SDPI *sdpi)
Definition: sdpi.c:3199
int SCIPsdpVarmapperGetNVars(SdpVarmapper *varmapper)
Definition: SdpVarmapper.c:203
static SCIP_DECL_RELAXINITSOL(relaxInitSolSdp)
Definition: relax_sdp.c:3623
int SCIPrelaxSdpGetNSdpStable(SCIP_RELAX *relax)
Definition: relax_sdp.c:5316
SCIP_RETCODE SCIPconsSdpComputeSparseSdpMatrix(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, int *length, int *row, int *col, SCIP_Real *val)
Definition: cons_sdp.c:2934
int SCIPrelaxSdpGetNSdpMedium(SCIP_RELAX *relax)
Definition: relax_sdp.c:5305
SCIP_RETCODE SCIPsdpVarmapperCreate(SCIP *scip, SdpVarmapper **varmapper, int size)
Definition: SdpVarmapper.c:53
#define DEFAULT_WARMSTARTIPFACTOR
Definition: relax_sdp.c:73
SCIP_Bool SCIPsdpiIsTimelimExc(SCIP_SDPI *sdpi)
Definition: sdpi.c:3115
SCIP_RETCODE SCIPrelaxSdpRelaxVal(SCIP_RELAX *relax, SCIP_Bool *success, SCIP_Real *objval)
Definition: relax_sdp.c:5150
SCIP_Bool SCIPsdpiIsDualInfeasible(SCIP_SDPI *sdpi)
Definition: sdpi.c:3004
General interface methods for SDP-preprocessing (mainly fixing variables and removing empty rows/cols...
int SCIPrelaxSdpGetNSlaterFailsFast(SCIP_RELAX *relax)
Definition: relax_sdp.c:5503
static SCIP_DECL_RELAXFREE(relaxFreeSdp)
Definition: relax_sdp.c:4231
struct Sdpvarmapper SdpVarmapper
Definition: SdpVarmapper.h:48
int SCIPrelaxSdpGetNSlaterFailsStable(SCIP_RELAX *relax)
Definition: relax_sdp.c:5514
enum SCIP_SDPSlaterSetting SCIP_SDPSLATERSETTING
Definition: type_sdpi.h:101
#define DEFAULT_DISPLAYSTAT
Definition: relax_sdp.c:88
int SCIPsdpVarmapperGetSdpIndex(SdpVarmapper *varmapper, SCIP_VAR *var)
Definition: SdpVarmapper.c:225
int SCIPrelaxSdpGetNSdpInterfaceCalls(SCIP_RELAX *relax)
Definition: relax_sdp.c:5283
int SCIPrelaxSdpGetNSlaterHolds(SCIP_RELAX *relax)
Definition: relax_sdp.c:5426
SCIP_RETCODE SCIPsdpiChgBounds(SCIP_SDPI *sdpi, int nvars, const int *ind, const SCIP_Real *lb, const SCIP_Real *ub)
Definition: sdpi.c:2179
int SCIPrelaxSdpGetNSdpCalls(SCIP_RELAX *relax)
Definition: relax_sdp.c:5272
Constraint handler for SDP-constraints.
SCIP_RETCODE SCIPsdpiGetLowerObjbound(SCIP_SDPI *sdpi, SCIP_Real *objlb)
Definition: sdpi.c:3260
SCIP_Bool SCIPsdpiIsObjlimExc(SCIP_SDPI *sdpi)
Definition: sdpi.c:3071
maps SCIP variables to SDP indices (the SCIP variables are given SDP indices in the order in which th...
#define DEFAULT_MAXPENALTYPARAM
Definition: relax_sdp.c:72
SCIP_Real SCIPconsSdpGetMaxSdpCoef(SCIP *scip, SCIP_CONS *cons)
Definition: cons_sdp.c:2871
SCIP_Real SCIPsdpiGetDefaultSdpiSolverFeastol(void)
Definition: sdpi.c:1402
SCIP_RETCODE SCIPconsSdpGetData(SCIP *scip, SCIP_CONS *cons, int *nvars, int *nnonz, int *blocksize, int *arraylength, int *nvarnonz, int **col, int **row, SCIP_Real **val, SCIP_VAR **vars, int *constnnonz, int *constcol, int *constrow, SCIP_Real *constval)
Definition: cons_sdp.c:2513
int SCIPconsSdpCompLowerTriangPos(int i, int j)
Definition: cons_sdp.c:2496
int SCIPrelaxSdpGetNSlaterHoldsUnsolved(SCIP_RELAX *relax)
Definition: relax_sdp.c:5481
#define DEFAULT_SDPINFO
Definition: relax_sdp.c:86
#define WARMSTART_PROJ_FACTOR_LHS
Definition: relax_sdp.c:96
SCIP_RETCODE SCIPsdpiAddLPRows(SCIP_SDPI *sdpi, int nrows, const SCIP_Real *lhs, const SCIP_Real *rhs, int nnonz, const int *row, const int *col, const SCIP_Real *val)
Definition: sdpi.c:1917
#define WARMSTART_PROJ_FACTOR
Definition: relax_sdp.c:95
int SCIPrelaxSdpGetNSlaterInfeasibleStable(SCIP_RELAX *relax)
Definition: relax_sdp.c:5569
int SCIPrelaxSdpGetNdualSlaterUnknown(SCIP_RELAX *relax)
Definition: relax_sdp.c:5382
#define DEFAULT_OBJLIMIT
Definition: relax_sdp.c:83
const char * SCIPsdpiGetSolverDesc(void)
Definition: sdpi.c:1381
SCIP_RETCODE SCIPsdpiComputePenaltyparam(SCIP_SDPI *sdpi, SCIP_Real maxcoeff, SCIP_Real *penaltyparam)
Definition: sdpi.c:4170
SCIP_RETCODE SCIPsdpiSetIntpar(SCIP_SDPI *sdpi, SCIP_SDPPARAM type, int ival)
Definition: sdpi.c:4129
SCIP_SDPSOLVERSETTING SCIPconsSavedsdpsettingsGetSettings(SCIP *scip, SCIP_CONS *cons)
#define DEFAULT_SETTINGSRESETOFS
Definition: relax_sdp.c:90
SCIP_Bool SCIPrelaxSdpSolvedProbing(SCIP_RELAX *relax)
Definition: relax_sdp.c:5233
SCIP_Real SCIPsdpiInfinity(SCIP_SDPI *sdpi)
Definition: sdpi.c:3982
#define RELAX_FREQ
Definition: relax_sdp.c:67
SCIP_RETCODE SCIPconsSavesdpsolGetPrimalMatrix(SCIP *scip, SCIP_CONS *cons, int nblocks, int *startXnblocknonz, int **startXrow, int **startXcol, SCIP_Real **startXval)
long int SCIPrelaxSdpGetSdpNode(SCIP_RELAX *relax)
Definition: relax_sdp.c:5205
SCIP_RETCODE SCIPsdpiCreate(SCIP_SDPI **sdpi, SCIP_MESSAGEHDLR *messagehdlr, BMS_BLKMEM *blkmem, BMS_BUFMEM *bufmem)
Definition: sdpi.c:1444
#define DEFAULT_WARMSTARTPROJECT
Definition: relax_sdp.c:76
int SCIPrelaxSdpGetNSlaterFailsPenalty(SCIP_RELAX *relax)
Definition: relax_sdp.c:5525
int SCIPrelaxSdpGetNSdpFast(SCIP_RELAX *relax)
Definition: relax_sdp.c:5294
SCIP_Bool SCIPrelaxSdpSolvedOrig(SCIP_RELAX *relax)
Definition: relax_sdp.c:5216
#define DEFAULT_WARMSTARTIPTYPE
Definition: relax_sdp.c:75
adds the main functionality to fix/unfix/(multi-)aggregate variables by merging two three-tuple-array...
int SCIPrelaxSdpGetNSlaterHoldsFast(SCIP_RELAX *relax)
Definition: relax_sdp.c:5437
int SCIPrelaxSdpGetNSlaterInfeasiblePenalty(SCIP_RELAX *relax)
Definition: relax_sdp.c:5580
#define WARMSTART_PROJ_MINRHSOBJ
Definition: relax_sdp.c:94
int SCIPsdpiGetDefaultSdpiSolverNpenaltyIncreases(void)
Definition: sdpi.c:1418
#define DEFAULT_WARMSTARTPRIMALTYPE
Definition: relax_sdp.c:74
int SCIPconsSdpComputeUbSparseSdpMatrixLength(SCIP *scip, SCIP_CONS *cons)
Definition: cons_sdp.c:2905
SCIP_Bool SCIPsdpiWasSolved(SCIP_SDPI *sdpi)
Definition: sdpi.c:2847
int SCIPrelaxSdpGetNIterations(SCIP_RELAX *relax)
Definition: relax_sdp.c:5261
int SCIPrelaxSdpGetNSlaterFails(SCIP_RELAX *relax)
Definition: relax_sdp.c:5492
SCIP_RETCODE SCIPsdpiComputeMaxPenaltyparam(SCIP_SDPI *sdpi, SCIP_Real penaltyparam, SCIP_Real *maxpenaltyparam)
Definition: sdpi.c:4184
SCIP_RETCODE SCIPsdpiClear(SCIP_SDPI *sdpi)
Definition: sdpi.c:2134
SCIP_RETCODE SCIPsdpiChgObj(SCIP_SDPI *sdpi, int nvars, const int *ind, const SCIP_Real *obj)
Definition: sdpi.c:2150
SCIP_RETCODE SCIPrelaxSdpGetRelaxSol(SCIP *scip, SCIP_RELAX *relax, SCIP_Bool *success, SCIP_Real *solarray, int *sollength)
Definition: relax_sdp.c:5172
SCIP_RETCODE SCIPsdpiGetPreoptimalSol(SCIP_SDPI *sdpi, SCIP_Bool *success, SCIP_Real *dualsol, int *dualsollength, int nblocks, int *startXnblocknonz, int **startXrow, int **startXcol, SCIP_Real **startXval)
Definition: sdpi.c:3398
int SCIPconsSdpGetBlocksize(SCIP *scip, SCIP_CONS *cons)
Definition: cons_sdp.c:2634
int SCIPrelaxSdpGetNSlaterHoldsBounded(SCIP_RELAX *relax)
Definition: relax_sdp.c:5470
int SCIPrelaxSdpGetNprimalSlaterFails(SCIP_RELAX *relax)
Definition: relax_sdp.c:5404
int SCIPrelaxSdpGetNSlaterInfeasibleBounded(SCIP_RELAX *relax)
Definition: relax_sdp.c:5591
SCIP_RETCODE SCIPsdpVarmapperFree(SCIP *scip, SdpVarmapper **varmapper)
Definition: SdpVarmapper.c:80
SCIP_RETCODE SCIPrelaxSdpGetPrimalBoundVars(SCIP_RELAX *relax, SCIP_Real *lbvars, SCIP_Real *ubvars, int *arraylength)
Definition: relax_sdp.c:5125
#define DEFAULT_LAMBDASTAR
Definition: relax_sdp.c:71
static SCIP_RETCODE scaleTransposedMatrix(int blocksize, SCIP_Real *matrix, SCIP_Real *scale)
Definition: relax_sdp.c:258
EXTERN SCIP_RETCODE SCIPlapackMatrixMatrixMult(int nrowsA, int ncolsA, SCIP_Real *matrixA, SCIP_Bool transposeA, int nrowsB, int ncolsB, SCIP_Real *matrixB, SCIP_Bool transposeB, SCIP_Real *result)
Definition: lapack_dsdp.c:359
SCIP_RETCODE SCIPsdpVarfixerMergeArrays(BMS_BLKMEM *blkmem, SCIP_Real epsilon, int *originrow, int *origincol, SCIP_Real *originval, int originlength, SCIP_Bool originsorted, SCIP_Real scalar, int *targetrow, int *targetcol, SCIP_Real *targetval, int *targetlength, int targetmemory)
Definition: SdpVarfixer.c:88
#define DEFAULT_WARMSTARTROUNDONLYINF
Definition: relax_sdp.c:81
SCIP_Bool SCIPsdpiIsDualFeasible(SCIP_SDPI *sdpi)
Definition: sdpi.c:3027
struct SCIP_SDPi SCIP_SDPI
Definition: type_sdpi.h:113
SCIP_Bool SCIPsdpiIsPrimalFeasible(SCIP_SDPI *sdpi)
Definition: sdpi.c:2958
SCIP_Bool SCIPrelaxSdpIsFeasible(SCIP_RELAX *relax)
Definition: relax_sdp.c:5250
SCIP_RETCODE SCIPsdpiSetRealpar(SCIP_SDPI *sdpi, SCIP_SDPPARAM type, SCIP_Real dval)
Definition: sdpi.c:4050
SCIP_Longint SCIPconsSavesdpsolGetNodeIndex(SCIP *scip, SCIP_CONS *cons)
int SCIPrelaxSdpGetNSlaterFailsUnsolved(SCIP_RELAX *relax)
Definition: relax_sdp.c:5547
#define DEFAULT_WARMSTARTPROJMINEV
Definition: relax_sdp.c:77
enum SCIP_SDPSlater SCIP_SDPSLATER
Definition: type_sdpi.h:111
SCIP_Real SCIPsdpiGetMaxPrimalEntry(SCIP_SDPI *sdpi)
Definition: sdpi.c:3558
#define RELAX_NAME
Definition: relax_sdp.c:64
SCIP_RETCODE SCIPconsSdpGetNNonz(SCIP *scip, SCIP_CONS *cons, int *nnonz, int *constnnonz)
Definition: cons_sdp.c:2609
SCIP_RETCODE SCIPsdpiGetRealpar(SCIP_SDPI *sdpi, SCIP_SDPPARAM type, SCIP_Real *dval)
Definition: sdpi.c:4003
static SCIP_RETCODE putSdpDataInInterface(SCIP *scip, SCIP_SDPI *sdpi, SdpVarmapper *varmapper, SCIP_Bool primalobj, SCIP_Bool boundprimal)
Definition: relax_sdp.c:284
int SCIPrelaxSdpGetNdualSlaterInfeasible(SCIP_RELAX *relax)
Definition: relax_sdp.c:5371
SCIP_Real SCIPsdpiGetDefaultSdpiSolverGaptol(void)
Definition: sdpi.c:1410
SCIP_RETCODE SCIPsdpiGetPreoptimalPrimalNonzeros(SCIP_SDPI *sdpi, int nblocks, int *startXnblocknonz)
Definition: sdpi.c:3360
SCIP_RETCODE SCIPrelaxSdpComputeAnalyticCenters(SCIP *scip, SCIP_RELAX *relax)
Definition: relax_sdp.c:4410
static SCIP_RETCODE expandSparseMatrix(int nnonz, int blocksize, int *row, int *col, SCIP_Real *val, SCIP_Real *fullmat)
Definition: relax_sdp.c:221
#define DEFAULT_WARMSTART
Definition: relax_sdp.c:87
int SCIPrelaxSdpGetNSlaterHoldsPenalty(SCIP_RELAX *relax)
Definition: relax_sdp.c:5459
#define DEFAULT_RESOLVE
Definition: relax_sdp.c:84
static SCIP_RETCODE putLpDataInInterface(SCIP *scip, SCIP_SDPI *sdpi, SdpVarmapper *varmapper, SCIP_Bool primalobj, SCIP_Bool dualobj)
Definition: relax_sdp.c:527
SCIP_RETCODE SCIPsdpiGetNLPRows(SCIP_SDPI *sdpi, int *nlprows)
Definition: sdpi.c:2257
#define DEFAULT_WARMSTARTPREOPTGAP
Definition: relax_sdp.c:80
SCIP_RETCODE SCIPsdpiGetPrimalBoundVars(SCIP_SDPI *sdpi, SCIP_Real *lbvars, SCIP_Real *ubvars, int *arraylength)
Definition: sdpi.c:3469
interface methods for eigenvector computation and matrix multiplication using different versions of L...
#define DEFAULT_WARMSTARTPROJPDSAME
Definition: relax_sdp.c:78
int SCIPrelaxSdpGetNprimalSlaterUnknown(SCIP_RELAX *relax)
Definition: relax_sdp.c:5415
SCIP_RETCODE SCIPconsSdpGuessInitialPoint(SCIP *scip, SCIP_CONS *cons, SCIP_Real *lambdastar)
Definition: cons_sdp.c:2759
int SCIPrelaxSdpGetNSlaterInfeasibleUnsolved(SCIP_RELAX *relax)
Definition: relax_sdp.c:5602
SCIP_Bool SCIPsdpiSolvedOrig(SCIP_SDPI *sdpi)
Definition: sdpi.c:2857
SCIP_RETCODE SCIPsdpiSlater(SCIP_SDPI *sdpi, SCIP_SDPSLATER *primalslater, SCIP_SDPSLATER *dualslater)
Definition: sdpi.c:3938
#define DEFAULT_SDPSOLVERTHREADS
Definition: relax_sdp.c:91
constraint handler for saving SDP solutions in nodes
SCIP_RETCODE SCIPincludeRelaxSdp(SCIP *scip)
Definition: relax_sdp.c:4255
#define DEFAULT_WARMSTART_PREOPTIMAL_SOL
Definition: relax_sdp.c:79
constraint handler for saving SDP settings