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