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-2019 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-2019 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.0
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.0
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_PREOPT_MIN_Z_LPVAL 0.01
102 #define TIMEOFDAY_CALL(x) do \
103  { \
104  int _errorcode_; \
105  if ( (_errorcode_ = (x)) != 0 ) \
106  { \
107  SCIPerrorMessage("Error in gettimeofday! \n"); \
108  return SCIP_ERROR; \
109  } \
110  } \
111  while( FALSE )
112 
113 /*
114  * Data structures
115  */
116 
118 struct SCIP_RelaxData
119 {
120  SCIP_SDPI* sdpi;
121  SCIP_LPI* lpi;
122  SdpVarmapper* varmapper;
124  SCIP_Real objval;
125  SCIP_Bool origsolved;
126  SCIP_Bool probingsolved;
127  long int lastsdpnode;
128  SCIP_Bool feasible;
130  SCIP_Real sdpsolvergaptol;
131  SCIP_Real sdpsolverfeastol;
132  SCIP_Real penaltyparam;
133  SCIP_Real maxpenaltyparam;
134  SCIP_Real lambdastar;
135  SCIP_Real computedlambdastar;
136  int npenaltyincr;
137  SCIP_Real peninfeasadjust;
138  int slatercheck;
139  SCIP_Bool sdpinfo;
140  SCIP_Bool displaystat;
141  SCIP_Bool objlimit;
142  SCIP_Bool resolve;
143  SCIP_Bool tightenvb;
144  int settingsresetfreq;
145  int settingsresetofs;
146  int sdpsolverthreads;
148  int sdpcalls;
149  int sdpinterfacecalls;
150  int sdpiterations;
151  int solvedfast;
152  int solvedmedium;
153  int solvedstable;
154  int solvedpenalty;
155  int unsolved;
156  int stablewslater;
157  int unstablewslater;
158  int penaltywslater;
159  int boundedwslater;
160  int unsolvedwslater;
161  int stablenoslater;
162  int unstablenoslater;
163  int penaltynoslater;
164  int boundednoslater;
165  int unsolvednoslater;
166  int nslaterholds;
167  int nnoslater;
168  int nslatercheckfailed;
170  int npslaterholds;
171  int npnoslater;
172  int npslatercheckfailed;
173  int ndslaterholds;
174  int ndnoslater;
175  int ndslatercheckfailed;
176  int nslaterinfeasible;
177  int stableinfeasible;
178  int unstableinfeasible;
179  int penaltyinfeasible;
180  int boundedinfeasible;
181  int unsolvedinfeasible;
182  int roundingprobinf;
183  int primalroundfails;
184  int dualroundfails;
185  int roundstartsuccess;
186  int roundingoptimal;
187  int roundingcutoff;
188  SCIP_Real roundingprobtime;
190  SCIP_Bool warmstart;
191  SCIP_Real warmstartipfactor;
192  int warmstartprimaltype;
194  int warmstartproject;
195  SCIP_Real warmstartpmevprimalpar;
196  SCIP_Real warmstartpmevdualpar;
197  SCIP_Real warmstartprojminevprimal;
198  SCIP_Real warmstartprojminevdual;
199  SCIP_Bool warmstartprojpdsame;
200  int warmstartiptype;
201  SCIP_Bool warmstartpreoptsol;
202  SCIP_Real warmstartpreoptgap;
203  SCIP_Bool warmstartroundonlyinf;
204  int nblocks;
205  SCIP_Bool ipXexists;
206  int* ipXnblocknonz;
208  int** ipXrow;
209  int** ipXcol;
210  SCIP_Real** ipXval;
211  SCIP_Bool ipZexists;
212  SCIP_SOL* ipy;
213  int* ipZnblocknonz;
215  int** ipZrow;
216  int** ipZcol;
217  SCIP_Real** ipZval;
218 };
219 
221 static
222 SCIP_RETCODE expandSparseMatrix(
223  int nnonz,
224  int blocksize,
225  int* row,
226  int* col,
227  SCIP_Real* val,
228  SCIP_Real* fullmat
229  )
230 {
231  int i;
232  int matrixsize;
233 
234  assert( nnonz >= 0 );
235  assert( row != NULL );
236  assert( col != NULL );
237  assert( val != NULL );
238  assert( fullmat != NULL );
239 
240  matrixsize = blocksize * blocksize;
241 
242  /* initialize matrix with zeros */
243  for (i = 0; i < matrixsize; i++)
244  fullmat[i] = 0.0;
245 
246  for (i = 0; i < nnonz; i++)
247  {
248  assert( row[i] * blocksize + col[i] <= matrixsize );
249  fullmat[row[i] * blocksize + col[i]] = val[i]; /*lint !e679*/
250  assert( col[i] * blocksize + row[i] <= matrixsize );
251  fullmat[col[i] * blocksize + row[i]] = val[i]; /*lint !e679*/
252  }
253 
254  return SCIP_OKAY;
255 }
256 
258 static
260  int blocksize, /* number of rows and columns */
261  SCIP_Real* matrix, /* matrix entries given as blocksize^2 array */
262  SCIP_Real* scale /* array of length blocksize to multiply the columns of matrix with */
263  )
264 {
265  int r;
266  int c;
267 
268  assert( blocksize >= 0 );
269  assert( matrix != NULL );
270  assert( scale != NULL );
271 
272  for (r = 0; r < blocksize; r++)
273  {
274  for (c = 0; c < blocksize; c++)
275  {
276  matrix[r * blocksize + c] *= scale[c]; /*lint !e679*/
277  }
278  }
279 
280  return SCIP_OKAY;
281 }
282 
284 static
286  SCIP* scip,
287  SCIP_SDPI* sdpi,
288  SdpVarmapper* varmapper,
289  SCIP_Bool primalobj,
290  SCIP_Bool boundprimal
291  )
292 {
293  SCIP_CONSHDLR* conshdlr;
294  const char* conshdlrname;
295  SCIP_CONS** conss;
296  SCIP_VAR** blockvars;
297  SCIP_VAR** vars;
298  SCIP_Real*** val;
299  SCIP_Real** constval;
300  SCIP_Real* obj;
301  SCIP_Real* lb;
302  SCIP_Real* ub;
303  SCIP_Real param;
304  int*** row;
305  int*** col;
306  int** nblockvarnonz;
307  int** constrow;
308  int** constcol;
309  int** sdpvar;
310  int* sdpblocksizes;
311  int* nblockvars;
312  int* nconstblocknonz;
313  int constnnonzcounter;
314  int blocknnonz;
315  int sdpconstnnonz;
316  int sdpnnonz;
317  int nsdpblocks;
318  int constlength;
319  int nvars;
320  int nvarspen;
321  int nconss;
322  int ind;
323  int i;
324  int j;
325 
326  SCIP_CALL( SCIPgetRealParam(scip, "relaxing/SDP/sdpsolvergaptol", &param) );
327 
328  SCIPdebugMessage("Putting SDP Data in general SDP interface!\n");
329 
330  assert( scip != NULL );
331  assert( sdpi != NULL );
332  assert( varmapper != NULL );
333 
334  vars = SCIPgetVars(scip);
335  nvars = SCIPgetNVars(scip);
336  nvarspen = boundprimal ? nvars + 1 : nvars; /* if the primal should be bounded, an additional penalty variable is added to the dual */
337 
338  /* prepare arrays of objective values and bounds */
339  SCIP_CALL( SCIPallocBufferArray(scip, &obj, nvarspen) );
340  SCIP_CALL( SCIPallocBufferArray(scip, &lb, nvarspen) );
341  SCIP_CALL( SCIPallocBufferArray(scip, &ub, nvarspen) );
342 
343  for (i = 0; i < nvars; i++)
344  {
345  obj[i] = SCIPvarGetObj(vars[i]);
346  lb[i] = SCIPvarGetLbLocal(vars[i]);
347  ub[i] = SCIPvarGetUbLocal(vars[i]);
348  }
349  if ( boundprimal )
350  {
351  obj[nvars] = 1.0; /* this objective coefficient together with lb = 0 and the identity matrix leads to constraint Tr(X) <= 1 */
352  lb[nvars] = 0.0;
353  ub[nvars] = SCIPinfinity(scip);
354  }
355 
356  nconss = SCIPgetNConss(scip);
357  conss = SCIPgetConss(scip);
358 
359  /* count the number of sdpblocks and compute the number of nonzeros */
360  nsdpblocks = 0;
361  sdpnnonz = 0;
362  sdpconstnnonz = 0;
363 
364  for (i = 0; i < nconss; i++)
365  {
366  conshdlr = SCIPconsGetHdlr(conss[i]);
367  assert( conshdlr != NULL );
368 
369  conshdlrname = SCIPconshdlrGetName(conshdlr);
370 
371 #ifdef SCIP_EVEN_MORE_DEBUG
372  SCIP_CALL( SCIPprintCons(scip, conss[i], NULL) );
373  SCIPinfoMessage(scip, NULL, "\n");
374 #endif
375 
376  if ( strcmp(conshdlrname, "SDP") == 0 )
377  {
378  nsdpblocks++;
379 
380  SCIP_CALL( SCIPconsSdpGetNNonz(scip, conss[i], &blocknnonz, &constnnonzcounter) );
381  sdpnnonz += blocknnonz;
382  sdpconstnnonz += constnnonzcounter;
383  }
384  }
385 
386  /* create the sdp- and sdpconst-arrays */
387  SCIP_CALL( SCIPallocBufferArray(scip, &sdpblocksizes, nsdpblocks) );
388  SCIP_CALL( SCIPallocBufferArray(scip, &nblockvarnonz, nsdpblocks) );
389  SCIP_CALL( SCIPallocBufferArray(scip, &nconstblocknonz, nsdpblocks) );
390  SCIP_CALL( SCIPallocBufferArray(scip, &col, nsdpblocks) );
391  SCIP_CALL( SCIPallocBufferArray(scip, &row, nsdpblocks) );
392  SCIP_CALL( SCIPallocBufferArray(scip, &val, nsdpblocks) );
393  SCIP_CALL( SCIPallocBufferArray(scip, &constcol, nsdpblocks) );
394  SCIP_CALL( SCIPallocBufferArray(scip, &constrow, nsdpblocks) );
395  SCIP_CALL( SCIPallocBufferArray(scip, &constval, nsdpblocks) );
396  SCIP_CALL( SCIPallocBufferArray(scip, &nblockvars, nsdpblocks) );
397  SCIP_CALL( SCIPallocBufferArray(scip, &sdpvar, nsdpblocks) );
398 
399  for (i = 0; i < nsdpblocks; i++)
400  {
401  SCIP_CALL( SCIPallocBufferArray(scip, &(nblockvarnonz[i]), nvarspen) );
402  SCIP_CALL( SCIPallocBufferArray(scip, &col[i], nvarspen) );
403  SCIP_CALL( SCIPallocBufferArray(scip, &row[i], nvarspen) );
404  SCIP_CALL( SCIPallocBufferArray(scip, &val[i], nvarspen) );
405  }
406 
407  /* get the SDP-data */
408  ind = 0; /* index of the current sdp block in the complete sdp */
409  SCIP_CALL( SCIPallocBufferArray(scip, &blockvars, nvars) );
410 
411  for (i = 0; i < nconss; i++)
412  {
413  conshdlr = SCIPconsGetHdlr(conss[i]);
414  assert( conshdlr != NULL );
415 
416  conshdlrname = SCIPconshdlrGetName(conshdlr);
417 
418  if ( strcmp(conshdlrname, "SDP") == 0 )
419  {
420  assert( ind < nsdpblocks );
421 
422  /* allocate memory for the constant nonzeros */
423  SCIP_CALL( SCIPconsSdpGetNNonz(scip, conss[i], NULL, &constlength) );
424  nconstblocknonz[ind] = constlength;
425  SCIP_CALL( SCIPallocBufferArray(scip, &(constcol[ind]), constlength) );
426  SCIP_CALL( SCIPallocBufferArray(scip, &(constrow[ind]), constlength) );
427  SCIP_CALL( SCIPallocBufferArray(scip, &(constval[ind]), constlength) );
428 
429  /* get the data */
430  SCIP_CALL( SCIPconsSdpGetData(scip, conss[i], &nblockvars[ind], &blocknnonz, &sdpblocksizes[ind], &nvars, nblockvarnonz[ind], col[ind],
431  row[ind], val[ind], blockvars, &nconstblocknonz[ind], constcol[ind], constrow[ind], constval[ind]) );
432 
433  /* nvars and nconstblocknonz[ind] would have been overwritten if the space in the given arrays hadn't been sufficient */
434  assert( nvars == SCIPgetNVars(scip) );
435  assert( nconstblocknonz[ind] <= constlength );
436 
437  SCIP_CALL( SCIPallocBufferArray(scip, &(sdpvar[ind]), boundprimal ? nblockvars[ind] + 1 : nblockvars[ind]) );
438 
439  /* get global variable indices */
440  for (j = 0; j < nblockvars[ind]; j++)
441  sdpvar[ind][j] = SCIPsdpVarmapperGetSdpIndex(varmapper, blockvars[j]);
442 
443  if ( boundprimal )
444  {
445  /* penalty variable is added as final variable to bound the primal */
446  sdpvar[ind][nblockvars[ind]] = SCIPsdpVarmapperGetNVars(varmapper);
447  nblockvarnonz[ind][nblockvars[ind]] = sdpblocksizes[ind];
448 
449  /* add identity matrix times penalty variable */
450  SCIP_CALL( SCIPallocBufferArray(scip, &col[ind][nblockvars[ind]], sdpblocksizes[ind]) );
451  SCIP_CALL( SCIPallocBufferArray(scip, &row[ind][nblockvars[ind]], sdpblocksizes[ind]) );
452  SCIP_CALL( SCIPallocBufferArray(scip, &val[ind][nblockvars[ind]], sdpblocksizes[ind]) );
453 
454  for (j = 0; j < sdpblocksizes[ind]; j++)
455  {
456  col[ind][nblockvars[ind]][j] = j;
457  row[ind][nblockvars[ind]][j] = j;
458  val[ind][nblockvars[ind]][j] = 1.0;
459  }
460  nblockvars[ind]++;
461  }
462 
463  ind++;
464  }
465  }
466 
467  /* free the memory that is no longer needed */
468  SCIPfreeBufferArray(scip, &blockvars);
469 
470  /* load data into SDPI */
471  if ( primalobj )
472  {
473  SCIP_CALL( SCIPsdpiLoadSDP(sdpi, nvarspen, obj, lb, ub, nsdpblocks, sdpblocksizes, nblockvars, sdpconstnnonz, nconstblocknonz, constrow,
474  constcol, constval, sdpnnonz, nblockvarnonz, sdpvar, row, col, val, 0,
475  NULL, NULL, 0, NULL, NULL, NULL) ); /* insert the SDP part, add an empty LP part */
476  }
477  else
478  {
479  /* overwrite nconstblocknonz */
480  for (i = 0; i < nsdpblocks; i++)
481  nconstblocknonz[i] = 0;
482 
483  SCIP_CALL( SCIPsdpiLoadSDP(sdpi, nvarspen, obj, lb, ub, nsdpblocks, sdpblocksizes, nblockvars, 0, nconstblocknonz, NULL,
484  NULL, NULL, sdpnnonz, nblockvarnonz, sdpvar, row, col, val, 0,
485  NULL, NULL, 0, NULL, NULL, NULL) ); /* insert the SDP part, add an empty LP part */
486  }
487 
488 
489  /* free the remaining memory */
490  for (i = 0; i < nsdpblocks; i++)
491  {
492  if ( boundprimal )
493  {
494  SCIPfreeBufferArrayNull(scip, &val[i][nblockvars[i] - 1]);
495  SCIPfreeBufferArrayNull(scip, &row[i][nblockvars[i] - 1]);
496  SCIPfreeBufferArrayNull(scip, &col[i][nblockvars[i] - 1]);
497  }
498  SCIPfreeBufferArrayNull(scip, &(sdpvar[i]));
499  SCIPfreeBufferArrayNull(scip, &val[i]);
500  SCIPfreeBufferArrayNull(scip, &row[i]);
501  SCIPfreeBufferArrayNull(scip, &col[i]);
502  SCIPfreeBufferArrayNull(scip, &(nblockvarnonz[i]));
503  SCIPfreeBufferArrayNull(scip, &(constval[i]));
504  SCIPfreeBufferArrayNull(scip, &(constrow[i]));
505  SCIPfreeBufferArrayNull(scip, &(constcol[i]));
506  }
507 
508  SCIPfreeBufferArrayNull(scip, &sdpvar);
509  SCIPfreeBufferArrayNull(scip, &nblockvars);
510  SCIPfreeBufferArrayNull(scip, &constval);
511  SCIPfreeBufferArrayNull(scip, &constrow);
512  SCIPfreeBufferArrayNull(scip, &constcol);
513  SCIPfreeBufferArrayNull(scip, &val);
514  SCIPfreeBufferArrayNull(scip, &row);
515  SCIPfreeBufferArrayNull(scip, &col);
516  SCIPfreeBufferArrayNull(scip, &nconstblocknonz);
517  SCIPfreeBufferArrayNull(scip, &nblockvarnonz);
518  SCIPfreeBufferArrayNull(scip, &sdpblocksizes);
519  SCIPfreeBufferArray(scip, &ub);
520  SCIPfreeBufferArray(scip, &lb);
521  SCIPfreeBufferArray(scip, &obj);
522 
523  return SCIP_OKAY;
524 }
525 
527 static
528 SCIP_RETCODE putLpDataInInterface(
529  SCIP* scip,
530  SCIP_SDPI* sdpi,
531  SdpVarmapper* varmapper,
532  SCIP_Bool primalobj,
533  SCIP_Bool dualobj
534  )
535 {
536  SCIP_VAR** vars;
537  SCIP_COL** rowcols;
538  SCIP_ROW** rows;
539  SCIP_Bool tightenvb;
540  SCIP_Real* rowvals;
541  SCIP_Real* lhs;
542  SCIP_Real* rhs;
543  SCIP_Real* obj;
544  SCIP_Real* lb;
545  SCIP_Real* ub;
546  SCIP_Real* val;
547  SCIP_Real sciplhs;
548  SCIP_Real sciprhs;
549  int* inds;
550  int* objinds;
551  int* rowind;
552  int* colind;
553  int nrowssdpi;
554  int nrows;
555  int rownnonz;
556  int nvars;
557  int nconss;
558  int scipnnonz;
559  int nnonz;
560  int i;
561  int j;
562 
563  assert( scip != NULL );
564  assert( sdpi != NULL );
565  assert( varmapper != NULL );
566 
567  nvars = SCIPgetNVars(scip);
568  assert( nvars > 0 );
569 
570  SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
571  SCIP_CALL( SCIPgetBoolParam(scip, "relaxing/SDP/tightenvb", &tightenvb) );
572 
573  SCIPdebugMessage("inserting %d LPRows into the interface.\n", nrows);
574 
575  /* compute the total number of LP nonzeroes in SCIP */
576  scipnnonz = 0;
577  for (i = 0; i < nrows; i++)
578  {
579  assert( rows[i] != NULL );
580  scipnnonz += SCIProwGetNNonz(rows[i]);
581  }
582 
583  /* allocate memory */
584  SCIP_CALL( SCIPallocBufferArray(scip, &lhs, nrows) );
585  SCIP_CALL( SCIPallocBufferArray(scip, &rhs, nrows) );
586  SCIP_CALL( SCIPallocBufferArray(scip, &rowind, scipnnonz) );
587  SCIP_CALL( SCIPallocBufferArray(scip, &colind, scipnnonz) );
588  SCIP_CALL( SCIPallocBufferArray(scip, &val, scipnnonz) );
589 
590  /* insert the nonzeroes */
591  nnonz = 0; /* this is recomputed for the sdpi, because of the possible duplication of non-zeroes for lhs and rhs */
592  nconss = 0; /* this will be increased for each finite lhs and rhs */
593 
594  for (i = 0; i < nrows; i++)
595  {
596  SCIP_ROW* row;
597  SCIP_Bool tightened = FALSE;
598  SCIP_Real tightenedval = 0.0;
599  SCIP_Bool swapped = FALSE;
600 
601  row = rows[i];
602  assert( row != 0 );
603  rownnonz = SCIProwGetNNonz(row);
604 
605  rowvals = SCIProwGetVals(row);
606  rowcols = SCIProwGetCols(row);
607  sciplhs = SCIProwGetLhs(row) - SCIProwGetConstant(row);
608  sciprhs = SCIProwGetRhs(row) - SCIProwGetConstant(row);
609 
610  /* check whether we have a variable bound and can strenghten the big-M */
611  if ( tightenvb && rownnonz == 2 && (SCIPisZero(scip, sciplhs) || SCIPisZero(scip, sciprhs) ) )
612  {
613  SCIP_VAR* var1;
614  SCIP_VAR* var2;
615  SCIP_Real val1;
616  SCIP_Real val2;
617 
618  val1 = rowvals[0];
619  val2 = rowvals[1];
620 
621  assert( rowcols[0] != NULL );
622  assert( rowcols[1] != NULL );
623  var1 = SCIPcolGetVar(rowcols[0]);
624  var2 = SCIPcolGetVar(rowcols[1]);
625  assert( var1 != NULL );
626  assert( var2 != NULL );
627 
628  /* check that variables are not locally fixed */
629  if ( ! SCIPisEQ(scip, SCIPvarGetLbLocal(var1), SCIPvarGetUbLocal(var1)) && ! SCIPisEQ(scip, SCIPvarGetLbLocal(var2), SCIPvarGetUbLocal(var2)) )
630  {
631  /* one coefficient must be 1 and the other negative */
632  if ( (SCIPisEQ(scip, val1, 1.0) || SCIPisEQ(scip, val2, 1.0)) && ( SCIPisNegative(scip, val1) || SCIPisNegative(scip, val2) ) )
633  {
634  /* We want x - a z <= 0 or x - a z >= 0, where var1 = x and var2 = z; possibly swap variables otherwise */
635  if ( ! SCIPisEQ(scip, val1, 1.0) || ! SCIPisNegative(scip, val2) )
636  {
637  SCIPswapPointers((void**) &var1, (void**) &var2);
638 
639  val2 = val1;
640  swapped = TRUE;
641  }
642 
643  /* var2 needs to be binary */
644  if ( SCIPvarIsBinary(var2) )
645  {
646  if ( SCIPisZero(scip, sciprhs) )
647  {
648  if ( SCIPisLT(scip, SCIPvarGetUbLocal(var1), REALABS(val2)) )
649  {
650  SCIPdebugMessage("Big-M in %s changed from %f to %f\n", SCIProwGetName(row), REALABS(val2), SCIPvarGetUbLocal(var1));
651 
652  tightened = TRUE;
653  tightenedval = -SCIPvarGetUbLocal(var1); /* negative sign because the coefficient needs to be negative */
654  }
655  }
656 
657  if ( SCIPisZero(scip, sciplhs) )
658  {
659  if ( SCIPisGT(scip, SCIPvarGetLbLocal(var1), REALABS(val2)) )
660  {
661  SCIPdebugMessage("Big-M in %s changed from %f to %f\n", SCIProwGetName(row), REALABS(val2), SCIPvarGetLbLocal(var1));
662 
663  tightened = TRUE;
664  tightenedval = -SCIPvarGetUbLocal(var1); /* negative sign because the coefficient needs to be negative */
665  }
666  }
667  }
668  }
669  }
670  }
671 
672  for (j = 0; j < rownnonz; j++)
673  {
674  /* 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) */
675  if ( tightened && ( (swapped && (j == 0)) || ((! swapped) && (j == 1)) ) ) /* use the tightened value */
676  {
677  if ( SCIPisFeasGT(scip, REALABS(tightenedval), 0.0) )
678  {
679  assert( SCIPcolGetVar(rowcols[j]) != 0 );
680  colind[nnonz] = SCIPsdpVarmapperGetSdpIndex(varmapper, SCIPcolGetVar(rowcols[j]));
681  rowind[nnonz] = nconss;
682  val[nnonz] = tightenedval;
683  nnonz++;
684  }
685  }
686  else if ( SCIPisFeasGT(scip, REALABS(rowvals[j]), 0.0))
687  {
688  assert( SCIPcolGetVar(rowcols[j]) != 0 );
689  colind[nnonz] = SCIPsdpVarmapperGetSdpIndex(varmapper, SCIPcolGetVar(rowcols[j]));
690  rowind[nnonz] = nconss;
691  val[nnonz] = rowvals[j];
692  nnonz++;
693  }
694  }
695  lhs[nconss] = primalobj ? sciplhs : (SCIPisInfinity(scip, -sciplhs) ? -sciplhs : 0.0);
696  rhs[nconss] = primalobj ? sciprhs : (SCIPisInfinity(scip, sciprhs) ? sciprhs : 0.0);
697  nconss++;
698  }
699 
700  /* delete the old LP-block from the sdpi */
701  SCIP_CALL( SCIPsdpiGetNLPRows(sdpi, &nrowssdpi) );
702  if ( nrowssdpi > 0 )
703  {
704  SCIP_CALL( SCIPsdpiDelLPRows(sdpi, 0, nrowssdpi - 1) );
705  }
706 
707  /* add the LP-block to the sdpi */
708  SCIP_CALL( SCIPsdpiAddLPRows(sdpi, nconss, lhs, rhs, nnonz, (const int*)rowind, (const int*)colind, val) );
709 
710  /* free the remaining arrays */
711  SCIPfreeBufferArray(scip, &val);
712  SCIPfreeBufferArray(scip, &colind);
713  SCIPfreeBufferArray(scip, &rowind);
714  SCIPfreeBufferArray(scip, &rhs);
715  SCIPfreeBufferArray(scip, &lhs);
716 
717  /* update bounds */
718 
719  /* get the variables */
720  vars = SCIPgetVars(scip);
721  assert( vars != NULL );
722 
723  /* prepare arrays of bounds */
724  SCIP_CALL( SCIPallocBufferArray(scip, &lb, nvars) );
725  SCIP_CALL( SCIPallocBufferArray(scip, &ub, nvars) );
726  SCIP_CALL( SCIPallocBufferArray(scip, &inds, nvars) );
727  SCIP_CALL( SCIPallocBufferArray(scip, &obj, nvars) );
728  SCIP_CALL( SCIPallocBufferArray(scip, &objinds, nvars) );
729 
730  /* get new bounds and objective coefficients */
731  for (i = 0; i < nvars; i++)
732  {
733  assert( vars[i] != NULL );
734  lb[i] = primalobj ? SCIPvarGetLbLocal(vars[i]) : (SCIPisInfinity(scip, -SCIPvarGetLbLocal(vars[i])) ? SCIPvarGetLbLocal(vars[i]) : 0.0);
735  ub[i] = primalobj ? SCIPvarGetUbLocal(vars[i]) : (SCIPisInfinity(scip, SCIPvarGetUbLocal(vars[i])) ? SCIPvarGetUbLocal(vars[i]) : 0.0);
736  inds[i] = i; /* we want to change all bounds, so all indices are included in inds */
737  obj[i] = dualobj ? SCIPvarGetObj(vars[i]) : 0.0;
738  objinds[i] = i;
739  }
740 
741  /* inform interface */
742  SCIP_CALL( SCIPsdpiChgBounds(sdpi, nvars, inds, lb, ub) );
743  SCIP_CALL( SCIPsdpiChgObj(sdpi, nvars, objinds, obj) );
744 
745  /* free the bounds-arrays */
746  SCIPfreeBufferArray(scip, &objinds);
747  SCIPfreeBufferArray(scip, &obj);
748  SCIPfreeBufferArray(scip, &inds);
749  SCIPfreeBufferArray(scip, &ub);
750  SCIPfreeBufferArray(scip, &lb);
751 
752  return SCIP_OKAY;
753 }
754 
756 static
757 SCIP_RETCODE calcRelax(
758  SCIP* scip,
759  SCIP_RELAXDATA* relaxdata,
760  SCIP_RESULT* result,
761  SCIP_Real* lowerbound
762  )
763 {
764  char saveconsname[SCIP_MAXSTRLEN];
765  SCIP_SDPSOLVERSETTING startsetting;
766  SCIP_SDPSOLVERSETTING usedsetting;
767  SCIP_CONS* savedsetting;
768  SCIP_CONS** conss;
769  SCIP_VAR** vars;
770  SCIP_SDPI* sdpi;
771  SCIP_Bool rootnode;
772  SCIP_Bool enforceslater;
773  SCIP_Real timelimit;
774  SCIP_Real objforscip;
775  SCIP_Real* solforscip;
776  SCIP_SDPSLATERSETTING slatersetting;
777  SCIP_SDPSLATER primalslater;
778  SCIP_SDPSLATER dualslater;
779  int naddediters;
780  int naddedsdpcalls;
781  int nblocks;
782  int nvars;
783  int b;
784  int i;
785  int v;
786 
787  SCIPdebugMessage("calcRelax called\n");
788 
789  assert( scip != NULL );
790  assert( relaxdata != NULL );
791  assert( result != NULL );
792  assert( lowerbound != NULL );
793 
794  nvars = SCIPgetNVars(scip);
795  assert( nvars > 0 );
796  vars = SCIPgetVars (scip);
797 
798  sdpi = relaxdata->sdpi;
799  assert( sdpi != NULL );
800 
801  if ( relaxdata->objlimit )
802  {
803  /* set the objective limit */
804  assert( SCIPgetUpperbound(scip) > -SCIPsdpiInfinity(sdpi) );
805  SCIP_CALL( SCIPsdpiSetRealpar(sdpi, SCIP_SDPPAR_OBJLIMIT, SCIPgetUpperbound(scip)) );
806  }
807  /* 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 */
808  rootnode = ! SCIPnodeGetParent(SCIPgetCurrentNode(scip));
809 
810  /* find settings to use for this relaxation */
811  if ( rootnode || (SCIPnodeGetDepth(SCIPgetCurrentNode(scip)) == relaxdata->settingsresetofs) ||
812  ( relaxdata->settingsresetfreq > 0 && ((SCIPnodeGetDepth(SCIPgetCurrentNode(scip)) - relaxdata->settingsresetofs) % relaxdata->settingsresetfreq == 0)) ||
813  (strcmp(SCIPsdpiGetSolverName(), "DSDP") == 0) || (strstr(SCIPsdpiGetSolverName(), "Mosek") != NULL))
814  {
815  startsetting = SCIP_SDPSOLVERSETTING_UNSOLVED; /* in the root node we have no information, at each multiple of resetfreq we reset */
816  }
817  else
818  {
819  SCIP_CONSHDLR* conshdlr;
820  int parentconsind;
821 
822  /* get constraint handler */
823  conshdlr = SCIPfindConshdlr(scip, "Savedsdpsettings");
824  if ( conshdlr == NULL )
825  {
826  SCIPerrorMessage("Savedsdpsettings constraint handler not found!\n");
827  return SCIP_PLUGINNOTFOUND;
828  }
829 
830  /* get startsettings of parent node, usually it will be the last active constraint of the corresponding constraint handler, so we iterate from
831  * the end of the list until we find the correct one */
832  conss = SCIPconshdlrGetConss(conshdlr);
833  parentconsind = SCIPconshdlrGetNActiveConss(conshdlr) - 1;
834  (void) SCIPsnprintf(saveconsname, SCIP_MAXSTRLEN, "savedsettings_node_%d", SCIPnodeGetNumber(SCIPnodeGetParent(SCIPgetCurrentNode(scip))));
835 
836  while ( parentconsind >= 0 && strcmp(saveconsname, SCIPconsGetName(conss[parentconsind])) )
837  parentconsind--;
838  if ( parentconsind >= 0 )
839  startsetting = SCIPconsSavedsdpsettingsGetSettings(scip, conss[parentconsind]);
840  else
841  {
842  SCIPdebugMessage("Startsetting from parent node not found, restarting with fastest settings!\n");
843  startsetting = SCIP_SDPSOLVERSETTING_UNSOLVED;
844  }
845  }
846 
847  /* set time limit */
848  SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
849  if ( ! SCIPisInfinity(scip, timelimit) )
850  {
851  timelimit -= SCIPgetSolvingTime(scip);
852  if ( timelimit <= 0.0 )
853  {
854  SCIPdebugMessage("Time limit reached, not running relax SDP!\n");
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 epsilon;
1078  int matrixsize;
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 epsilon;
2514  int matrixsize;
2515  int matrixpos;
2516  int c;
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  assert( startXval != NULL );
2918  assert( startXcol != NULL );
2919  assert( startXrow != NULL );
2920  assert( startZval != NULL );
2921  assert( startZcol != NULL );
2922  assert( startZrow != NULL );
2923 
2924  /* free memory */
2925  for (b = 0; b < nblocks; b++)
2926  {
2927  SCIPfreeBufferArray(scip, &startXval[b]);
2928  SCIPfreeBufferArray(scip, &startXcol[b]);
2929  SCIPfreeBufferArray(scip, &startXrow[b]);
2930  SCIPfreeBufferArray(scip, &startZval[b]);
2931  SCIPfreeBufferArray(scip, &startZcol[b]);
2932  SCIPfreeBufferArray(scip, &startZrow[b]);
2933  }
2934 
2935  SCIPfreeBufferArray(scip, &startXval);
2936  SCIPfreeBufferArray(scip, &startXcol);
2937  SCIPfreeBufferArray(scip, &startXrow);
2938  SCIPfreeBufferArray(scip, &startXnblocknonz);
2939  SCIPfreeBufferArray(scip, &startZval);
2940  SCIPfreeBufferArray(scip, &startZcol);
2941  SCIPfreeBufferArray(scip, &startZrow);
2942  SCIPfreeBufferArray(scip, &startZnblocknonz);
2943  }
2944  SCIPfreeBufferArray(scip, &starty);
2945  }
2946  }
2947 
2948  solved:
2949 
2950  relaxdata->lastsdpnode = SCIPnodeGetNumber(SCIPgetCurrentNode(scip));
2951 
2952  /* update calls, iterations and stability numbers (only if the SDP-solver was actually called) */
2953  relaxdata->sdpinterfacecalls++;
2954  naddedsdpcalls = 0;
2955  SCIP_CALL( SCIPsdpiGetSdpCalls(relaxdata->sdpi, &naddedsdpcalls) );
2956  usedsetting = SCIP_SDPSOLVERSETTING_UNSOLVED;
2957  if ( naddedsdpcalls )
2958  {
2959  relaxdata->sdpcalls += naddedsdpcalls;
2960  naddediters = 0;
2961  SCIP_CALL( SCIPsdpiGetIterations(relaxdata->sdpi, &naddediters) );
2962  relaxdata->sdpiterations += naddediters;
2963 
2964  SCIP_CALL( SCIPsdpiSettingsUsed(relaxdata->sdpi, &usedsetting) );
2965 
2966  switch( usedsetting )/*lint --e{788}*/
2967  {
2969  relaxdata->solvedpenalty++;
2970  break;
2972  relaxdata->solvedfast++;
2973  break;
2975  relaxdata->solvedmedium++;
2976  break;
2978  relaxdata->solvedstable++;
2979  break;
2981  relaxdata->unsolved++;
2982  break;
2983  default:
2984  break;
2985  }
2986  primalslater = SCIP_SDPSLATER_NOINFO;
2987  dualslater = SCIP_SDPSLATER_NOINFO;
2988  SCIP_CALL( SCIPsdpiSlater(relaxdata->sdpi, &primalslater, &dualslater) );
2989  switch( primalslater )/*lint --e{788}*/
2990  {
2991  case SCIP_SDPSLATER_NOINFO:
2992  relaxdata->npslatercheckfailed++;
2993  switch( dualslater )/*lint --e{788}*/
2994  {
2995  case SCIP_SDPSLATER_NOINFO:
2996  relaxdata->ndslatercheckfailed++;
2997  relaxdata->nslatercheckfailed++;
2998  break;
2999  case SCIP_SDPSLATER_NOT:
3000  relaxdata->ndnoslater++;
3001  relaxdata->nnoslater++;
3002  break;
3003  case SCIP_SDPSLATER_HOLDS:
3004  relaxdata->ndslaterholds++;
3005  relaxdata->nslatercheckfailed++;
3006  break;
3007  case SCIP_SDPSLATER_INF:
3008  relaxdata->nslaterinfeasible++;
3009  break;
3010  default:
3011  relaxdata->ndslatercheckfailed++;
3012  relaxdata->nslatercheckfailed++;
3013  break;
3014  }
3015  break;
3016  case SCIP_SDPSLATER_NOT:
3017  relaxdata->npnoslater++;
3018  switch( dualslater )/*lint --e{788}*/
3019  {
3020  case SCIP_SDPSLATER_NOINFO:
3021  relaxdata->ndslatercheckfailed++;
3022  relaxdata->nnoslater++;
3023  break;
3024  case SCIP_SDPSLATER_NOT:
3025  relaxdata->ndnoslater++;
3026  relaxdata->nnoslater++;
3027  break;
3028  case SCIP_SDPSLATER_HOLDS:
3029  relaxdata->ndslaterholds++;
3030  relaxdata->nnoslater++;
3031  break;
3032  case SCIP_SDPSLATER_INF:
3033  relaxdata->nslaterinfeasible++;
3034  break;
3035  default:
3036  relaxdata->ndslatercheckfailed++;
3037  relaxdata->nnoslater++;
3038  break;
3039  }
3040  break;
3041  case SCIP_SDPSLATER_HOLDS:
3042  relaxdata->npslaterholds++;
3043  switch( dualslater )/*lint --e{788}*/
3044  {
3045  case SCIP_SDPSLATER_NOINFO:
3046  relaxdata->ndslatercheckfailed++;
3047  relaxdata->nslatercheckfailed++;
3048  break;
3049  case SCIP_SDPSLATER_NOT:
3050  relaxdata->ndnoslater++;
3051  relaxdata->nnoslater++;
3052  break;
3053  case SCIP_SDPSLATER_HOLDS:
3054  relaxdata->ndslaterholds++;
3055  relaxdata->nslaterholds++;
3056  break;
3057  case SCIP_SDPSLATER_INF:
3058  relaxdata->nslaterinfeasible++;
3059  break;
3060  default:
3061  relaxdata->ndslatercheckfailed++;
3062  relaxdata->nslatercheckfailed++;
3063  break;
3064  }
3065  break;
3066  default:
3067  relaxdata->npslatercheckfailed++;
3068  relaxdata->ndslatercheckfailed++;
3069  relaxdata->nslatercheckfailed++;
3070  break;
3071  }
3072  slatersetting = SCIP_SDPSLATERSETTING_NOINFO;
3073  SCIP_CALL( SCIPsdpiSlaterSettings(relaxdata->sdpi, &slatersetting) );
3074  switch( slatersetting )/*lint --e{788}*/
3075  {
3077  relaxdata->stablewslater++;
3078  break;
3080  relaxdata->unstablewslater++;
3081  break;
3083  relaxdata->penaltywslater++;
3084  break;
3086  relaxdata->boundedwslater++;
3087  break;
3089  relaxdata->unsolvedwslater++;
3090  break;
3092  relaxdata->stablenoslater++;
3093  break;
3095  relaxdata->unstablenoslater++;
3096  break;
3098  relaxdata->penaltynoslater++;
3099  break;
3101  relaxdata->boundednoslater++;
3102  break;
3104  relaxdata->unsolvednoslater++;
3105  break;
3107  relaxdata->stableinfeasible++;
3108  break;
3110  relaxdata->unstableinfeasible++;
3111  break;
3113  relaxdata->penaltyinfeasible++;
3114  break;
3116  relaxdata->boundedinfeasible++;
3117  break;
3119  relaxdata->unsolvedinfeasible++;
3120  break;
3121  default:
3122  break;
3123  }
3124  }
3125 
3126  /* remember settings */
3127  if ( ! (strcmp(SCIPsdpiGetSolverName(), "DSDP") == 0) && ! (strstr(SCIPsdpiGetSolverName(), "MOSEK") != NULL) )
3128  {
3129  (void) SCIPsnprintf(saveconsname, SCIP_MAXSTRLEN, "savedsettings_node_%d", SCIPnodeGetNumber(SCIPgetCurrentNode(scip)));
3130  SCIP_CALL( createConsSavedsdpsettings(scip, &savedsetting, saveconsname, usedsetting) );
3131  SCIP_CALL( SCIPaddCons(scip, savedsetting) );
3132  SCIP_CALL( SCIPreleaseCons(scip, &savedsetting) );
3133  }
3134 
3135  if ( ! SCIPsdpiWasSolved(sdpi) )
3136  relaxdata->feasible = FALSE;
3137 
3138  if ( SCIPinProbing(scip) )
3139  relaxdata->probingsolved = SCIPsdpiWasSolved(sdpi) && ( ! SCIPsdpiIsTimelimExc(sdpi) );
3140  else
3141  relaxdata->origsolved = SCIPsdpiSolvedOrig(sdpi) && ( ! SCIPsdpiIsTimelimExc(sdpi) );
3142 
3143  if ( SCIPsdpiIsAcceptable(sdpi) )
3144  {
3145 #ifdef SCIP_MORE_DEBUG /* print the optimal solution */
3146  {
3147  int sollength;
3148  SCIP_CALL( SCIPallocBufferArray(scip, &solforscip, nvars) );
3149  sollength = nvars;
3150  SCIP_CALL( SCIPsdpiGetSol(sdpi, &objforscip, solforscip, &sollength) ); /* get both the objective and the solution from the SDP solver */
3151 
3152  assert( sollength == nvars ); /* If this isn't true any longer, the getSol-call was unsuccessfull, because the given array wasn't long enough,
3153  * but this can't happen, because the array has enough space for all SDP variables. */
3154 
3155  if ( SCIPsdpiFeasibilityKnown(sdpi) )
3156  {
3157  SCIPdebugMessage("optimal solution: objective = %f, dual feasible: %u, primal feasible: %u.\n",
3158  objforscip, SCIPsdpiIsDualFeasible(sdpi), SCIPsdpiIsPrimalFeasible(sdpi));
3159  }
3160  else
3161  {
3162  SCIPdebugMessage("The solver could not determine feasibility ! ");
3163  }
3164 
3165  /* output solution */
3166  for (i = 0; i < nvars; ++i)
3167  {
3168  SCIPdebugMessage("<%s> = %f\n", SCIPvarGetName(vars[i]), solforscip[i]);
3169  }
3170  SCIPfreeBufferArray(scip, &solforscip);
3171  }
3172 #endif
3173 
3174  if ( SCIPsdpiIsDualInfeasible(sdpi) )
3175  {
3176  SCIPdebugMessage("Node cut off due to infeasibility.\n");
3177  relaxdata->feasible = FALSE;
3178  *result = SCIP_CUTOFF;
3179  return SCIP_OKAY;
3180  }
3181  else if ( SCIPsdpiIsObjlimExc(sdpi) )
3182  {
3183  SCIPdebugMessage("Node cut off due to objective limit.\n");
3184  relaxdata->feasible = FALSE;
3185  *result = SCIP_CUTOFF;
3186  return SCIP_OKAY;
3187  }
3188  else if ( SCIPsdpiIsDualUnbounded(sdpi) )
3189  {
3190  SCIPdebugMessage("Node unbounded.");
3191  relaxdata->feasible = TRUE;
3192  *result = SCIP_SUCCESS;
3193  *lowerbound = -SCIPinfinity(scip);
3194  return SCIP_OKAY;
3195  }
3196  else if ( SCIPsdpiIsPrimalFeasible(sdpi) && SCIPsdpiIsDualFeasible(sdpi) )
3197  {
3198  SCIP_SOL* scipsol; /* TODO: eliminate this from warmstart and save array instead */
3199  SCIP_SOL* preoptimalsol = NULL;
3200  SCIP_CONS* savedcons;
3201  int slength;
3202  SCIP_Bool preoptimalsolsuccess;
3203 
3204  /* get solution w.r.t. SCIP variables */
3205  SCIP_CALL( SCIPallocBufferArray(scip, &solforscip, nvars) );
3206  slength = nvars;
3207  SCIP_CALL( SCIPsdpiGetSol(sdpi, &objforscip, solforscip, &slength) ); /* get both the objective and the solution from the SDP solver */
3208 
3209  assert( slength == nvars ); /* If this isn't true any longer, the getSol-Call was unsuccessfull, because the given array wasn't long enough,
3210  * but this can't happen, because the array has enough space for all sdp variables. */
3211 
3212  /* create SCIP solution */
3213  SCIP_CALL( SCIPcreateSol(scip, &scipsol, NULL) );
3214  SCIP_CALL( SCIPsetSolVals(scip, scipsol, nvars, vars, solforscip) );
3215 
3216  *lowerbound = objforscip;
3217  relaxdata->objval = objforscip;
3218 
3219  /* copy solution */
3220  SCIP_CALL( SCIPsetRelaxSolVals(scip, nvars, vars, solforscip, TRUE) );
3221 
3222  relaxdata->feasible = TRUE;
3223  *result = SCIP_SUCCESS;
3224  preoptimalsolsuccess = FALSE;
3225 
3226  /* save solution for warmstarts (only if we did not use the penalty formulation, since this would change the problem structure) */
3227  if ( relaxdata->warmstart && SCIPsdpiSolvedOrig(relaxdata->sdpi) )
3228  {
3229  SCIP_Real maxprimalentry;
3230  int* startXnblocknonz;
3231  int** startXrow;
3232  int** startXcol;
3233  SCIP_Real** startXval;
3234  char consname[SCIP_MAXSTRLEN];
3235 #ifndef NDEBUG
3236  int snprintfreturn; /* this is used to assert that the SCIP string concatenation works */
3237 #endif
3238 
3239  startXnblocknonz = NULL;
3240  startXrow = NULL;
3241  startXcol = NULL;
3242  startXval = NULL;
3243 
3244  /* use preoptimal solution if using DSDP and parameter is set accordingly */
3245  if ( relaxdata->warmstartpreoptsol )
3246  {
3247  if ( strcmp(SCIPsdpiGetSolverName(), "DSDP") == 0.0 || strcmp(SCIPsdpiGetSolverName(), "SDPA") == 0.0 )
3248  {
3249  SCIP_Real* preoptimalvec;
3250  int nvarsgiven;
3251 
3252  SCIP_CALL( SCIPallocBufferArray(scip, &preoptimalvec, nvars) );
3253  nvarsgiven = nvars;
3254 
3256  {
3257  maxprimalentry = 0.0;
3258  if ( relaxdata->warmstartprimaltype == 3 )
3259  {
3260  nblocks = SCIPconshdlrGetNConss(SCIPfindConshdlr(scip, "SDP")) + 1; /* +1 for the LP part */
3261  SCIP_CALL( SCIPallocBufferArray(scip, &startXnblocknonz, nblocks) );
3262 
3263  /* get amount of memory to allocate for row/col/val from sdpi */
3264  SCIP_CALL( SCIPsdpiGetPreoptimalPrimalNonzeros(relaxdata->sdpi, nblocks, startXnblocknonz) );
3265 
3266  /* check if the primal matrix exists, otherwise skip creation of the savedsol contraint */
3267  if ( startXnblocknonz[0] > -1 )
3268  {
3269  preoptimalsolsuccess = TRUE;
3270 
3271  SCIP_CALL( SCIPallocBufferArray(scip, &startXrow, nblocks) );
3272  SCIP_CALL( SCIPallocBufferArray(scip, &startXcol, nblocks) );
3273  SCIP_CALL( SCIPallocBufferArray(scip, &startXval, nblocks) );
3274 
3275  /* allocate memory for different blocks in row/col/val */
3276  for (b = 0; b < nblocks; b++)
3277  {
3278  SCIP_CALL( SCIPallocBufferArray(scip, &startXrow[b], startXnblocknonz[b]) );
3279  SCIP_CALL( SCIPallocBufferArray(scip, &startXcol[b], startXnblocknonz[b]) );
3280  SCIP_CALL( SCIPallocBufferArray(scip, &startXval[b], startXnblocknonz[b]) );
3281  }
3282 
3283  SCIP_CALL( SCIPsdpiGetPreoptimalSol(relaxdata->sdpi, &preoptimalsolsuccess, preoptimalvec, &nvarsgiven,
3284  nblocks, startXnblocknonz, startXrow, startXcol, startXval) );
3285  }
3286  else
3287  preoptimalsolsuccess = FALSE;
3288  }
3289  else
3290  {
3291  nblocks = 0;
3292  maxprimalentry = SCIPsdpiGetMaxPrimalEntry(relaxdata->sdpi);
3293  }
3294  }
3295  else
3296  {
3297  maxprimalentry = 0.0;
3298  SCIP_CALL( SCIPsdpiGetPreoptimalSol(relaxdata->sdpi, &preoptimalsolsuccess, preoptimalvec, &nvarsgiven,
3299  -1, NULL, NULL, NULL, NULL) );
3300  nblocks = 0;
3301  }
3302 
3303  if ( preoptimalsolsuccess )
3304  {
3305  assert( nvarsgiven == nvars ); /* length of solution should be nvars */
3306 
3307  /* create SCIP solution */
3308  SCIP_CALL( SCIPcreateSol(scip, &preoptimalsol, NULL) );
3309  SCIP_CALL( SCIPsetSolVals(scip, preoptimalsol, nvars, vars, preoptimalvec) );
3310  }
3311 
3312  SCIPfreeBufferArray(scip, &preoptimalvec);
3313  }
3314  else
3315  {
3316  SCIPerrorMessage("Warmstarting with preoptimal solutions currently only supported for DSDP and SDPA \n");
3317  return SCIP_LPERROR;
3318  }
3319  }
3320  else if ( SCIPsdpiDoesWarmstartNeedPrimal() )
3321  {
3322  maxprimalentry = 0.0;
3323  if ( relaxdata->warmstartprimaltype == 3 )
3324  {
3325  nblocks = SCIPconshdlrGetNConss(SCIPfindConshdlr(scip, "SDP")) + 1; /* +1 for the LP part */
3326  SCIP_CALL( SCIPallocBufferArray(scip, &startXnblocknonz, nblocks) );
3327  SCIP_CALL( SCIPallocBufferArray(scip, &startXrow, nblocks) );
3328  SCIP_CALL( SCIPallocBufferArray(scip, &startXcol, nblocks) );
3329  SCIP_CALL( SCIPallocBufferArray(scip, &startXval, nblocks) );
3330 
3331  /* get amount of memory to allocate for row/col/val from sdpi */
3332  SCIP_CALL( SCIPsdpiGetPrimalNonzeros(relaxdata->sdpi, nblocks, startXnblocknonz) );
3333 
3334  /* allocate memory for different blocks in row/col/val */
3335  for (b = 0; b < nblocks; b++)
3336  {
3337  SCIP_CALL( SCIPallocBufferArray(scip, &startXrow[b], startXnblocknonz[b]) );
3338  SCIP_CALL( SCIPallocBufferArray(scip, &startXcol[b], startXnblocknonz[b]) );
3339  SCIP_CALL( SCIPallocBufferArray(scip, &startXval[b], startXnblocknonz[b]) );
3340  }
3341  SCIP_CALL( SCIPsdpiGetPrimalMatrix(sdpi, nblocks, startXnblocknonz, startXrow, startXcol, startXval) );
3342  }
3343  else
3344  {
3345  nblocks = 0;
3346  maxprimalentry = SCIPsdpiGetMaxPrimalEntry(relaxdata->sdpi);
3347  }
3348  }
3349  else
3350  {
3351  maxprimalentry = 0.0;
3352  nblocks = 0;
3353  }
3354 #ifndef NDEBUG
3355  snprintfreturn = SCIPsnprintf(consname, SCIP_MAXSTRLEN, "saved_relax_sol_%d", SCIPnodeGetNumber(SCIPgetCurrentNode(scip)));
3356  assert( snprintfreturn < SCIP_MAXSTRLEN ); /* check whether name fit into string */
3357 #else
3358  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "saved_relax_sol_%d", SCIPnodeGetNumber(SCIPgetCurrentNode(scip)));
3359 #endif
3360  if ( relaxdata->warmstartpreoptsol )
3361  {
3362  /* only create constraint if the preoptimal solution exists, otherwise we don't want to warmstart at all */
3363  if ( preoptimalsolsuccess )
3364  {
3365  SCIP_CALL( createConsSavesdpsol(scip, &savedcons, consname, SCIPnodeGetNumber(SCIPgetCurrentNode(scip)), preoptimalsol,
3366  maxprimalentry, nblocks, startXnblocknonz, startXrow, startXcol, startXval) );
3367 
3368  SCIP_CALL( SCIPaddCons(scip, savedcons) );
3369  SCIP_CALL( SCIPreleaseCons(scip, &savedcons) );
3370  }
3371  }
3372  else
3373  {
3374  SCIP_CALL( createConsSavesdpsol(scip, &savedcons, consname, SCIPnodeGetNumber(SCIPgetCurrentNode(scip)), scipsol,
3375  maxprimalentry, nblocks, startXnblocknonz, startXrow, startXcol, startXval) );
3376 
3377  SCIP_CALL( SCIPaddCons(scip, savedcons) );
3378  SCIP_CALL( SCIPreleaseCons(scip, &savedcons) );
3379  }
3380 
3381  if ( SCIPsdpiDoesWarmstartNeedPrimal() && relaxdata->warmstartprimaltype == 3 )
3382  {
3383  /* free memory for primal matrix */
3384  if ( startXnblocknonz[0] > 1 ) /* no memory was allocated if computation of preoptimal solution failed */
3385  {
3386  for (b = 0; b < nblocks; b++)
3387  {
3388  assert( startXval != NULL ); /* for lint */
3389  assert( startXcol != NULL ); /* for lint */
3390  assert( startXrow != NULL ); /* for lint */
3391 
3392  SCIPfreeBufferArrayNull(scip, &startXval[b]);
3393  SCIPfreeBufferArrayNull(scip, &startXcol[b]);
3394  SCIPfreeBufferArrayNull(scip, &startXrow[b]);
3395  }
3396  SCIPfreeBufferArrayNull(scip, &startXval);
3397  SCIPfreeBufferArrayNull(scip, &startXcol);
3398  SCIPfreeBufferArrayNull(scip, &startXrow);
3399  }
3400  SCIPfreeBufferArrayNull(scip, &startXnblocknonz);
3401  }
3402  }
3403 
3404  SCIPfreeBufferArray(scip, &solforscip);
3405  SCIP_CALL( SCIPfreeSol(scip, &scipsol) );
3406  if ( preoptimalsolsuccess )
3407  {
3408  SCIP_CALL( SCIPfreeSol(scip, &preoptimalsol) );
3409  }
3410  }
3411  }
3412  else
3413  {
3414  SCIP_Real objlb;
3415 
3416  if ( SCIPsdpiIsTimelimExc(relaxdata->sdpi) )
3417  {
3418  *result = SCIP_DIDNOTRUN;
3419  return SCIP_OKAY;
3420  }
3421 
3422  /* 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
3423  * keep the current bound, if the current bound is -infty, we abort */
3424  objlb = -SCIPinfinity(scip);
3425  SCIP_CALL( SCIPsdpiGetLowerObjbound(relaxdata->sdpi, &objlb) );
3426  if ( ! SCIPisInfinity(scip, objlb) )
3427  {
3428  *lowerbound = objlb;
3429  SCIPdebugMessage("The relaxation could not be solved, using best computed bound from penalty formulation.\n");
3430  }
3431  else if ( ! SCIPisInfinity(scip, -1 * SCIPnodeGetLowerbound(SCIPgetCurrentNode(scip))) )
3432  {
3433  *lowerbound = SCIPnodeGetLowerbound(SCIPgetCurrentNode(scip));
3434  SCIPdebugMessage("The relaxation could not be solved, keeping old bound.\n");
3435  }
3436  else
3437  {
3438  *result = SCIP_SUSPENDED;
3439  SCIPerrorMessage("The relaxation of the root node could not be solved, so there is no hope to solve this instance.\n");
3440  return SCIP_ERROR;
3441  }
3442 
3443  *result = SCIP_SUCCESS;
3444  return SCIP_OKAY;
3445  }
3446 
3447  return SCIP_OKAY;
3448 }
3449 
3451 static
3452 SCIP_Bool allVarsFixed(
3453  SCIP* scip
3454  )
3455 {
3456  SCIP_VAR** vars;
3457  int i;
3458 
3459  assert( scip != NULL );
3460 
3461  vars = SCIPgetVars(scip);
3462 
3463  /* try to find a variable that is not fixed */
3464  for (i = 0; i < SCIPgetNVars(scip); i++)
3465  {
3466  if ( SCIPisLT(scip, SCIPvarGetLbLocal(vars[i]), SCIPvarGetUbLocal(vars[i])) )
3467  return FALSE;
3468  }
3469 
3470  /* if no variable with lower bound strictly lower than upper bound has been found, all variables are fixed */
3471  return TRUE;
3472 }
3473 
3475 static
3476 SCIP_DECL_RELAXEXEC(relaxExecSdp)
3477 {
3478  SCIP_RELAXDATA* relaxdata;
3479  SCIP_VAR** vars;
3480  SCIP_Real* ubs;
3481  SCIP_Bool cutoff;
3482  SCIP_SOL* scipsol; /* TODO: eliminate this */
3483  int nconss;
3484  int nvars;
3485  int i;
3486 #ifdef SCIP_EVEN_MORE_DEBUG
3487  SCIP_VAR** varsfordebug = SCIPgetVars(scip);
3488  const int nvarsfordebug = SCIPgetNVars(scip);
3489 #endif
3490 
3491  SCIPdebugMessage("Calling relaxExecSdp.\n");
3492 
3493  relaxdata = SCIPrelaxGetData(relax);
3494  vars = SCIPgetVars(scip);
3495  nvars = SCIPgetNVars(scip);
3496 
3497  /* set the solved flags to false in case a timeout happens */
3498  relaxdata->origsolved = FALSE;
3499  relaxdata->probingsolved = FALSE;
3500 
3501  /* don't run again if we already solved the current node (except during probing), and we solved the correct problem */
3502  if ( (relaxdata->lastsdpnode == SCIPnodeGetNumber(SCIPgetCurrentNode(scip)) && ( ! SCIPinProbing(scip) ) ) && relaxdata->origsolved && ! relaxdata->resolve )
3503  {
3504  SCIP_COL** cols;
3505  SCIP_Real objforscip;
3506  SCIP_Real* solforscip;
3507  int ncols;
3508  int slength;
3509 
3510  SCIPdebugMessage("Already solved SDP-relaxation for node %ld, returning with SCIP_SUCCESS so that no other relaxator is called.\n",
3511  SCIPrelaxGetData(relax)->lastsdpnode);
3512 
3513  if ( SCIPsdpiIsDualUnbounded(relaxdata->sdpi) )
3514  {
3515  relaxdata->feasible = TRUE;
3516  *result = SCIP_SUCCESS;
3517  *lowerbound = -SCIPinfinity(scip);
3518  return SCIP_OKAY;
3519  }
3520 
3521  /* get solution w.r.t. SCIP variables */
3522  SCIP_CALL( SCIPallocBufferArray(scip, &solforscip, nvars) );
3523  slength = nvars;
3524  SCIP_CALL( SCIPsdpiGetSol(relaxdata->sdpi, &objforscip, solforscip, &slength) ); /* get both the objective and the solution from the SDP solver */
3525 
3526  assert( slength == nvars ); /* If this isn't true any longer, the getSol-Call was unsuccessfull, because the given array wasn't long enough,
3527  * but this can't happen, because the array has enough space for all sdp variables. */
3528 
3529  /* create SCIP solution */
3530  SCIP_CALL( SCIPcreateSol(scip, &scipsol, NULL) );
3531  SCIP_CALL( SCIPsetRelaxSolVals(scip, nvars, vars, solforscip, TRUE) );
3532 
3533  *lowerbound = objforscip;
3534 
3535  /* copy solution */
3536  SCIP_CALL( SCIPgetLPColsData(scip, &cols, &ncols) );
3537  for (i = 0; i < ncols; i++)
3538  {
3539  SCIP_CALL( SCIPsetRelaxSolVal(scip, SCIPcolGetVar(cols[i]), SCIPgetSolVal(scip, scipsol, SCIPcolGetVar(cols[i]))) );
3540  }
3541 
3542  SCIP_CALL( SCIPmarkRelaxSolValid(scip, TRUE) );
3543  *result = SCIP_SUCCESS;
3544 
3545  SCIPfreeBufferArray(scip, &solforscip);
3546  SCIP_CALL( SCIPfreeSol(scip, &scipsol) );
3547 
3548  *result = SCIP_SUCCESS;
3549  return SCIP_OKAY;
3550  }
3551 
3552  /* construct the lp and make sure, that everything is where it should be */
3553  SCIP_CALL( SCIPconstructLP(scip, &cutoff) );
3554 
3555  if ( cutoff )
3556  {
3557  relaxdata->feasible = FALSE;
3558  *result = SCIP_CUTOFF;
3559  return SCIP_OKAY;
3560  }
3561 
3562  /* very important to call flushLP */
3563  SCIP_CALL( SCIPflushLP(scip) );
3564 
3565  /* get varmapper */
3566  nconss = SCIPgetNConss(scip);
3567 
3568 #ifdef SCIP_EVEN_MORE_DEBUG
3569  for (i = 0; i < nvarsfordebug; i++)
3570  {
3571  SCIPdebugMessage("variable %s: status = %u, integral = %u, bounds = [%f, %f] \n", SCIPvarGetName(varsfordebug[i]), SCIPvarGetStatus(varsfordebug[i]),
3572  SCIPvarIsIntegral(varsfordebug[i]), SCIPvarGetLbLocal(varsfordebug[i]), SCIPvarGetUbLocal(varsfordebug[i]));
3573  }
3574 #endif
3575 
3576  if ( nconss == 0 )
3577  {
3578  /* if there are no constraints, there is nothing to do */
3579  relaxdata->feasible = TRUE;
3580  *result = SCIP_DIDNOTRUN;
3581  return SCIP_OKAY;
3582  }
3583 
3584  if ( allVarsFixed(scip) )
3585  {
3586  SCIP_Bool feasible;
3587 
3588  /* if all variables, really all, are fixed, we give this fixed solution to SCIP */
3589 
3590  SCIP_CALL( SCIPallocBufferArray(scip, &ubs, nvars) );
3591 
3592  *lowerbound = 0.0;
3593  for (i = 0; i < nvars; i++)
3594  {
3595  ubs[i] = SCIPvarGetUbLocal(vars[i]);
3596  *lowerbound += SCIPvarGetObj(vars[i]) * ubs[i];
3597  assert( SCIPisFeasEQ(scip, SCIPvarGetUbLocal(vars[i]), SCIPvarGetLbLocal(vars[i])));
3598  }
3599 
3600  SCIPdebugMessage("EVERYTHING IS FIXED, objective value = %f\n", *lowerbound);
3601 
3602  SCIP_CALL( SCIPcreateSol(scip, &scipsol, NULL) );
3603  SCIP_CALL( SCIPsetSolVals(scip, scipsol, nvars, vars, ubs) );
3604 
3605  /* set the relaxation solution */
3606  for (i = 0; i < nvars; i++)
3607  {
3608  SCIP_CALL( SCIPsetRelaxSolVal(scip, vars[i], SCIPvarGetLbLocal(vars[i])) );
3609  }
3610  SCIP_CALL( SCIPmarkRelaxSolValid(scip, TRUE) );
3611 
3612  /* check if the solution really is feasible */
3613  SCIP_CALL( SCIPcheckSol(scip, scipsol, FALSE, TRUE, TRUE, TRUE, TRUE, &feasible) );
3614 
3615  relaxdata->feasible = feasible;
3616 
3617  SCIP_CALL( SCIPfreeSol(scip, &scipsol) );
3618 
3619  SCIPfreeBufferArray(scip, &ubs);
3620 
3621  *result = SCIP_SUCCESS;
3622  return SCIP_OKAY;
3623  }
3624 
3625  /* update LP Data in Interface */
3626  SCIP_CALL( putLpDataInInterface(scip, relaxdata->sdpi, relaxdata->varmapper, TRUE, TRUE) );
3627 
3628  SCIP_CALL( calcRelax(scip, relaxdata, result, lowerbound));
3629 
3630  return SCIP_OKAY;
3631 }
3632 
3633 
3636 static
3637 SCIP_DECL_RELAXINITSOL(relaxInitSolSdp)
3638 {
3639  SCIP_RELAXDATA* relaxdata;
3640  SCIP_RETCODE retcode;
3641  SCIP_VAR** vars;
3642  SCIP_Real gaptol;
3643  SCIP_Real feastol;
3644  SCIP_Real penaltyparam;
3645  SCIP_Real maxpenaltyparam;
3646  int npenaltyincr;
3647  SCIP_Real peninfeasadjust;
3648  SCIP_Bool sdpinfo;
3649  SCIP_Real givenpenaltyparam;
3650  SCIP_Real projminevprimal;
3651  SCIP_Real projminevdual;
3652  SCIP_Real preoptgap;
3653  int nthreads;
3654  int slatercheck;
3655  int nvars;
3656 
3657  assert( relax != NULL );
3658 
3659  relaxdata = SCIPrelaxGetData(relax);
3660  assert( relaxdata != NULL );
3661 
3662  relaxdata->objval = 0.0;
3663  relaxdata->origsolved = FALSE;
3664  relaxdata->probingsolved = FALSE;
3665  relaxdata->sdpcalls = 0;
3666  relaxdata->sdpinterfacecalls = 0;
3667  relaxdata->sdpiterations = 0;
3668  relaxdata->solvedfast = 0;
3669  relaxdata->solvedmedium = 0;
3670  relaxdata->solvedstable = 0;
3671  relaxdata->solvedpenalty = 0;
3672  relaxdata->stablewslater = 0;
3673  relaxdata->unstablewslater = 0;
3674  relaxdata->boundedwslater = 0;
3675  relaxdata->unsolvedwslater = 0;
3676  relaxdata->stablenoslater = 0;
3677  relaxdata->unsolvednoslater = 0;
3678  relaxdata->boundednoslater = 0;
3679  relaxdata->unsolvednoslater = 0;
3680  relaxdata->nslaterholds = 0;
3681  relaxdata->nnoslater = 0;
3682  relaxdata->nslatercheckfailed = 0;
3683  relaxdata->npslaterholds = 0;
3684  relaxdata->npnoslater = 0;
3685  relaxdata->npslatercheckfailed = 0;
3686  relaxdata->ndslaterholds = 0;
3687  relaxdata->ndnoslater = 0;
3688  relaxdata->ndslatercheckfailed = 0;
3689  relaxdata->nslaterinfeasible = 0;
3690  relaxdata->stableinfeasible = 0;
3691  relaxdata->unstableinfeasible = 0;
3692  relaxdata->penaltyinfeasible = 0;
3693  relaxdata->boundedinfeasible = 0;
3694  relaxdata->unsolvedinfeasible = 0;
3695  relaxdata->roundingprobinf = 0;
3696  relaxdata->primalroundfails = 0;
3697  relaxdata->dualroundfails = 0;
3698  relaxdata->roundstartsuccess = 0;
3699  relaxdata->roundingoptimal = 0;
3700  relaxdata->roundingcutoff = 0;
3701  relaxdata->roundingprobtime = 0.0;
3702  relaxdata->unsolved = 0;
3703  relaxdata->feasible = FALSE;
3704 
3705  relaxdata->ipXexists = FALSE;
3706  relaxdata->ipZexists = FALSE;
3707 
3708  nvars = SCIPgetNVars(scip);
3709  vars = SCIPgetVars(scip);
3710 
3711  /* all SCIPvars will be added to this list, and 3/4 seems like a good load factor (java uses this factor) */
3712  SCIP_CALL( SCIPsdpVarmapperCreate(scip, &(relaxdata->varmapper), (int) ceil(1.33 * nvars)) );
3713  SCIP_CALL( SCIPsdpVarmapperAddVars(scip, relaxdata->varmapper, nvars, vars) );
3714 
3715  if ( nvars > 0 )
3716  {
3717  SCIP_CALL( putSdpDataInInterface(scip, relaxdata->sdpi, relaxdata->varmapper, TRUE, FALSE) );
3718  }
3719 
3720  /* set the parameters of the SDP-Solver */
3721  SCIP_CALL( SCIPgetRealParam(scip, "relaxing/SDP/sdpsolvergaptol", &gaptol) );
3722  retcode = SCIPsdpiSetRealpar(relaxdata->sdpi, SCIP_SDPPAR_GAPTOL, gaptol);
3723  if ( retcode == SCIP_PARAMETERUNKNOWN )
3724  {
3725  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL,
3726  "SDP Solver <%s>: gaptol setting not available -- SCIP parameter has no effect.\n",
3728  }
3729  else
3730  {
3731  SCIP_CALL( retcode );
3732  }
3733 
3734  SCIP_CALL( SCIPgetRealParam(scip, "relaxing/SDP/sdpsolverfeastol", &feastol) );
3735  retcode = SCIPsdpiSetRealpar(relaxdata->sdpi, SCIP_SDPPAR_SDPSOLVERFEASTOL, feastol);
3736  if ( retcode == SCIP_PARAMETERUNKNOWN )
3737  {
3738  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL,
3739  "SDP Solver <%s>: sdpsolverfeastol setting not available -- SCIP parameter has no effect.\n",
3741  }
3742  else
3743  {
3744  SCIP_CALL( retcode );
3745  }
3746 
3747  retcode = SCIPsdpiSetRealpar(relaxdata->sdpi, SCIP_SDPPAR_EPSILON, SCIPepsilon(scip));
3748  if ( retcode == SCIP_PARAMETERUNKNOWN )
3749  {
3750  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL,
3751  "SDP Solver <%s>: epsilon setting not available -- SCIP parameter has no effect.\n",
3753  }
3754  else
3755  {
3756  SCIP_CALL( retcode );
3757  }
3758 
3759  retcode = SCIPsdpiSetRealpar(relaxdata->sdpi, SCIP_SDPPAR_FEASTOL, SCIPfeastol(scip));
3760  if ( retcode == SCIP_PARAMETERUNKNOWN )
3761  {
3762  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL,
3763  "SDP Solver <%s>: feastol setting not available -- SCIP parameter has no effect.\n",
3765  }
3766  else
3767  {
3768  SCIP_CALL( retcode );
3769  }
3770 
3771  /* set/compute the starting penalty parameter */
3772  SCIP_CALL( SCIPgetRealParam(scip, "relaxing/SDP/penaltyparam", &penaltyparam) );
3773  if ( SCIPisGE(scip, penaltyparam, 0.0) )
3774  {
3775  retcode = SCIPsdpiSetRealpar(relaxdata->sdpi, SCIP_SDPPAR_PENALTYPARAM, penaltyparam);
3776  givenpenaltyparam = penaltyparam;
3777  if ( retcode == SCIP_PARAMETERUNKNOWN )
3778  {
3779  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL,
3780  "SDP Solver <%s>: penaltyparam setting not available -- SCIP parameter has no effect\n",
3782  }
3783  else
3784  {
3785  SCIP_CALL( retcode );
3786  }
3787  }
3788  else
3789  {
3790  SCIP_Real maxcoeff;
3791  int v;
3792 
3793  /* compute the maximum coefficient in the objective */
3794  maxcoeff = 0.0;
3795  for (v = 0; v < nvars; v++)
3796  {
3797  if ( SCIPisGT(scip, REALABS(SCIPvarGetObj(vars[v])), maxcoeff) )
3798  maxcoeff = REALABS(SCIPvarGetObj(vars[v]));
3799  }
3800 
3801  SCIP_CALL( SCIPsdpiComputePenaltyparam(relaxdata->sdpi, maxcoeff, &givenpenaltyparam) );
3802  }
3803 
3804  /* set/compute the maximum penalty parameter */
3805  SCIP_CALL( SCIPgetRealParam(scip, "relaxing/SDP/maxpenaltyparam", &maxpenaltyparam) );
3806  if ( SCIPisGE(scip, maxpenaltyparam, 0.0) )
3807  {
3808  retcode = SCIPsdpiSetRealpar(relaxdata->sdpi, SCIP_SDPPAR_MAXPENALTYPARAM, maxpenaltyparam);
3809 
3810  if ( retcode == SCIP_PARAMETERUNKNOWN )
3811  {
3812  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL,
3813  "SDP Solver <%s>: maxpenaltyparam setting not available -- SCIP parameter has no effect.\n",
3815  }
3816  else
3817  {
3818  SCIP_CALL( retcode );
3819  }
3820 
3821  /* check if the starting value is not bigger than the maximum one, otherwise update it */
3822  if ( SCIPisLT(scip, givenpenaltyparam, maxpenaltyparam) )
3823  {
3824  SCIPdebugMessage("Penalty parameter %f overwritten by maxpenaltyparam %f! \n", givenpenaltyparam, maxpenaltyparam);
3825  SCIP_CALL( SCIPsdpiSetRealpar(relaxdata->sdpi, SCIP_SDPPAR_PENALTYPARAM, maxpenaltyparam) );
3826  }
3827  }
3828  else
3829  {
3830  SCIP_Real givenmaxpenaltyparam;
3831 
3832  SCIP_CALL( SCIPsdpiComputeMaxPenaltyparam(relaxdata->sdpi, givenpenaltyparam, &givenmaxpenaltyparam) );
3833  }
3834 
3835  /* set maximum number of penalty increasing rounds */
3836  SCIP_CALL( SCIPgetIntParam(scip, "relaxing/SDP/npenaltyincr", &npenaltyincr) );
3837  retcode = SCIPsdpiSetIntpar(relaxdata->sdpi, SCIP_SDPPAR_NPENALTYINCR, npenaltyincr);
3838  if ( retcode == SCIP_PARAMETERUNKNOWN )
3839  {
3840  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL,
3841  "SDP Solver <%s>: npenaltyincr setting not available -- SCIP parameter has no effect.\n",
3843  }
3844  else
3845  {
3846  SCIP_CALL( retcode );
3847  }
3848 
3849  /* set penalty-infeasibility-adjustment */
3850  SCIP_CALL( SCIPgetRealParam(scip, "relaxing/SDP/peninfeasadjust", &peninfeasadjust) );
3851  retcode = SCIPsdpiSetRealpar(relaxdata->sdpi, SCIP_SDPPAR_PENINFEASADJUST, peninfeasadjust);
3852 
3853  if ( retcode == SCIP_PARAMETERUNKNOWN )
3854  {
3855  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL,
3856  "SDP Solver <%s>: peninfeasadjust setting not available -- SCIP parameter has no effect.\n",
3858  }
3859  else
3860  {
3861  SCIP_CALL( retcode );
3862  }
3863 
3864 
3865  /* set/compute lambda star if SDPA is used as the SDP-Solver */
3866  if ( strcmp(SCIPsdpiGetSolverName(), "SDPA") == 0.0 )
3867  {
3868  SCIP_Real lambdastar;
3869 
3870  SCIP_CALL( SCIPgetRealParam(scip, "relaxing/SDP/lambdastar", &lambdastar) );
3871  if ( SCIPisGE(scip, lambdastar, 0.0) )
3872  {
3873  retcode = SCIPsdpiSetRealpar(relaxdata->sdpi, SCIP_SDPPAR_LAMBDASTAR, lambdastar);
3874  }
3875  else
3876  {
3877  SCIP_Real guess;
3878  SCIP_Real maxguess;
3879  SCIP_CONS** conss;
3880  int nconss;
3881  int c;
3882 
3883  /* iterate over all SDP-constraints to compute the biggest guess for lambdastar */
3884  conss = SCIPgetConss(scip);
3885  nconss = SCIPgetNConss(scip);
3886  maxguess = 0.0;
3887 
3888  for (c = 0; c < nconss; c++)
3889  {
3890  /* only check the SDP constraints */
3891  if ( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(conss[c])), "SDP") == 0 )
3892  {
3893  SCIP_CALL( SCIPconsSdpGuessInitialPoint(scip, conss[c], &guess) );
3894  if ( (! SCIPisInfinity(scip, maxguess) ) && SCIPisGT(scip, guess, maxguess) )
3895  maxguess = guess;
3896  }
3897  }
3898 
3899  SCIP_CALL( SCIPsdpiComputeLambdastar(relaxdata->sdpi, maxguess) );
3900  retcode = SCIPsdpiGetRealpar(relaxdata->sdpi, SCIP_SDPPAR_LAMBDASTAR, &relaxdata->lambdastar);
3901  }
3902  }
3903  else
3904  relaxdata->lambdastar = 1.0;
3905 
3906  if ( retcode == SCIP_PARAMETERUNKNOWN )
3907  {
3908  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL,
3909  "SDP Solver <%s>: lambdastar setting not available -- SCIP parameter has no effect.\n",
3911  }
3912  else
3913  {
3914  SCIP_CALL( retcode );
3915  }
3916 
3917  /* set/compute minimum eigenvalue for projecting warmstarting points */
3918  SCIP_CALL( SCIPgetRealParam(scip, "relaxing/SDP/warmstartprminevpri", &projminevprimal) );
3919  SCIP_CALL( SCIPgetRealParam(scip, "relaxing/SDP/warmstartprminevdu", &projminevdual) );
3920 
3921  if ( SCIPisGE(scip, projminevprimal, 0.0) && SCIPisGE(scip, projminevdual, 0.0) ) /* TODO: maybe only do these computations if warmstart = TRUE? */
3922  {
3923  relaxdata->warmstartprojminevprimal = projminevprimal;
3924  relaxdata->warmstartprojminevdual = projminevdual;
3925  }
3926  else if ( SCIPisGE(scip, projminevprimal, 0.0) && relaxdata->warmstartprojpdsame )
3927  {
3928  relaxdata->warmstartprojminevprimal = projminevprimal;
3929  relaxdata->warmstartprojminevdual = projminevprimal;
3930  }
3931  else if ( SCIPisGE(scip, projminevdual, 0.0) && relaxdata->warmstartprojpdsame )
3932  {
3933  relaxdata->warmstartprojminevprimal = projminevdual;
3934  relaxdata->warmstartprojminevdual = projminevdual;
3935  }
3936  else
3937  {
3938  SCIP_CONSHDLR* sdpconshdlr;
3939  SCIP_CONS** sdpblocks;
3940  int nsdpblocks;
3941  int b;
3942  int v;
3943  SCIP_Real maxsdprhs; /* note that we only take the maximum value of the SDP constraints, since these tend to be the most problematic */
3944  SCIP_Real maxobj;
3945  SCIP_Real maxsdpcoef; /* note that we only take the maximum value of the SDP constraints, since these tend to be the most problematic */
3946  SCIP_Real maxval;
3947  SCIP_Real sdpcoef;
3948 
3949  /* compute value as WARMSTART_PROJ_FACTOR * max{maxrhs, maxobj, maxsdpcoef} */
3950  sdpconshdlr = SCIPfindConshdlr(scip, "SDP");
3951  nsdpblocks = SCIPconshdlrGetNConss(sdpconshdlr);
3952  sdpblocks = SCIPconshdlrGetConss(sdpconshdlr);
3953 
3954  /* compute maxsdpcoef */
3955  maxsdpcoef = WARMSTART_PROJ_MINRHSOBJ;
3956  for (b = 0; b < nsdpblocks; b++)
3957  {
3958  sdpcoef = SCIPconsSdpGetMaxSdpCoef(scip, sdpblocks[b]);
3959  if ( SCIPisGT(scip, sdpcoef, maxsdpcoef) )
3960  maxsdpcoef = sdpcoef;
3961  }
3962  maxsdpcoef *= WARMSTART_PROJ_FACTOR_LHS; /* multiply by additional factor to account for summation of lhs entries */
3963 
3964  /* compute maxsdprhs */
3965  maxsdprhs = WARMSTART_PROJ_MINRHSOBJ;
3966  for (b = 0; b < nsdpblocks; b++)
3967  {
3968  if ( SCIPisGT(scip, SCIPconsSdpGetMaxConstEntry(scip, sdpblocks[b]), maxsdprhs) )
3969  maxsdprhs = SCIPconsSdpGetMaxConstEntry(scip, sdpblocks[b]);
3970  }
3971 
3972  /* compute maxobj */
3973  maxobj = WARMSTART_PROJ_MINRHSOBJ;
3974  for (v = 0; v < nvars; v++)
3975  {
3976  if ( SCIPisGT(scip, REALABS(SCIPvarGetObj(vars[v])), maxobj) )
3977  maxobj = REALABS(SCIPvarGetObj(vars[v]));
3978  }
3979 
3980  if ( relaxdata->warmstartprojpdsame )
3981  {
3982  maxval = SCIPisGT(scip, maxsdprhs, maxobj) ? maxsdprhs : maxobj;
3983  maxval = SCIPisGT(scip, maxsdpcoef, maxval) ? maxsdpcoef : maxval;
3984 
3985  relaxdata->warmstartprojminevprimal = WARMSTART_PROJ_FACTOR * maxval;
3986  relaxdata->warmstartprojminevdual = WARMSTART_PROJ_FACTOR * maxval;
3987 
3988  SCIPdebugMsg(scip, "Setting warmstartprojminev to %f\n", relaxdata->warmstartprojminevdual);
3989  }
3990  else
3991  {
3992  if ( ! SCIPisGE(scip, projminevprimal, 0.0) )
3993  {
3994  relaxdata->warmstartprojminevprimal = WARMSTART_PROJ_FACTOR_PRIMAL * (SCIPisGT(scip, maxobj, maxsdpcoef) ? maxobj : maxsdpcoef);
3995 
3996  SCIPdebugMsg(scip, "Setting warmstartprojminevprimal to %f\n", relaxdata->warmstartprojminevprimal);
3997  }
3998 
3999  if ( ! SCIPisGE(scip, projminevdual, 0.0) )
4000  {
4001  relaxdata->warmstartprojminevdual = WARMSTART_PROJ_FACTOR_PRIMAL * (SCIPisGT(scip, maxsdprhs, maxsdpcoef) ? maxsdprhs : maxsdpcoef);
4002 
4003  SCIPdebugMsg(scip, "Setting warmstartprojminevdual to %f\n", relaxdata->warmstartprojminevdual);
4004  }
4005  }
4006  }
4007 
4008  SCIP_CALL( SCIPgetBoolParam(scip, "relaxing/SDP/sdpinfo", &sdpinfo) );
4009  retcode = SCIPsdpiSetIntpar(relaxdata->sdpi, SCIP_SDPPAR_SDPINFO, (int) sdpinfo);
4010  if ( retcode == SCIP_PARAMETERUNKNOWN )
4011  {
4012  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL,
4013  "SDP Solver <%s>: sdpinfo setting not available -- SCIP parameter has no effect.\n",
4015  }
4016  else
4017  {
4018  SCIP_CALL( retcode );
4019  }
4020 
4021  SCIP_CALL( SCIPgetIntParam(scip, "relaxing/SDP/sdpsolverthreads", &nthreads) );
4022  /* only try to set nthreads if the value differs from the default to prevent unnecessary warning messages for unknown parameter */
4023  if ( nthreads != DEFAULT_SDPSOLVERTHREADS )
4024  {
4025  retcode = SCIPsdpiSetIntpar(relaxdata->sdpi, SCIP_SDPPAR_NTHREADS, nthreads);
4026  if ( retcode == SCIP_PARAMETERUNKNOWN )
4027  {
4028  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL,
4029  "SDP Solver <%s>: nthreads setting not available -- SCIP parameter has no effect.\n",
4031  }
4032  else
4033  {
4034  SCIP_CALL( retcode );
4035  }
4036  }
4037 
4038  SCIP_CALL( SCIPgetIntParam(scip, "relaxing/SDP/slatercheck", &slatercheck) );
4039  retcode = SCIPsdpiSetIntpar(relaxdata->sdpi, SCIP_SDPPAR_SLATERCHECK, slatercheck);
4040  if ( retcode == SCIP_PARAMETERUNKNOWN )
4041  {
4042  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL,
4043  "SDP Solver <%s>: slatercheck setting not available -- SCIP parameter has no effect.\n",
4045  }
4046  else
4047  {
4048  SCIP_CALL( retcode );
4049  }
4050 
4051  /* initialize objective limit in case it was set in an earlier optimize call */
4052  SCIP_CALL( SCIPsdpiSetRealpar(relaxdata->sdpi, SCIP_SDPPAR_OBJLIMIT, SCIPsdpiInfinity(relaxdata->sdpi)) );
4053 
4054  /* set warmstartpreoptimal gap if DSDP is used as the SDP-Solver and preoptimal solutions should be saved */
4055  if ( relaxdata->warmstartpreoptsol && (strcmp(SCIPsdpiGetSolverName(), "DSDP") == 0.0 || strcmp(SCIPsdpiGetSolverName(), "SDPA") == 0.0) )
4056  {
4057  SCIP_CALL( SCIPgetRealParam(scip, "relaxing/SDP/warmstartpreoptgap", &preoptgap) );
4058  retcode = SCIPsdpiSetRealpar(relaxdata->sdpi, SCIP_SDPPAR_WARMSTARTPOGAP, preoptgap);
4059  if ( retcode == SCIP_PARAMETERUNKNOWN )
4060  {
4061  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL,
4062  "SDP Solver <%s>: warmstartpreoptgap setting not available -- SCIP parameter has no effect.\n",
4064  }
4065  else
4066  {
4067  SCIP_CALL( retcode );
4068  }
4069  }
4070 
4071  return SCIP_OKAY;
4072 }
4073 
4075 static
4076 SCIP_DECL_RELAXCOPY(relaxCopySdp)
4077 {
4078  assert( scip != NULL );
4079  assert( relax != NULL );
4080  assert( strcmp(SCIPrelaxGetName(relax), RELAX_NAME) == 0 );
4081 
4082  SCIP_CALL( SCIPincludeRelaxSdp(scip) );
4083 
4084  return SCIP_OKAY;
4085 }
4086 
4088 static
4089 SCIP_DECL_RELAXEXITSOL(relaxExitSolSdp)
4090 {
4091  SCIP_RELAXDATA* relaxdata;
4092 
4093  assert( scip != NULL );
4094  assert( relax != NULL );
4095 
4096  relaxdata = SCIPrelaxGetData(relax);
4097  assert( relaxdata != NULL );
4098 
4099  SCIPdebugMessage("Exiting Relaxation Handler.\n");
4100 
4101  if ( relaxdata->displaystat && SCIPgetSubscipDepth(scip) == 0 )
4102  {
4103  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "\nSDP iterations:\t\t\t\t%6d\n", relaxdata->sdpiterations);
4104  if ( relaxdata->sdpcalls )
4105  {
4106  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Average SDP-iterations:\t\t\t%6.2f \n", (SCIP_Real) relaxdata->sdpiterations / (SCIP_Real) relaxdata->sdpcalls );
4107  }
4108  if ( relaxdata->sdpinterfacecalls )
4109  {
4110  if ( strcmp(SCIPsdpiGetSolverName(), "SDPA") == 0 )
4111  {
4112  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'fastest settings' solved:\t%6.2f \n", 100.0 * (SCIP_Real) relaxdata->solvedfast / (SCIP_Real) relaxdata->sdpinterfacecalls);
4113  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'medium settings' solved:\t%6.2f \n", 100.0 * (SCIP_Real) relaxdata->solvedmedium / (SCIP_Real) relaxdata->sdpinterfacecalls);
4114  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'stable settings' solved:\t%6.2f \n", 100.0 * (SCIP_Real) relaxdata->solvedstable / (SCIP_Real) relaxdata->sdpinterfacecalls);
4115  }
4116  else
4117  {
4118  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'default formulation' solved:\t%6.2f \n", 100.0 * (SCIP_Real) relaxdata->solvedfast / (SCIP_Real) relaxdata->sdpinterfacecalls);
4119  }
4120  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage penalty formulation used:\t%6.2f \n", 100.0 * (SCIP_Real) relaxdata->solvedpenalty / (SCIP_Real) relaxdata->sdpinterfacecalls);
4121  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);
4122  }
4123  if ( relaxdata->slatercheck )
4124  {
4125  if ( relaxdata->sdpinterfacecalls )
4126  {
4127  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);
4128  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);
4129  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);
4130 
4131  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);
4132  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);
4133  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);
4134  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);
4135  }
4136  if ( relaxdata->nslaterholds )
4137  {
4138  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'fastest settings' with primal and dual slater holding:\t%6.2f \n",
4139  100.0 * (SCIP_Real) relaxdata->stablewslater / (SCIP_Real) relaxdata->nslaterholds);
4140  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'stable settings' with primal and dual slater holding:\t%6.2f \n",
4141  100.0 * (SCIP_Real) relaxdata->unstablewslater / (SCIP_Real) relaxdata->nslaterholds);
4142  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'penalty' with primal and dual slater holding:\t%6.2f \n",
4143  100.0 * (SCIP_Real) relaxdata->penaltywslater / (SCIP_Real) relaxdata->nslaterholds);
4144  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'computed infeasible lower bound' with primal and dual slater holding:\t%6.2f \n",
4145  100.0 * (SCIP_Real) relaxdata->boundedwslater / (SCIP_Real) relaxdata->nslaterholds);
4146  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'unsolved' with primal and dual slater holding:\t%6.2f \n",
4147  100.0 * (SCIP_Real) relaxdata->unsolvedwslater / (SCIP_Real) relaxdata->nslaterholds);
4148  }
4149  if ( relaxdata->nnoslater )
4150  {
4151  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'fastest settings' with either primal or dual slater not holding:\t%6.2f \n",
4152  100.0 * (SCIP_Real) relaxdata->stablenoslater / (SCIP_Real) relaxdata->nnoslater);
4153  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'stable settings' with either primal or dual slater not holding:\t%6.2f \n",
4154  100.0 * (SCIP_Real) relaxdata->unstablenoslater / (SCIP_Real) relaxdata->nnoslater);
4155  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'penalty' with either primal or dual slater not holding:\t%6.2f \n",
4156  100.0 * (SCIP_Real) relaxdata->penaltynoslater / (SCIP_Real) relaxdata->nnoslater);
4157  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'computed infeasible lower bound' with either primal or dual slater not holding:\t%6.2f \n",
4158  100.0 * (SCIP_Real) relaxdata->boundednoslater / (SCIP_Real) relaxdata->nnoslater);
4159  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'unsolved' with either primal or dual slater not holding:\t%6.2f \n",
4160  100.0 * (SCIP_Real) relaxdata->unsolvednoslater / (SCIP_Real) relaxdata->nnoslater);
4161  }
4162  if ( relaxdata->nslaterinfeasible )
4163  {
4164  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'fastest settings' with slater check showing infeasibility:\t%6.2f \n",
4165  100.0 * (SCIP_Real) relaxdata->stableinfeasible / (SCIP_Real) relaxdata->nslaterinfeasible);
4166  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'stable settings' with slater check showing infeasibility:\t%6.2f \n",
4167  100.0 * (SCIP_Real) relaxdata->unstableinfeasible / (SCIP_Real) relaxdata->nslaterinfeasible);
4168  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'penalty' with slater check showing infeasibility:\t%6.2f \n",
4169  100.0 * (SCIP_Real) relaxdata->penaltyinfeasible / (SCIP_Real) relaxdata->nslaterinfeasible);
4170  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'computed infeasible lower bound' with slater check showing infeasibility:\t%6.2f \n",
4171  100.0 * (SCIP_Real) relaxdata->boundedinfeasible / (SCIP_Real) relaxdata->nslaterinfeasible);
4172  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Percentage 'unsolved' with slater check showing infeasibility:\t%6.2f \n",
4173  100.0 * (SCIP_Real) relaxdata->unsolvedinfeasible / (SCIP_Real) relaxdata->nslaterinfeasible);
4174  }
4175 #ifdef SLATERSOLVED_ABSOLUTE
4176  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes with primal and dual slater holding:\t%d \n", relaxdata->nslaterholds);
4177  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes with 'fastest settings' and primal and dual slater holding:\t%d \n", relaxdata->stablewslater);
4178  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes with 'stable settings' and primal and dual slater holding:\t%d \n", relaxdata->unstablewslater);
4179  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes with 'penalty' and primal and dual slater holding:\t%d \n", relaxdata->penaltywslater);
4180  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);
4181  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes with 'unsolved' and primal and dual slater holding:\t%d \n", relaxdata->unsolvedwslater);
4182 
4183  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes with either primal or dual slater not holding:\t%d \n", relaxdata->nnoslater);
4184  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);
4185  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);
4186  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes with 'penalty' and either primal or dual slater not holding:\t%d \n", relaxdata->penaltynoslater);
4187  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);
4188  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes with 'unsolved' and either primal or dual slater not holding:\t%d \n", relaxdata->unsolvednoslater);
4189 
4190  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of infeasible nodes:\t%d \n", relaxdata->nslaterinfeasible);
4191  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of infeasible nodes with 'fastest settings':\t%d \n", relaxdata->stableinfeasible);
4192  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of infeasible nodes with 'stable settings':\t%d \n", relaxdata->unstableinfeasible);
4193  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of infeasible nodes with 'penalty':\t%d \n", relaxdata->penaltyinfeasible);
4194  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of infeasible nodes with 'computed infeasible lower bound':\t%d \n", relaxdata->boundedinfeasible);
4195  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of infeasible nodes with 'unsolved':\t%d \n", relaxdata->unsolvedinfeasible);
4196 #endif
4197  }
4198  if ( relaxdata->warmstart && relaxdata->warmstartproject == 4 )
4199  {
4200  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes detected infeasible through primal rounding problem:\t%d \n", relaxdata->roundingprobinf);
4201  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes that were successfully warmstarted using the rounding problems:\t%d \n", relaxdata->roundstartsuccess);
4202  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes where the primal rounding problem failed:\t%d \n", relaxdata->primalroundfails);
4203  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes where the dual rounding problem failed:\t%d \n", relaxdata->dualroundfails);
4204  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes where the optimal solution was determined by the rounding problem:\t%d \n", relaxdata->roundingoptimal);
4205  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Number of nodes cut off through bounding by the rounding problem:\t%d \n", relaxdata->roundingcutoff);
4206  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Time spent in rounding problems for warmstarting / detecting infeasibility:\t%f s \n", relaxdata->roundingprobtime);
4207  }
4208  }
4209 
4210  if ( relaxdata->varmapper != NULL )
4211  {
4212  SCIP_CALL( SCIPsdpVarmapperFree(scip, &(relaxdata->varmapper)) );
4213  relaxdata->varmapper = NULL;
4214  }
4215 
4216  /* free warmstart data (the nblocks > 0 check is only needed in case the parameter was changed after initsol) */
4217  if ( relaxdata->warmstart && SCIPisGT(scip, relaxdata->warmstartipfactor, 0.0) && relaxdata->nblocks > 0 )
4218  {
4219  int b;
4220 
4221  for (b = 0; b < relaxdata->nblocks; b++)
4222  {
4223  if ( relaxdata->warmstartprimaltype != 2 && SCIPsdpiDoesWarmstartNeedPrimal() && relaxdata->ipXnblocknonz[b] > 0 )
4224  {
4225  SCIPfreeBlockMemoryArrayNull(scip, &(relaxdata->ipXval[b]), relaxdata->ipXnblocknonz[b]);
4226  SCIPfreeBlockMemoryArrayNull(scip, &(relaxdata->ipXcol[b]), relaxdata->ipXnblocknonz[b]);
4227  SCIPfreeBlockMemoryArrayNull(scip, &(relaxdata->ipXrow[b]), relaxdata->ipXnblocknonz[b]);
4228  }
4229  if ( relaxdata->ipZnblocknonz[b] > 0 )
4230  {
4231  SCIPfreeBlockMemoryArrayNull(scip, &(relaxdata->ipZval[b]), relaxdata->ipZnblocknonz[b]);
4232  SCIPfreeBlockMemoryArrayNull(scip, &(relaxdata->ipZcol[b]), relaxdata->ipZnblocknonz[b]);
4233  SCIPfreeBlockMemoryArrayNull(scip, &(relaxdata->ipZrow[b]), relaxdata->ipZnblocknonz[b]);
4234  }
4235  }
4236  if ( relaxdata->warmstartprimaltype != 2 && SCIPsdpiDoesWarmstartNeedPrimal() )
4237  {
4238  SCIPfreeBlockMemoryArrayNull(scip, &relaxdata->ipXval, relaxdata->nblocks);
4239  SCIPfreeBlockMemoryArrayNull(scip, &relaxdata->ipXcol, relaxdata->nblocks);
4240  SCIPfreeBlockMemoryArrayNull(scip, &relaxdata->ipXrow, relaxdata->nblocks);
4241  SCIPfreeBlockMemoryArrayNull(scip, &relaxdata->ipXnblocknonz, relaxdata->nblocks);
4242  }
4243  SCIPfreeBlockMemoryArrayNull(scip, &relaxdata->ipZval, relaxdata->nblocks);
4244  SCIPfreeBlockMemoryArrayNull(scip, &relaxdata->ipZcol, relaxdata->nblocks);
4245  SCIPfreeBlockMemoryArrayNull(scip, &relaxdata->ipZrow, relaxdata->nblocks);
4246  SCIPfreeBlockMemoryArrayNull(scip, &relaxdata->ipZnblocknonz, relaxdata->nblocks);
4247  SCIP_CALL( SCIPfreeSol(scip, &relaxdata->ipy) );
4248  }
4249 
4250  relaxdata->objval = 0.0;
4251  relaxdata->origsolved = FALSE;
4252  relaxdata->probingsolved = FALSE;
4253  relaxdata->feasible = FALSE;
4254  relaxdata->sdpiterations = 0;
4255  relaxdata->sdpcalls = 0;
4256  relaxdata->sdpinterfacecalls = 0;
4257  relaxdata->lastsdpnode = 0;
4258  relaxdata->unsolved = 0;
4259  SCIP_CALL( SCIPsdpiClear(relaxdata->sdpi) );
4260 
4261  return SCIP_OKAY;
4262 }
4263 
4265 static
4266 SCIP_DECL_RELAXFREE(relaxFreeSdp)
4267 {/*lint --e{715}*/
4268  SCIP_RELAXDATA* relaxdata;
4269 
4270  relaxdata = SCIPrelaxGetData(relax);
4271  assert(relaxdata != NULL);
4272 
4273  if ( relaxdata->sdpi != NULL )
4274  {
4275  SCIP_CALL( SCIPsdpiFree(&(relaxdata->sdpi)) );
4276  }
4277  if ( relaxdata->lpi != NULL )
4278  {
4279  SCIP_CALL( SCIPlpiFree(&(relaxdata->lpi)) );
4280  }
4281 
4282  SCIPfreeMemory(scip, &relaxdata);
4283 
4284  SCIPrelaxSetData(relax, NULL);
4285 
4286  return SCIP_OKAY;
4287 }
4288 
4290 SCIP_RETCODE SCIPincludeRelaxSdp(
4291  SCIP* scip
4292  )
4293 {
4294  SCIP_RELAXDATA* relaxdata = NULL;
4295  SCIP_RELAX* relax;
4296  SCIP_SDPI* sdpi;
4297  SCIP_LPI* lpi;
4298 
4299  assert( scip != NULL );
4300 
4301  /* create SDP-relaxator data */
4302  SCIP_CALL( SCIPallocMemory(scip, &relaxdata) );
4303  SCIP_CALL( SCIPsdpiCreate(&sdpi, SCIPgetMessagehdlr(scip), SCIPblkmem(scip), SCIPbuffer(scip)) );
4304  SCIP_CALL( SCIPlpiCreate(&lpi, SCIPgetMessagehdlr(scip), "SDProundingProb", SCIP_OBJSEN_MINIMIZE) );
4305 
4306  relaxdata->sdpi = sdpi;
4307  relaxdata->lpi = lpi;
4308  relaxdata->lastsdpnode = -1;
4309  relaxdata->nblocks = 0;
4310  relaxdata->varmapper = NULL;
4311 
4312  /* include relaxator */
4313  SCIP_CALL( SCIPincludeRelaxBasic(scip, &relax, RELAX_NAME, RELAX_DESC, RELAX_PRIORITY, RELAX_FREQ, relaxExecSdp, relaxdata) );
4314  assert( relax != NULL );
4315 
4316  /* include additional callbacks */
4317  SCIP_CALL( SCIPsetRelaxInitsol(scip, relax, relaxInitSolSdp) );
4318  SCIP_CALL( SCIPsetRelaxExitsol(scip, relax, relaxExitSolSdp) );
4319  SCIP_CALL( SCIPsetRelaxFree(scip, relax, relaxFreeSdp) );
4320  SCIP_CALL( SCIPsetRelaxCopy(scip, relax, relaxCopySdp) );
4321 
4322  /* add parameters for SDP-solver */
4323  SCIP_CALL( SCIPaddRealParam(scip, "relaxing/SDP/sdpsolvergaptol",
4324  "the stopping criterion for the duality gap the sdpsolver should use",
4325  &(relaxdata->sdpsolvergaptol), TRUE, SCIPsdpiGetDefaultSdpiSolverGaptol(), 1e-20, 0.001, NULL, NULL) );
4326 
4327  SCIP_CALL( SCIPaddRealParam(scip, "relaxing/SDP/sdpsolverfeastol",
4328  "the feasibility tolerance for the SDP solver",
4329  &(relaxdata->sdpsolverfeastol), TRUE, SCIPsdpiGetDefaultSdpiSolverFeastol(), 1e-17, 0.001, NULL, NULL) );
4330 
4331  SCIP_CALL( SCIPaddRealParam(scip, "relaxing/SDP/penaltyparam",
4332  "the starting value of the penalty parameter Gamma used for the penalty formulation if the "
4333  "SDP solver didn't converge; set this to a negative value to compute the parameter depending on the given problem", &(relaxdata->penaltyparam),
4334  TRUE, DEFAULT_PENALTYPARAM, -1.0, 1e+20, NULL, NULL) );
4335 
4336  SCIP_CALL( SCIPaddRealParam(scip, "relaxing/SDP/maxpenaltyparam",
4337  "the maximum value of the penalty parameter Gamma used for the penalty formulation if the "
4338  "SDP solver didn't converge; set this to a negative value to compute the parameter depending on the given problem", &(relaxdata->maxpenaltyparam),
4339  TRUE, DEFAULT_MAXPENALTYPARAM, -1.0, 1e+20, NULL, NULL) );
4340 
4341  SCIP_CALL( SCIPaddRealParam(scip, "relaxing/SDP/peninfeasadjust",
4342  "gap- or feastol will be multiplied by this before checking for infeasibility using the penalty formulation", &(relaxdata->peninfeasadjust),
4343  TRUE, DEFAULT_PENINFEASADJUST, 0.0, 1e+20, NULL, NULL) );
4344 
4345  SCIP_CALL( SCIPaddRealParam(scip, "relaxing/SDP/warmstartipfactor",
4346  "factor for interior point in convexcombination of IP and parent solution, if warmstarts are enabled", &(relaxdata->warmstartipfactor),
4347  TRUE, DEFAULT_WARMSTARTIPFACTOR, 0.0, 1.0, NULL, NULL) );
4348 
4349  SCIP_CALL( SCIPaddIntParam(scip, "relaxing/SDP/warmstartprimaltype",
4350  "how to warmstart the primal problem? 1: scaled identity/analytic center, 2: elementwise reciprocal, 3: saved primal sol", &(relaxdata->warmstartprimaltype), TRUE,
4351  DEFAULT_WARMSTARTPRIMALTYPE, 1, 3, NULL, NULL) );
4352 
4353  SCIP_CALL( SCIPaddIntParam(scip, "relaxing/SDP/warmstartiptype",
4354  "which interior point to use for convex combination for warmstarts? 1: scaled identity, 2: analytic center", &(relaxdata->warmstartiptype), TRUE,
4355  DEFAULT_WARMSTARTIPTYPE, 1, 2, NULL, NULL) );
4356 
4357  SCIP_CALL( SCIPaddIntParam(scip, "relaxing/SDP/warmstartproject",
4358  "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,
4359  DEFAULT_WARMSTARTPROJECT, 1, 4, NULL, NULL) );
4360 
4361  SCIP_CALL( SCIPaddRealParam(scip, "relaxing/SDP/warmstartprminevpri",
4362  "minimum eigenvalue to allow when projecting primal matrices onto the positive (semi-)definite cone for warmstarting; -1 to compute automatically", &(relaxdata->warmstartpmevprimalpar),
4363  TRUE, DEFAULT_WARMSTARTPROJMINEV, -1.0, 1e+20, NULL, NULL) );
4364 
4365  SCIP_CALL( SCIPaddRealParam(scip, "relaxing/SDP/warmstartprminevdu",
4366  "minimum eigenvalue to allow when projecting dual matrices onto the positive (semi-)definite cone for warmstarting; -1 to compute automatically", &(relaxdata->warmstartpmevdualpar),
4367  TRUE, DEFAULT_WARMSTARTPROJMINEV, -1.0, 1e+20, NULL, NULL) );
4368 
4369  SCIP_CALL( SCIPaddBoolParam(scip, "relaxing/SDP/warmstartprojpdsame",
4370  "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 ?",
4371  &(relaxdata->warmstartprojpdsame), TRUE, DEFAULT_WARMSTARTPROJPDSAME, NULL, NULL) );
4372 
4373  SCIP_CALL( SCIPaddBoolParam(scip, "relaxing/SDP/warmstartpreoptsol",
4374  "Should a preoptimal solution (with larger gap) instead of the optimal solution be used for warmstarts",
4375  &(relaxdata->warmstartpreoptsol), TRUE, DEFAULT_WARMSTART_PREOPTIMAL_SOL, NULL, NULL) );
4376 
4377  SCIP_CALL( SCIPaddRealParam(scip, "relaxing/SDP/warmstartpreoptgap",
4378  "If warmstartpreoptsol is TRUE, this is the gap where the preoptimal solution will be saved", &(relaxdata->warmstartpreoptgap),
4379  TRUE, DEFAULT_WARMSTARTPREOPTGAP, 0.0, 1e+20, NULL, NULL) );
4380 
4381  SCIP_CALL( SCIPaddBoolParam(scip, "relaxing/SDP/warmstartroundonlyinf",
4382  "Only use solution of roundingproblem to detect infeasibility (only has an effect for warmstartproject = 4)",
4383  &(relaxdata->warmstartroundonlyinf), TRUE, DEFAULT_WARMSTARTROUNDONLYINF, NULL, NULL) );
4384 
4385  SCIP_CALL( SCIPaddIntParam(scip, "relaxing/SDP/npenaltyincr",
4386  "maximum number of times the penalty parameter will be increased if the penalty formulation failed", &(relaxdata->npenaltyincr), TRUE,
4387  SCIPsdpiGetDefaultSdpiSolverNpenaltyIncreases(), 0, INT_MAX, NULL, NULL) );
4388 
4389  SCIP_CALL( SCIPaddRealParam(scip, "relaxing/SDP/lambdastar",
4390  "the parameter lambda star used by SDPA to set the initial point;"
4391  "set this to a negative value to compute the parameter depending on the given problem", &(relaxdata->lambdastar),
4392  TRUE, DEFAULT_LAMBDASTAR, -1.0, 1e+20, NULL, NULL) );
4393 
4394  SCIP_CALL( SCIPaddIntParam(scip, "relaxing/SDP/slatercheck",
4395  "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 "
4396  "every problem not satisfying primal and dual Slater condition", &(relaxdata->slatercheck), TRUE, DEFAULT_SLATERCHECK, 0, 2, NULL, NULL) );
4397 
4398  SCIP_CALL( SCIPaddBoolParam(scip, "relaxing/SDP/sdpinfo",
4399  "Should the SDP solver output information to the screen?",
4400  &(relaxdata->sdpinfo), TRUE, DEFAULT_SDPINFO, NULL, NULL) );
4401 
4402  SCIP_CALL( SCIPaddBoolParam(scip, "relaxing/SDP/warmstart",
4403  "Should the SDP solver try to use warmstarts?",
4404  &(relaxdata->warmstart), TRUE, DEFAULT_WARMSTART, NULL, NULL) );
4405 
4406  SCIP_CALL( SCIPaddBoolParam(scip, "relaxing/SDP/objlimit",
4407  "Should an objective limit be given to the SDP-Solver?",
4408  &(relaxdata->objlimit), TRUE, DEFAULT_OBJLIMIT, NULL, NULL) );
4409 
4410  SCIP_CALL( SCIPaddBoolParam(scip, "relaxing/SDP/resolve",
4411  "Should the relaxation be resolved after bound-tightenings were found during propagation (outside of probing)?",
4412  &(relaxdata->resolve), TRUE, DEFAULT_RESOLVE, NULL, NULL) );
4413 
4414  SCIP_CALL( SCIPaddBoolParam(scip, "relaxing/SDP/tightenvb",
4415  "Should Big-Ms in varbound-like constraints be tightened before giving them to the SDP-solver ?",
4416  &(relaxdata->tightenvb), TRUE, DEFAULT_TIGHTENVB, NULL, NULL) );
4417 
4418  SCIP_CALL( SCIPaddBoolParam(scip, "relaxing/SDP/displaystatistics",
4419  "Should statistics about SDP iterations and solver settings/success be printed after quitting SCIP-SDP ?",
4420  &(relaxdata->displaystat), TRUE, DEFAULT_DISPLAYSTAT, NULL, NULL) );
4421 
4422  SCIP_CALL( SCIPaddIntParam(scip, "relaxing/SDP/settingsresetfreq",
4423  "frequency for resetting parameters in SDP solver and trying again with fastest settings (-1: never, 0: only at depth settingsresetofs);"
4424  "currently only supported for SDPA",
4425  &(relaxdata->settingsresetfreq), TRUE, DEFAULT_SETTINGSRESETFREQ, -1, INT_MAX, NULL, NULL) );
4426 
4427  SCIP_CALL( SCIPaddIntParam(scip, "relaxing/SDP/settingsresetofs",
4428  "frequency offset for resetting parameters in SDP solver and trying again with fastest settings; currently only supported for SDPA",
4429  &(relaxdata->settingsresetofs), TRUE, DEFAULT_SETTINGSRESETOFS, 0, INT_MAX, NULL, NULL) );
4430 
4431  SCIP_CALL( SCIPaddIntParam(scip, "relaxing/SDP/sdpsolverthreads",
4432  "number of threads the SDP solver should use (-1 = number of cores); currently only supported for MOSEK",
4433  &(relaxdata->sdpsolverthreads), TRUE, DEFAULT_SDPSOLVERTHREADS, -1, INT_MAX, NULL, NULL) );
4434 
4435 
4436  /* add description of SDP-solver */
4437  SCIP_CALL( SCIPincludeExternalCodeInformation(scip, SCIPsdpiGetSolverName(), SCIPsdpiGetSolverDesc()) );
4438 
4439  return SCIP_OKAY;
4440 }
4441 
4442 
4443 /* external functions */
4444 
4449  SCIP* scip,
4450  SCIP_RELAX* relax
4451  )
4452 {
4453  SCIP_CONSHDLR* sdpconshdlr;
4454  SCIP_RELAXDATA* relaxdata;
4455 
4456  assert( scip != NULL );
4457  assert( relax != NULL );
4458  assert( SCIPgetStage(scip) == SCIP_STAGE_SOLVING );
4459 
4460  SCIPdebugMsg(scip, "computing analytic centers for warmstarting\n");
4461 
4462  relaxdata = SCIPrelaxGetData(relax);
4463 
4464  /* this function should only be executed once */
4465  if ( relaxdata->ipXexists || relaxdata->ipZexists )
4466  {
4467  SCIPdebugMsg(scip, "aborting SCIPrelaxSdpComputeAnalyticCenters since analytic centers have already been computed\n");
4468  return SCIP_OKAY;
4469  }
4470 
4471  sdpconshdlr = SCIPfindConshdlr(scip, "SDP");
4472 
4473  /* if we want to warmstart using the analytic center, compute it now */
4474  if ( relaxdata->warmstart && (relaxdata->warmstartiptype == 2) && SCIPisGT(scip, relaxdata->warmstartipfactor, 0.0) && (SCIPconshdlrGetNConss(sdpconshdlr) + SCIPgetNLPRows(scip) > 0 ) )
4475  {
4476  int b;
4477 
4478  relaxdata->nblocks = SCIPgetNLPRows(scip) + SCIPgetNVars(scip) > 0 ? SCIPconshdlrGetNConss(sdpconshdlr) + 1 : SCIPconshdlrGetNConss(sdpconshdlr);
4479 
4480  if ( SCIPgetNVars(scip) > 0 )
4481  {
4482  SCIP_ROW** rows;
4483  SCIP_COL** rowcols;
4484  SCIP_CONS** sdpblocks;
4485  SCIP_Real* solforscip;
4486  SCIP_Real* rowvals;
4487  SCIP_Real timelimit;
4488  SCIP_Real rowval;
4489  int slength;
4490  int arraylength;
4491  int nrows;
4492  int rownnonz;
4493  int i;
4494  int r;
4495  int v;
4496  SCIP_SDPSOLVERSETTING usedsetting;
4497  SCIP_SDPSLATERSETTING slatersetting;
4498  SCIP_SDPSLATER primalslater;
4499  SCIP_SDPSLATER dualslater;
4500  int naddediters;
4501  int naddedsdpcalls;
4502 
4503  /* first solve SDP with primal objective (dual constant part) set to zero to compute analytic center of primal feasible set */
4504  if ( relaxdata->warmstartprimaltype != 2 && SCIPsdpiDoesWarmstartNeedPrimal() )
4505  {
4506  SCIP_CALL( putSdpDataInInterface(scip, relaxdata->sdpi, relaxdata->varmapper, FALSE, TRUE) );
4507  SCIP_CALL( putLpDataInInterface(scip, relaxdata->sdpi, relaxdata->varmapper, FALSE, TRUE) );
4508 
4509  /* set time limit */
4510  SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
4511  if ( ! SCIPisInfinity(scip, timelimit) )
4512  {
4513  timelimit -= SCIPgetSolvingTime(scip);
4514  if ( timelimit <= 0.0 )
4515  return SCIP_OKAY;
4516  }
4517 
4518  /* TODO: might want to add an additional parameter to solve to disable penalty, since we cannot use that here anyways */
4519  SCIP_CALL(SCIPsdpiSolve(relaxdata->sdpi, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, SCIP_SDPSOLVERSETTING_UNSOLVED, FALSE, timelimit));
4520 
4521  /* update calls, iterations and stability numbers (only if the SDP-solver was actually called) */
4522  relaxdata->sdpinterfacecalls++;
4523  naddedsdpcalls = 0;
4524  SCIP_CALL( SCIPsdpiGetSdpCalls(relaxdata->sdpi, &naddedsdpcalls) );
4525  usedsetting = SCIP_SDPSOLVERSETTING_UNSOLVED;
4526  if ( naddedsdpcalls )
4527  {
4528  relaxdata->sdpcalls += naddedsdpcalls;
4529  naddediters = 0;
4530  SCIP_CALL( SCIPsdpiGetIterations(relaxdata->sdpi, &naddediters) );
4531  relaxdata->sdpiterations += naddediters;
4532 
4533  SCIP_CALL( SCIPsdpiSettingsUsed(relaxdata->sdpi, &usedsetting) );
4534 
4535  switch( usedsetting )/*lint --e{788}*/
4536  {
4538  relaxdata->solvedpenalty++;
4539  break;
4541  relaxdata->solvedfast++;
4542  break;
4544  relaxdata->solvedmedium++;
4545  break;
4547  relaxdata->solvedstable++;
4548  break;
4550  relaxdata->unsolved++;
4551  break;
4552  default:
4553  break;
4554  }
4555  primalslater = SCIP_SDPSLATER_NOINFO;
4556  dualslater = SCIP_SDPSLATER_NOINFO;
4557  SCIP_CALL( SCIPsdpiSlater(relaxdata->sdpi, &primalslater, &dualslater) );
4558  switch( primalslater )/*lint --e{788}*/
4559  {
4560  case SCIP_SDPSLATER_NOINFO:
4561  relaxdata->npslatercheckfailed++;
4562  switch( dualslater )/*lint --e{788}*/
4563  {
4564  case SCIP_SDPSLATER_NOINFO:
4565  relaxdata->ndslatercheckfailed++;
4566  relaxdata->nslatercheckfailed++;
4567  break;
4568  case SCIP_SDPSLATER_NOT:
4569  relaxdata->ndnoslater++;
4570  relaxdata->nnoslater++;
4571  break;
4572  case SCIP_SDPSLATER_HOLDS:
4573  relaxdata->ndslaterholds++;
4574  relaxdata->nslatercheckfailed++;
4575  break;
4576  case SCIP_SDPSLATER_INF:
4577  relaxdata->nslaterinfeasible++;
4578  break;
4579  default:
4580  relaxdata->ndslatercheckfailed++;
4581  relaxdata->nslatercheckfailed++;
4582  break;
4583  }
4584  break;
4585  case SCIP_SDPSLATER_NOT:
4586  relaxdata->npnoslater++;
4587  switch( dualslater )/*lint --e{788}*/
4588  {
4589  case SCIP_SDPSLATER_NOINFO:
4590  relaxdata->ndslatercheckfailed++;
4591  relaxdata->nnoslater++;
4592  break;
4593  case SCIP_SDPSLATER_NOT:
4594  relaxdata->ndnoslater++;
4595  relaxdata->nnoslater++;
4596  break;
4597  case SCIP_SDPSLATER_HOLDS:
4598  relaxdata->ndslaterholds++;
4599  relaxdata->nnoslater++;
4600  break;
4601  case SCIP_SDPSLATER_INF:
4602  relaxdata->nslaterinfeasible++;
4603  break;
4604  default:
4605  relaxdata->ndslatercheckfailed++;
4606  relaxdata->nnoslater++;
4607  break;
4608  }
4609  break;
4610  case SCIP_SDPSLATER_HOLDS:
4611  relaxdata->npslaterholds++;
4612  switch( dualslater )/*lint --e{788}*/
4613  {
4614  case SCIP_SDPSLATER_NOINFO:
4615  relaxdata->ndslatercheckfailed++;
4616  relaxdata->nslatercheckfailed++;
4617  break;
4618  case SCIP_SDPSLATER_NOT:
4619  relaxdata->ndnoslater++;
4620  relaxdata->nnoslater++;
4621  break;
4622  case SCIP_SDPSLATER_HOLDS:
4623  relaxdata->ndslaterholds++;
4624  relaxdata->nslaterholds++;
4625  break;
4626  case SCIP_SDPSLATER_INF:
4627  relaxdata->nslaterinfeasible++;
4628  break;
4629  default:
4630  relaxdata->ndslatercheckfailed++;
4631  relaxdata->nslatercheckfailed++;
4632  break;
4633  }
4634  break;
4635  default:
4636  relaxdata->npslatercheckfailed++;
4637  relaxdata->ndslatercheckfailed++;
4638  relaxdata->nslatercheckfailed++;
4639  break;
4640  }
4641  slatersetting = SCIP_SDPSLATERSETTING_NOINFO;
4642  SCIP_CALL( SCIPsdpiSlaterSettings(relaxdata->sdpi, &slatersetting) );
4643  switch( slatersetting )/*lint --e{788}*/
4644  {
4646  relaxdata->stablewslater++;
4647  break;
4649  relaxdata->unstablewslater++;
4650  break;
4652  relaxdata->penaltywslater++;
4653  break;
4655  relaxdata->boundedwslater++;
4656  break;
4658  relaxdata->unsolvedwslater++;
4659  break;
4661  relaxdata->stablenoslater++;
4662  break;
4664  relaxdata->unstablenoslater++;
4665  break;
4667  relaxdata->penaltynoslater++;
4668  break;
4670  relaxdata->boundednoslater++;
4671  break;
4673  relaxdata->unsolvednoslater++;
4674  break;
4676  relaxdata->stableinfeasible++;
4677  break;
4679  relaxdata->unstableinfeasible++;
4680  break;
4682  relaxdata->penaltyinfeasible++;
4683  break;
4685  relaxdata->boundedinfeasible++;
4686  break;
4688  relaxdata->unsolvedinfeasible++;
4689  break;
4690  default:
4691  break;
4692  }
4693  }
4694 
4695  if ( SCIPsdpiWasSolved(relaxdata->sdpi) && SCIPsdpiSolvedOrig(relaxdata->sdpi) && SCIPsdpiIsPrimalFeasible(relaxdata->sdpi) )
4696  {
4697  int npenaltybounds = 0;
4698 
4699  relaxdata->ipXexists = TRUE;
4700 
4701  /* allocate memory (for the different blocks the neccessary anount first needs to be computed) */
4702  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXnblocknonz, relaxdata->nblocks) );
4703  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXrow, relaxdata->nblocks) );
4704  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXcol, relaxdata->nblocks) );
4705  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXval, relaxdata->nblocks) );
4706 
4707  SCIP_CALL(SCIPsdpiGetPrimalNonzeros(relaxdata->sdpi, relaxdata->nblocks, relaxdata->ipXnblocknonz));
4708  for (b = 0; b < relaxdata->nblocks; b++)
4709  {
4710  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXrow[b], relaxdata->ipXnblocknonz[b]) );
4711  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXcol[b], relaxdata->ipXnblocknonz[b]) );
4712  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXval[b], relaxdata->ipXnblocknonz[b]) );
4713  }
4714 
4715  /* get primal solution */
4716  SCIP_CALL( SCIPsdpiGetPrimalMatrix(relaxdata->sdpi, relaxdata->nblocks, relaxdata->ipXnblocknonz,
4717  relaxdata->ipXrow, relaxdata->ipXcol, relaxdata->ipXval) );
4718 
4719  /* count the number of primal entries corresponding to bounds of the penalty variable and remove them */
4720  for (i = 0; i < relaxdata->ipXnblocknonz[relaxdata->nblocks - 1]; i++)
4721  {
4722  if ( relaxdata->ipXrow[relaxdata->nblocks - 1][i] == SCIPsdpVarmapperGetNVars(relaxdata->varmapper) )
4723  npenaltybounds++;
4724  }
4725 
4726  if ( npenaltybounds > 0 )
4727  {
4728  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &relaxdata->ipXrow[relaxdata->nblocks - 1],
4729  relaxdata->ipXnblocknonz[relaxdata->nblocks - 1], relaxdata->ipXnblocknonz[relaxdata->nblocks - 1] - npenaltybounds) );
4730  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &relaxdata->ipXcol[relaxdata->nblocks - 1],
4731  relaxdata->ipXnblocknonz[relaxdata->nblocks - 1], relaxdata->ipXnblocknonz[relaxdata->nblocks - 1] - npenaltybounds) );
4732  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &relaxdata->ipXval[relaxdata->nblocks - 1],
4733  relaxdata->ipXnblocknonz[relaxdata->nblocks - 1], relaxdata->ipXnblocknonz[relaxdata->nblocks - 1] - npenaltybounds) );
4734  relaxdata->ipXnblocknonz[relaxdata->nblocks - 1] = relaxdata->ipXnblocknonz[relaxdata->nblocks - 1] - npenaltybounds;
4735  }
4736 
4737  for (b = 0; b < relaxdata->nblocks; b++)
4738  {
4739  /* TODO check if they are already sorted (sorting is needed since they will later be merged into warmstart arrays) */
4740  SCIPsdpVarfixerSortRowCol(relaxdata->ipXrow[b], relaxdata->ipXcol[b], relaxdata->ipXval[b], relaxdata->ipXnblocknonz[b]);
4741  }
4742 
4743 #ifdef SCIP_PRINT_WARMSTART
4744  SCIPdebugMessage("Computed primal analytic center:\n");
4745  for (b = 0; b < relaxdata->nblocks; b++)
4746  {
4747  SCIPdebugMessage("primal matrix, block %d:\n", b);
4748  for (i = 0; i < relaxdata->ipXnblocknonz[b]; i++)
4749  {
4750  SCIPdebugMessage("X_%d[%d,%d]: %f\n", b, relaxdata->ipXrow[b][i], relaxdata->ipXcol[b][i], relaxdata->ipXval[b][i]);
4751  }
4752  }
4753 #endif
4754  }
4755  else
4756  {
4757  relaxdata->ipXexists = TRUE;
4758 
4759  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXnblocknonz, relaxdata->nblocks) );
4760  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXrow, relaxdata->nblocks) );
4761  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXcol, relaxdata->nblocks) );
4762  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXval, relaxdata->nblocks) );
4763 
4764  sdpblocks = SCIPconshdlrGetConss(sdpconshdlr);
4765 
4766  for (b = 0; b < relaxdata->nblocks; b++)
4767  {
4768  if ( b < relaxdata->nblocks - 1 )
4769  {
4770  /* SDP block */
4771  relaxdata->ipXnblocknonz[b] = SCIPconsSdpGetBlocksize(scip, sdpblocks[b]);
4772  }
4773  else
4774  {
4775  /* LP block */
4776  relaxdata->ipXnblocknonz[b] = SCIPgetNLPRows(scip) + 2 * SCIPgetNVars(scip);
4777  }
4778  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXrow[b], relaxdata->ipXnblocknonz[b]) );
4779  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXcol[b], relaxdata->ipXnblocknonz[b]) );
4780  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipXval[b], relaxdata->ipXnblocknonz[b]) );
4781 
4782  for (i = 0; i < relaxdata->ipXnblocknonz[b]; i++)
4783  {
4784  relaxdata->ipXrow[b][i] = i;
4785  relaxdata->ipXcol[b][i] = i;
4786  relaxdata->ipXval[b][i] = relaxdata->lambdastar;
4787  }
4788  }
4789 
4790  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL, "Failed to compute analytic center of primal feasible set, using scaled identity instead.\n");
4791  }
4792  }
4793 
4794  /* set dual objective coefficients to zero to compute analytic center of dual feasible set */
4795  SCIP_CALL( putSdpDataInInterface(scip, relaxdata->sdpi, relaxdata->varmapper, TRUE, FALSE) );
4796  SCIP_CALL( putLpDataInInterface(scip, relaxdata->sdpi, relaxdata->varmapper, TRUE, FALSE) );
4797 
4798  /* set time limit */
4799  SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
4800  if ( ! SCIPisInfinity(scip, timelimit) )
4801  {
4802  timelimit -= SCIPgetSolvingTime(scip);
4803  if ( timelimit <= 0.0 )
4804  return SCIP_OKAY;
4805  }
4806 
4807  /* TODO: might want to add an additional parameter to solve to disable penalty, since we cannot use that here anyways */
4808  SCIP_CALL(SCIPsdpiSolve(relaxdata->sdpi, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, SCIP_SDPSOLVERSETTING_UNSOLVED, FALSE, timelimit));
4809 
4810  /* update calls, iterations and stability numbers (only if the SDP-solver was actually called) */
4811  naddedsdpcalls = 0;
4812  SCIP_CALL( SCIPsdpiGetSdpCalls(relaxdata->sdpi, &naddedsdpcalls) );
4813  usedsetting = SCIP_SDPSOLVERSETTING_UNSOLVED;
4814  if ( naddedsdpcalls )
4815  {
4816  relaxdata->sdpinterfacecalls++;
4817  relaxdata->sdpcalls += naddedsdpcalls;
4818  naddediters = 0;
4819  SCIP_CALL( SCIPsdpiGetIterations(relaxdata->sdpi, &naddediters) );
4820  relaxdata->sdpiterations += naddediters;
4821 
4822  SCIP_CALL( SCIPsdpiSettingsUsed(relaxdata->sdpi, &usedsetting) );
4823 
4824  switch( usedsetting )/*lint --e{788}*/
4825  {
4827  relaxdata->solvedpenalty++;
4828  break;
4830  relaxdata->solvedfast++;
4831  break;
4833  relaxdata->solvedmedium++;
4834  break;
4836  relaxdata->solvedstable++;
4837  break;
4839  relaxdata->unsolved++;
4840  break;
4841  default:
4842  break;
4843  }
4844  primalslater = SCIP_SDPSLATER_NOINFO;
4845  dualslater = SCIP_SDPSLATER_NOINFO;
4846  SCIP_CALL( SCIPsdpiSlater(relaxdata->sdpi, &primalslater, &dualslater) );
4847  switch( primalslater )/*lint --e{788}*/
4848  {
4849  case SCIP_SDPSLATER_NOINFO:
4850  relaxdata->npslatercheckfailed++;
4851  switch( dualslater )/*lint --e{788}*/
4852  {
4853  case SCIP_SDPSLATER_NOINFO:
4854  relaxdata->ndslatercheckfailed++;
4855  relaxdata->nslatercheckfailed++;
4856  break;
4857  case SCIP_SDPSLATER_NOT:
4858  relaxdata->ndnoslater++;
4859  relaxdata->nnoslater++;
4860  break;
4861  case SCIP_SDPSLATER_HOLDS:
4862  relaxdata->ndslaterholds++;
4863  relaxdata->nslatercheckfailed++;
4864  break;
4865  case SCIP_SDPSLATER_INF:
4866  relaxdata->nslaterinfeasible++;
4867  break;
4868  default:
4869  relaxdata->ndslatercheckfailed++;
4870  relaxdata->nslatercheckfailed++;
4871  break;
4872  }
4873  break;
4874  case SCIP_SDPSLATER_NOT:
4875  relaxdata->npnoslater++;
4876  switch( dualslater )/*lint --e{788}*/
4877  {
4878  case SCIP_SDPSLATER_NOINFO:
4879  relaxdata->ndslatercheckfailed++;
4880  relaxdata->nnoslater++;
4881  break;
4882  case SCIP_SDPSLATER_NOT:
4883  relaxdata->ndnoslater++;
4884  relaxdata->nnoslater++;
4885  break;
4886  case SCIP_SDPSLATER_HOLDS:
4887  relaxdata->ndslaterholds++;
4888  relaxdata->nnoslater++;
4889  break;
4890  case SCIP_SDPSLATER_INF:
4891  relaxdata->nslaterinfeasible++;
4892  break;
4893  default:
4894  relaxdata->ndslatercheckfailed++;
4895  relaxdata->nnoslater++;
4896  break;
4897  }
4898  break;
4899  case SCIP_SDPSLATER_HOLDS:
4900  relaxdata->npslaterholds++;
4901  switch( dualslater )/*lint --e{788}*/
4902  {
4903  case SCIP_SDPSLATER_NOINFO:
4904  relaxdata->ndslatercheckfailed++;
4905  relaxdata->nslatercheckfailed++;
4906  break;
4907  case SCIP_SDPSLATER_NOT:
4908  relaxdata->ndnoslater++;
4909  relaxdata->nnoslater++;
4910  break;
4911  case SCIP_SDPSLATER_HOLDS:
4912  relaxdata->ndslaterholds++;
4913  relaxdata->nslaterholds++;
4914  break;
4915  case SCIP_SDPSLATER_INF:
4916  relaxdata->nslaterinfeasible++;
4917  break;
4918  default:
4919  relaxdata->ndslatercheckfailed++;
4920  relaxdata->nslatercheckfailed++;
4921  break;
4922  }
4923  break;
4924  default:
4925  relaxdata->npslatercheckfailed++;
4926  relaxdata->ndslatercheckfailed++;
4927  relaxdata->nslatercheckfailed++;
4928  break;
4929  }
4930  slatersetting = SCIP_SDPSLATERSETTING_NOINFO;
4931  SCIP_CALL( SCIPsdpiSlaterSettings(relaxdata->sdpi, &slatersetting) );
4932  switch( slatersetting )/*lint --e{788}*/
4933  {
4935  relaxdata->stablewslater++;
4936  break;
4938  relaxdata->unstablewslater++;
4939  break;
4941  relaxdata->penaltywslater++;
4942  break;
4944  relaxdata->boundedwslater++;
4945  break;
4947  relaxdata->unsolvedwslater++;
4948  break;
4950  relaxdata->stablenoslater++;
4951  break;
4953  relaxdata->unstablenoslater++;
4954  break;
4956  relaxdata->penaltynoslater++;
4957  break;
4959  relaxdata->boundednoslater++;
4960  break;
4962  relaxdata->unsolvednoslater++;
4963  break;
4965  relaxdata->stableinfeasible++;
4966  break;
4968  relaxdata->unstableinfeasible++;
4969  break;
4971  relaxdata->penaltyinfeasible++;
4972  break;
4974  relaxdata->boundedinfeasible++;
4975  break;
4977  relaxdata->unsolvedinfeasible++;
4978  break;
4979  default:
4980  break;
4981  }
4982  }
4983 
4984  if ( SCIPsdpiWasSolved(relaxdata->sdpi) && SCIPsdpiSolvedOrig(relaxdata->sdpi) && SCIPsdpiIsDualFeasible(relaxdata->sdpi) )
4985  {
4986  int nvars;
4987  SCIP_VAR** vars;
4988 
4989  relaxdata->ipZexists = TRUE;
4990 
4991  nvars = SCIPgetNVars(scip);
4992  vars = SCIPgetVars(scip);
4993 
4994  /* allocate memory */
4995  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZnblocknonz, relaxdata->nblocks) );
4996  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZrow, relaxdata->nblocks) );
4997  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZcol, relaxdata->nblocks) );
4998  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZval, relaxdata->nblocks) );
4999 
5000  /* get solution w.r.t. SCIP variables */
5001  SCIP_CALL( SCIPallocBufferArray(scip, &solforscip, nvars) );
5002  slength = nvars;
5003 
5004  SCIP_CALL( SCIPsdpiGetSol(relaxdata->sdpi, NULL, solforscip, &slength) ); /* get the solution from the SDP solver */
5005 
5006  assert( slength == nvars ); /* If this isn't true any longer, the getSol-Call was unsuccessfull, because the given array wasn't long enough,
5007  * but this can't happen, because the array has enough space for all sdp variables. */
5008 
5009  /* create SCIP solution */
5010  SCIP_CALL( SCIPcreateSol(scip, &relaxdata->ipy, NULL) );
5011  SCIP_CALL( SCIPsetSolVals(scip, relaxdata->ipy, nvars, vars, solforscip) );
5012 #ifdef SCIP_PRINT_WARMSTART
5013  SCIPdebugMessage("Computed dual analytic center:\n");
5014  for (i = 0; i < nvars; i++)
5015  {
5016  SCIPdebugMessage("y[%d] = %f\n", i, solforscip[i]);
5017  }
5018 #endif
5019 
5020  SCIPfreeBufferArray(scip, &solforscip);
5021 
5022  /* compute SDP blocks of dual analytic center */
5023  sdpblocks = SCIPconshdlrGetConss(sdpconshdlr);
5024  for (b = 0; b < relaxdata->nblocks - 1; b++)
5025  {
5026  relaxdata->ipZnblocknonz[b] = SCIPconsSdpComputeUbSparseSdpMatrixLength(scip, sdpblocks[b]);
5027  arraylength = relaxdata->ipZnblocknonz[b];
5028 
5029  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZrow[b], relaxdata->ipZnblocknonz[b]) );
5030  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZcol[b], relaxdata->ipZnblocknonz[b]) );
5031  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZval[b], relaxdata->ipZnblocknonz[b]) );
5032 
5033  /* compute Z matrix */
5034  SCIP_CALL( SCIPconsSdpComputeSparseSdpMatrix(scip, sdpblocks[b], relaxdata->ipy, &(relaxdata->ipZnblocknonz[b]), relaxdata->ipZrow[b], relaxdata->ipZcol[b], relaxdata->ipZval[b]) );
5035 
5036  assert( relaxdata->ipZnblocknonz[b] <= arraylength );
5037 
5038  if ( relaxdata->ipZnblocknonz[b] < arraylength )
5039  {
5040  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &relaxdata->ipZrow[b], arraylength, relaxdata->ipZnblocknonz[b]) );
5041  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &relaxdata->ipZcol[b], arraylength, relaxdata->ipZnblocknonz[b]) );
5042  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &relaxdata->ipZval[b], arraylength, relaxdata->ipZnblocknonz[b]) );
5043  }
5044 
5045  /* TODO check if they are already sorted (sorting is needed since they will later be merged into warmstart arrays) */
5046  SCIPsdpVarfixerSortRowCol(relaxdata->ipZrow[b], relaxdata->ipZcol[b], relaxdata->ipZval[b], relaxdata->ipZnblocknonz[b]);
5047  }
5048 
5049  /* compute LP block */
5050  SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
5051  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZrow[b], 2 * nrows + 2 * nvars) );
5052  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZcol[b], 2 * nrows + 2 * nvars) );
5053  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZval[b], 2 * nrows + 2 * nvars) );
5054 
5055  /* for the analytic center all the entries should be strictly positive */
5056  relaxdata->ipZnblocknonz[b] = 2 * nrows + 2 * nvars;
5057 
5058  for (r = 0; r < nrows; r++)
5059  {
5060  /* compute row value for current solution */
5061  rowval = 0.0;
5062  rownnonz = SCIProwGetNNonz(rows[r]);
5063  rowvals = SCIProwGetVals(rows[r]);
5064  rowcols = SCIProwGetCols(rows[r]);
5065  for (i = 0; i < rownnonz; i++)
5066  rowval += SCIPgetSolVal(scip, relaxdata->ipy, SCIPcolGetVar(rowcols[i])) * rowvals[i];
5067 
5068  relaxdata->ipZrow[b][2*r] = 2*r;
5069  relaxdata->ipZcol[b][2*r] = 2*r;
5070  relaxdata->ipZval[b][2*r] = rowval - (SCIProwGetLhs(rows[r]) - SCIProwGetConstant(rows[r]));
5071  relaxdata->ipZrow[b][2*r + 1] = 2*r + 1;
5072  relaxdata->ipZcol[b][2*r + 1] = 2*r + 1;
5073  relaxdata->ipZval[b][2*r + 1] = SCIProwGetRhs(rows[r]) - SCIProwGetConstant(rows[r]) - rowval;
5074  }
5075 
5076  for (v = 0; v < nvars; v++)
5077  {
5078  relaxdata->ipZrow[b][2*nrows + 2*v] = 2*nrows + 2*v;
5079  relaxdata->ipZcol[b][2*nrows + 2*v] = 2*nrows + 2*v;
5080  relaxdata->ipZval[b][2*nrows + 2*v] = SCIPgetSolVal(scip, relaxdata->ipy, vars[v]) - SCIPvarGetLbLocal(vars[v]);
5081  relaxdata->ipZrow[b][2*nrows + 2*v + 1] = 2*nrows + 2*v + 1;
5082  relaxdata->ipZcol[b][2*nrows + 2*v + 1] = 2*nrows + 2*v + 1;
5083  relaxdata->ipZval[b][2*nrows + 2*v + 1] = SCIPvarGetUbLocal(vars[v]) - SCIPgetSolVal(scip, relaxdata->ipy, vars[v]);
5084  }
5085 #ifdef SCIP_PRINT_WARMSTART
5086  for (b = 0; b < relaxdata->nblocks - 1; b++)
5087  {
5088  SCIPdebugMessage("dual matrix, block %d:\n", b);
5089  for (i = 0; i < relaxdata->ipZnblocknonz[b]; i++)
5090  {
5091  SCIPdebugMessage("Z_%d[%d,%d]: %f\n", b, relaxdata->ipZrow[b][i], relaxdata->ipZcol[b][i], relaxdata->ipZval[b][i]);
5092  }
5093  }
5094  SCIPdebugMessage("dual matrix, LP constraints:\n");
5095  for (r = 0; r < nrows; r++)
5096  {
5097  SCIPdebugMessage("Z_%d[%d,%d]: %f\n", relaxdata->nblocks, relaxdata->ipZrow[b][2*r], relaxdata->ipZcol[b][2*r], relaxdata->ipZval[b][2*r]);
5098  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]);
5099  }
5100  for (v = 0; v < nvars; v++)
5101  {
5102  SCIPdebugMessage("Z_%d[%d,%d]: %f\n", relaxdata->nblocks,
5103  relaxdata->ipZrow[b][2*nrows + 2*v], relaxdata->ipZcol[b][2*nrows + 2*v], relaxdata->ipZval[b][2*nrows + 2*v]);
5104  SCIPdebugMessage("Z_%d[%d,%d]: %f\n", relaxdata->nblocks,
5105  relaxdata->ipZrow[b][2*nrows + 2*v + 1], relaxdata->ipZcol[b][2*nrows + 2*v + 1], relaxdata->ipZval[b][2*nrows + 2*v + 1]);
5106  }
5107 #endif
5108  }
5109  else
5110  {
5111  /* use a scaled identity matrix (and y=0) if the computation of the dual analytic center failed */
5112  relaxdata->ipZexists = TRUE;
5113 
5114  /* y is set to the zero vector */
5115  SCIP_CALL( SCIPcreateSol(scip, &relaxdata->ipy, NULL) );
5116 
5117  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZnblocknonz, relaxdata->nblocks) );
5118  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZrow, relaxdata->nblocks) );
5119  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZcol, relaxdata->nblocks) );
5120  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZval, relaxdata->nblocks) );
5121 
5122  sdpblocks = SCIPconshdlrGetConss(sdpconshdlr);
5123 
5124  for (b = 0; b < relaxdata->nblocks; b++)
5125  {
5126  if ( b < relaxdata->nblocks - 1 )
5127  {
5128  /* SDP block */
5129  relaxdata->ipZnblocknonz[b] = SCIPconsSdpGetBlocksize(scip, sdpblocks[b]);
5130  }
5131  else
5132  {
5133  /* LP block */
5134  relaxdata->ipZnblocknonz[b] = SCIPgetNLPRows(scip) + 2 * SCIPgetNVars(scip);
5135  }
5136  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZrow[b], relaxdata->ipZnblocknonz[b]) );
5137  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZcol[b], relaxdata->ipZnblocknonz[b]) );
5138  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->ipZval[b], relaxdata->ipZnblocknonz[b]) );
5139 
5140  for (i = 0; i < relaxdata->ipXnblocknonz[b]; i++)
5141  {
5142  relaxdata->ipZrow[b][i] = i;
5143  relaxdata->ipZcol[b][i] = i;
5144  relaxdata->ipZval[b][i] = relaxdata->lambdastar;
5145  }
5146  }
5147 
5148  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL, "Failed to compute analytic center of dual feasible set, using scaled identity instead.\n");
5149  }
5150  }
5151  }
5152  return SCIP_OKAY;
5153 }
5154 
5164  SCIP_RELAX* relax,
5165  SCIP_Real* lbvars,
5166  SCIP_Real* ubvars,
5167  int* arraylength
5169  )
5170 {
5171  SCIP_RELAXDATA* relaxdata;
5172 
5173  assert( relax != NULL );
5174  assert( lbvars != NULL );
5175  assert( ubvars != NULL );
5176  assert( arraylength != NULL );
5177  assert( *arraylength >= 0 );
5178 
5179  relaxdata = SCIPrelaxGetData(relax);
5180  assert( relaxdata != NULL );
5181 
5182  SCIP_CALL( SCIPsdpiGetPrimalBoundVars(relaxdata->sdpi, lbvars, ubvars, arraylength) );
5183 
5184  return SCIP_OKAY;
5185 }
5186 
5189  SCIP_RELAX* relax,
5190  SCIP_Bool* success,
5191  SCIP_Real* objval
5192  )
5193 {
5194  SCIP_RELAXDATA* relaxdata;
5195 
5196  assert( relax != NULL );
5197  assert( success != NULL );
5198  assert( objval != NULL );
5199 
5200  relaxdata = SCIPrelaxGetData(relax);
5201  assert( relaxdata != NULL );
5202 
5203  *success = relaxdata->origsolved;
5204  *objval = relaxdata->objval;
5205 
5206  return SCIP_OKAY;
5207 }
5208 
5211  SCIP* scip,
5212  SCIP_RELAX* relax,
5213  SCIP_Bool* success,
5214  SCIP_Real* solarray,
5215  int* sollength
5216  )
5217 {
5218  SCIP_RELAXDATA* relaxdata;
5219 
5220  assert( relax != NULL );
5221  assert( success != NULL );
5222  assert( solarray != NULL );
5223 
5224  relaxdata = SCIPrelaxGetData(relax);
5225  assert( relaxdata != NULL );
5226 
5227  *success = relaxdata->origsolved;
5228 
5229  if ( *sollength >= SCIPgetNVars(scip) )
5230  {
5231  SCIP_CALL( SCIPsdpiGetSol(relaxdata->sdpi, NULL, solarray, sollength) );
5232  }
5233  else
5234  {
5235  SCIPdebugMessage("Called SCIPrelaxSdpGetRelaxSol with an array that wasn't big enough, needed length %d, given %d!\n", SCIPgetNVars(scip), *sollength);
5236  *sollength = SCIPgetNVars(scip);
5237  }
5238 
5239  return SCIP_OKAY;
5240 }
5241 
5244  SCIP_RELAX* relax
5245  )
5246 {
5247  assert( relax != NULL );
5248  assert( SCIPrelaxGetData(relax) != NULL );
5249 
5250  return SCIPrelaxGetData(relax)->lastsdpnode;
5251 }
5252 
5255  SCIP_RELAX* relax
5256  )
5257 {
5258  SCIP_RELAXDATA* relaxdata;
5259 
5260  assert( relax != NULL );
5261 
5262  relaxdata = SCIPrelaxGetData(relax);
5263 
5264  assert( relaxdata != NULL );
5265  assert( relaxdata->sdpi != NULL );
5266 
5267  return relaxdata->origsolved && SCIPsdpiSolvedOrig(relaxdata->sdpi);
5268 }
5269 
5272  SCIP_RELAX* relax
5273  )
5274 {
5275  SCIP_RELAXDATA* relaxdata;
5276 
5277  assert( relax != NULL );
5278 
5279  relaxdata = SCIPrelaxGetData(relax);
5280 
5281  assert( relaxdata != NULL );
5282  assert( relaxdata->sdpi != NULL );
5283 
5284  return relaxdata->probingsolved;
5285 }
5286 
5289  SCIP_RELAX* relax
5290  )
5291 {
5292  assert( relax != NULL );
5293  assert( SCIPrelaxGetData(relax) != NULL );
5294 
5295  return ( SCIPrelaxGetData(relax)->feasible );
5296 }
5297 
5300  SCIP_RELAX* relax
5301  )
5302 {
5303  SCIP_RELAXDATA* relaxdata;
5304 
5305  assert( relax != NULL );
5306 
5307  relaxdata = SCIPrelaxGetData(relax);
5308 
5309  assert( SCIPrelaxGetData(relax) != NULL );
5310  assert( relaxdata->sdpi != NULL );
5311 
5312  return SCIPsdpiIsDualUnbounded(relaxdata->sdpi);
5313 }
5314 
5317  SCIP_RELAX* relax
5318  )
5319 {
5320  assert( relax != NULL );
5321  assert( SCIPrelaxGetData(relax) != NULL );
5322 
5323  return SCIPrelaxGetData(relax)->sdpiterations;
5324 }
5325 
5328  SCIP_RELAX* relax
5329  )
5330 {
5331  assert( relax != NULL );
5332  assert( SCIPrelaxGetData(relax) != NULL );
5333 
5334  return ( SCIPrelaxGetData(relax)->sdpcalls );
5335 }
5336 
5339  SCIP_RELAX* relax
5340  )
5341 {
5342  assert( relax != NULL );
5343  assert( SCIPrelaxGetData(relax) != NULL );
5344 
5345  return ( SCIPrelaxGetData(relax)->sdpinterfacecalls );
5346 }
5347 
5350  SCIP_RELAX* relax
5351  )
5352 {
5353  assert( relax != NULL );
5354  assert( SCIPrelaxGetData(relax) != NULL );
5355 
5356  return ( SCIPrelaxGetData(relax)->solvedfast );
5357 }
5358 
5361  SCIP_RELAX* relax
5362  )
5363 {
5364  assert( relax != NULL );
5365  assert( SCIPrelaxGetData(relax) != NULL );
5366 
5367  return ( SCIPrelaxGetData(relax)->solvedmedium );
5368 }
5369 
5372  SCIP_RELAX* relax
5373  )
5374 {
5375  assert( relax != NULL );
5376  assert( SCIPrelaxGetData(relax) != NULL );
5377 
5378  return ( SCIPrelaxGetData(relax)->solvedstable );
5379 }
5380 
5383  SCIP_RELAX* relax
5384  )
5385 {
5386  assert( relax != NULL );
5387  assert( SCIPrelaxGetData(relax) != NULL );
5388 
5389  return ( SCIPrelaxGetData(relax)->solvedpenalty );
5390 }
5391 
5394  SCIP_RELAX* relax
5395  )
5396 {
5397  assert( relax != NULL );
5398  assert( SCIPrelaxGetData(relax) != NULL );
5399 
5400  return ( SCIPrelaxGetData(relax)->unsolved );
5401 }
5402 
5405  SCIP_RELAX* relax
5406  )
5407 {
5408  assert( relax != NULL );
5409  assert( SCIPrelaxGetData(relax) != NULL );
5410 
5411  return ( SCIPrelaxGetData(relax)->ndslaterholds );
5412 }
5413 
5416  SCIP_RELAX* relax
5417  )
5418 {
5419  assert( relax != NULL );
5420  assert( SCIPrelaxGetData(relax) != NULL );
5421 
5422  return ( SCIPrelaxGetData(relax)->ndnoslater );
5423 }
5424 
5427  SCIP_RELAX* relax
5428  )
5429 {
5430  assert( relax != NULL );
5431  assert( SCIPrelaxGetData(relax) != NULL );
5432 
5433  return ( SCIPrelaxGetData(relax)->nslaterinfeasible );
5434 }
5435 
5438  SCIP_RELAX* relax
5439  )
5440 {
5441  assert( relax != NULL );
5442  assert( SCIPrelaxGetData(relax) != NULL );
5443 
5444  return ( SCIPrelaxGetData(relax)->ndslatercheckfailed );
5445 }
5446 
5449  SCIP_RELAX* relax
5450  )
5451 {
5452  assert( relax != NULL );
5453  assert( SCIPrelaxGetData(relax) != NULL );
5454 
5455  return ( SCIPrelaxGetData(relax)->npslaterholds );
5456 }
5457 
5460  SCIP_RELAX* relax
5461  )
5462 {
5463  assert( relax != NULL );
5464  assert( SCIPrelaxGetData(relax) != NULL );
5465 
5466  return ( SCIPrelaxGetData(relax)->npnoslater );
5467 }
5468 
5471  SCIP_RELAX* relax
5472  )
5473 {
5474  assert( relax != NULL );
5475  assert( SCIPrelaxGetData(relax) != NULL );
5476 
5477  return ( SCIPrelaxGetData(relax)->npslatercheckfailed );
5478 }
5479 
5482  SCIP_RELAX* relax
5483  )
5484 {
5485  assert( relax != NULL );
5486  assert( SCIPrelaxGetData(relax) != NULL );
5487 
5488  return ( SCIPrelaxGetData(relax)->nslaterholds );
5489 }
5490 
5493  SCIP_RELAX* relax
5494  )
5495 {
5496  assert( relax != NULL );
5497  assert( SCIPrelaxGetData(relax) != NULL );
5498 
5499  return ( SCIPrelaxGetData(relax)->stablewslater );
5500 }
5501 
5504  SCIP_RELAX* relax
5505  )
5506 {
5507  assert( relax != NULL );
5508  assert( SCIPrelaxGetData(relax) != NULL );
5509 
5510  return ( SCIPrelaxGetData(relax)->unstablewslater );
5511 }
5512 
5515  SCIP_RELAX* relax
5516  )
5517 {
5518  assert( relax != NULL );
5519  assert( SCIPrelaxGetData(relax) != NULL );
5520 
5521  return ( SCIPrelaxGetData(relax)->penaltywslater );
5522 }
5523 
5526  SCIP_RELAX* relax
5527  )
5528 {
5529  assert( relax != NULL );
5530  assert( SCIPrelaxGetData(relax) != NULL );
5531 
5532  return ( SCIPrelaxGetData(relax)->boundedwslater );
5533 }
5534 
5537  SCIP_RELAX* relax
5538  )
5539 {
5540  assert( relax != NULL );
5541  assert( SCIPrelaxGetData(relax) != NULL );
5542 
5543  return ( SCIPrelaxGetData(relax)->unsolvedwslater );
5544 }
5545 
5548  SCIP_RELAX* relax
5549  )
5550 {
5551  assert( relax != NULL );
5552  assert( SCIPrelaxGetData(relax) != NULL );
5553 
5554  return ( SCIPrelaxGetData(relax)->nnoslater );
5555 }
5556 
5559  SCIP_RELAX* relax
5560  )
5561 {
5562  assert( relax != NULL );
5563  assert( SCIPrelaxGetData(relax) != NULL );
5564 
5565  return ( SCIPrelaxGetData(relax)->stablenoslater );
5566 }
5567 
5570  SCIP_RELAX* relax
5571  )
5572 {
5573  assert( relax != NULL );
5574  assert( SCIPrelaxGetData(relax) != NULL );
5575 
5576  return ( SCIPrelaxGetData(relax)->unstablenoslater );
5577 }
5578 
5581  SCIP_RELAX* relax
5582  )
5583 {
5584  assert( relax != NULL );
5585  assert( SCIPrelaxGetData(relax) != NULL );
5586 
5587  return ( SCIPrelaxGetData(relax)->penaltynoslater );
5588 }
5589 
5592  SCIP_RELAX* relax
5593  )
5594 {
5595  assert( relax != NULL );
5596  assert( SCIPrelaxGetData(relax) != NULL );
5597 
5598  return ( SCIPrelaxGetData(relax)->boundednoslater );
5599 }
5600 
5603  SCIP_RELAX* relax
5604  )
5605 {
5606  assert( relax != NULL );
5607  assert( SCIPrelaxGetData(relax) != NULL );
5608 
5609  return ( SCIPrelaxGetData(relax)->unsolvednoslater );
5610 }
5611 
5614  SCIP_RELAX* relax
5615  )
5616 {
5617  assert( relax != NULL );
5618  assert( SCIPrelaxGetData(relax) != NULL );
5619 
5620  return ( SCIPrelaxGetData(relax)->stableinfeasible );
5621 }
5622 
5625  SCIP_RELAX* relax
5626  )
5627 {
5628  assert( relax != NULL );
5629  assert( SCIPrelaxGetData(relax) != NULL );
5630 
5631  return ( SCIPrelaxGetData(relax)->unstableinfeasible );
5632 }
5633 
5636  SCIP_RELAX* relax
5637  )
5638 {
5639  assert( relax != NULL );
5640  assert( SCIPrelaxGetData(relax) != NULL );
5641 
5642  return ( SCIPrelaxGetData(relax)->penaltyinfeasible );
5643 }
5644 
5647  SCIP_RELAX* relax
5648  )
5649 {
5650  assert( relax != NULL );
5651  assert( SCIPrelaxGetData(relax) != NULL );
5652 
5653  return ( SCIPrelaxGetData(relax)->boundedinfeasible );
5654 }
5655 
5658  SCIP_RELAX* relax
5659  )
5660 {
5661  assert( relax != NULL );
5662  assert( SCIPrelaxGetData(relax) != NULL );
5663 
5664  return ( SCIPrelaxGetData(relax)->unsolvedinfeasible );
5665 }
SCIP_Real SCIPconsSdpGetMaxConstEntry(SCIP *scip, SCIP_CONS *cons)
Definition: cons_sdp.c:2866
#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:2994
SCIP_RETCODE SCIPsdpiDelLPRows(SCIP_SDPI *sdpi, int firstrow, int lastrow)
Definition: sdpi.c:1984
int SCIPrelaxSdpGetNSlaterHoldsStable(SCIP_RELAX *relax)
Definition: relax_sdp.c:5503
#define WARMSTART_MINVAL
Definition: relax_sdp.c:94
int SCIPrelaxSdpGetNSlaterInfeasibleFast(SCIP_RELAX *relax)
Definition: relax_sdp.c:5613
SCIP_RETCODE SCIPsdpiGetSdpCalls(SCIP_SDPI *sdpi, int *calls)
Definition: sdpi.c:3606
static SCIP_RETCODE calcRelax(SCIP *scip, SCIP_RELAXDATA *relaxdata, SCIP_RESULT *result, SCIP_Real *lowerbound)
Definition: relax_sdp.c:757
SCIP_Bool SCIPsdpiDoesWarmstartNeedPrimal(void)
Definition: sdpi.c:1428
static SCIP_DECL_RELAXCOPY(relaxCopySdp)
Definition: relax_sdp.c:4076
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:5591
static SCIP_DECL_RELAXEXITSOL(relaxExitSolSdp)
Definition: relax_sdp.c:4089
#define DEFAULT_PENINFEASADJUST
Definition: relax_sdp.c:92
#define TIMEOFDAY_CALL(x)
Definition: relax_sdp.c:102
int SCIPrelaxSdpGetNprimalSlaterHolds(SCIP_RELAX *relax)
Definition: relax_sdp.c:5448
SCIP_Real SCIPconsSavesdpsolGetMaxPrimalEntry(SCIP *scip, SCIP_CONS *cons)
static SCIP_Bool allVarsFixed(SCIP *scip)
Definition: relax_sdp.c:3452
#define DEFAULT_SLATERCHECK
Definition: relax_sdp.c:82
#define WARMSTART_PREOPT_MIN_Z_LPVAL
Definition: relax_sdp.c:99
int SCIPrelaxSdpGetNSdpPenalty(SCIP_RELAX *relax)
Definition: relax_sdp.c:5382
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:3553
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:5404
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:3328
SDP-relaxator.
#define RELAX_PRIORITY
Definition: relax_sdp.c:66
int SCIPrelaxSdpGetNSdpUnsolved(SCIP_RELAX *relax)
Definition: relax_sdp.c:5393
#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:2454
SCIP_Bool SCIPsdpiFeasibilityKnown(SCIP_SDPI *sdpi)
Definition: sdpi.c:2878
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:4190
SCIP_RETCODE SCIPsdpiGetPrimalNonzeros(SCIP_SDPI *sdpi, int nblocks, int *startXnblocknonz)
Definition: sdpi.c:3523
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:3476
SCIP_VAR * SCIPsdpVarmapperGetSCIPvar(SdpVarmapper *varmapper, int ind)
Definition: SdpVarmapper.c:237
SCIP_RETCODE SCIPsdpiGetIterations(SCIP_SDPI *sdpi, int *iterations)
Definition: sdpi.c:3592
#define DEFAULT_SETTINGSRESETFREQ
Definition: relax_sdp.c:89
SCIP_RETCODE SCIPsdpiSettingsUsed(SCIP_SDPI *sdpi, SCIP_SDPSOLVERSETTING *usedsetting)
Definition: sdpi.c:3620
SCIP_RETCODE SCIPsdpiSlaterSettings(SCIP_SDPI *sdpi, SCIP_SDPSLATERSETTING *slatersetting)
Definition: sdpi.c:3657
int SCIPrelaxSdpGetNdualSlaterFails(SCIP_RELAX *relax)
Definition: relax_sdp.c:5415
SCIP_Bool SCIPsdpiIsAcceptable(SCIP_SDPI *sdpi)
Definition: sdpi.c:3216
int SCIPsdpVarmapperGetNVars(SdpVarmapper *varmapper)
Definition: SdpVarmapper.c:203
static SCIP_DECL_RELAXINITSOL(relaxInitSolSdp)
Definition: relax_sdp.c:3637
int SCIPrelaxSdpGetNSdpStable(SCIP_RELAX *relax)
Definition: relax_sdp.c:5371
SCIP_RETCODE SCIPconsSdpComputeSparseSdpMatrix(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, int *length, int *row, int *col, SCIP_Real *val)
Definition: cons_sdp.c:2945
int SCIPrelaxSdpGetNSdpMedium(SCIP_RELAX *relax)
Definition: relax_sdp.c:5360
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:3130
SCIP_RETCODE SCIPrelaxSdpRelaxVal(SCIP_RELAX *relax, SCIP_Bool *success, SCIP_Real *objval)
Definition: relax_sdp.c:5188
SCIP_Bool SCIPsdpiIsDualInfeasible(SCIP_SDPI *sdpi)
Definition: sdpi.c:3018
General interface methods for SDP-preprocessing (mainly fixing variables and removing empty rows/cols...
int SCIPrelaxSdpGetNSlaterFailsFast(SCIP_RELAX *relax)
Definition: relax_sdp.c:5558
static SCIP_DECL_RELAXFREE(relaxFreeSdp)
Definition: relax_sdp.c:4266
struct Sdpvarmapper SdpVarmapper
Definition: SdpVarmapper.h:48
int SCIPrelaxSdpGetNSlaterFailsStable(SCIP_RELAX *relax)
Definition: relax_sdp.c:5569
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:5338
int SCIPrelaxSdpGetNSlaterHolds(SCIP_RELAX *relax)
Definition: relax_sdp.c:5481
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:5327
Constraint handler for SDP-constraints.
SCIP_RETCODE SCIPsdpiGetLowerObjbound(SCIP_SDPI *sdpi, SCIP_Real *objlb)
Definition: sdpi.c:3278
SCIP_Bool SCIPsdpiIsObjlimExc(SCIP_SDPI *sdpi)
Definition: sdpi.c:3086
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:2882
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:2524
int SCIPconsSdpCompLowerTriangPos(int i, int j)
Definition: cons_sdp.c:2507
int SCIPrelaxSdpGetNSlaterHoldsUnsolved(SCIP_RELAX *relax)
Definition: relax_sdp.c:5536
#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:5624
int SCIPrelaxSdpGetNdualSlaterUnknown(SCIP_RELAX *relax)
Definition: relax_sdp.c:5437
#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:4199
SCIP_RETCODE SCIPsdpiSetIntpar(SCIP_SDPI *sdpi, SCIP_SDPPARAM type, int ival)
Definition: sdpi.c:4158
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:5271
SCIP_Real SCIPsdpiInfinity(SCIP_SDPI *sdpi)
Definition: sdpi.c:4005
#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:5243
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:5580
int SCIPrelaxSdpGetNSdpFast(SCIP_RELAX *relax)
Definition: relax_sdp.c:5349
SCIP_Bool SCIPrelaxSdpSolvedOrig(SCIP_RELAX *relax)
Definition: relax_sdp.c:5254
#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:5492
int SCIPrelaxSdpGetNSlaterInfeasiblePenalty(SCIP_RELAX *relax)
Definition: relax_sdp.c:5635
#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:2916
SCIP_Bool SCIPsdpiWasSolved(SCIP_SDPI *sdpi)
Definition: sdpi.c:2855
int SCIPrelaxSdpGetNIterations(SCIP_RELAX *relax)
Definition: relax_sdp.c:5316
int SCIPrelaxSdpGetNSlaterFails(SCIP_RELAX *relax)
Definition: relax_sdp.c:5547
SCIP_RETCODE SCIPsdpiComputeMaxPenaltyparam(SCIP_SDPI *sdpi, SCIP_Real penaltyparam, SCIP_Real *maxpenaltyparam)
Definition: sdpi.c:4213
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:5210
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:3417
int SCIPconsSdpGetBlocksize(SCIP *scip, SCIP_CONS *cons)
Definition: cons_sdp.c:2645
int SCIPrelaxSdpGetNSlaterHoldsBounded(SCIP_RELAX *relax)
Definition: relax_sdp.c:5525
int SCIPrelaxSdpGetNprimalSlaterFails(SCIP_RELAX *relax)
Definition: relax_sdp.c:5459
int SCIPrelaxSdpGetNSlaterInfeasibleBounded(SCIP_RELAX *relax)
Definition: relax_sdp.c:5646
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:5163
#define DEFAULT_LAMBDASTAR
Definition: relax_sdp.c:71
static SCIP_RETCODE scaleTransposedMatrix(int blocksize, SCIP_Real *matrix, SCIP_Real *scale)
Definition: relax_sdp.c:259
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:3042
struct SCIP_SDPi SCIP_SDPI
Definition: type_sdpi.h:114
SCIP_Bool SCIPsdpiIsPrimalFeasible(SCIP_SDPI *sdpi)
Definition: sdpi.c:2970
SCIP_Bool SCIPrelaxSdpIsFeasible(SCIP_RELAX *relax)
Definition: relax_sdp.c:5288
SCIP_RETCODE SCIPsdpiSetRealpar(SCIP_SDPI *sdpi, SCIP_SDPPARAM type, SCIP_Real dval)
Definition: sdpi.c:4076
SCIP_Longint SCIPconsSavesdpsolGetNodeIndex(SCIP *scip, SCIP_CONS *cons)
int SCIPrelaxSdpGetNSlaterFailsUnsolved(SCIP_RELAX *relax)
Definition: relax_sdp.c:5602
#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:3582
#define RELAX_NAME
Definition: relax_sdp.c:64
SCIP_RETCODE SCIPconsSdpGetNNonz(SCIP *scip, SCIP_CONS *cons, int *nnonz, int *constnnonz)
Definition: cons_sdp.c:2620
SCIP_Bool SCIPrelaxSdpIsUnbounded(SCIP_RELAX *relax)
Definition: relax_sdp.c:5299
SCIP_RETCODE SCIPsdpiGetRealpar(SCIP_SDPI *sdpi, SCIP_SDPPARAM type, SCIP_Real *dval)
Definition: sdpi.c:4026
static SCIP_RETCODE putSdpDataInInterface(SCIP *scip, SCIP_SDPI *sdpi, SdpVarmapper *varmapper, SCIP_Bool primalobj, SCIP_Bool boundprimal)
Definition: relax_sdp.c:285
int SCIPrelaxSdpGetNdualSlaterInfeasible(SCIP_RELAX *relax)
Definition: relax_sdp.c:5426
SCIP_Real SCIPsdpiGetDefaultSdpiSolverGaptol(void)
Definition: sdpi.c:1412
SCIP_RETCODE SCIPsdpiGetPreoptimalPrimalNonzeros(SCIP_SDPI *sdpi, int nblocks, int *startXnblocknonz)
Definition: sdpi.c:3379
SCIP_RETCODE SCIPrelaxSdpComputeAnalyticCenters(SCIP *scip, SCIP_RELAX *relax)
Definition: relax_sdp.c:4448
static SCIP_RETCODE expandSparseMatrix(int nnonz, int blocksize, int *row, int *col, SCIP_Real *val, SCIP_Real *fullmat)
Definition: relax_sdp.c:222
#define DEFAULT_WARMSTART
Definition: relax_sdp.c:87
int SCIPrelaxSdpGetNSlaterHoldsPenalty(SCIP_RELAX *relax)
Definition: relax_sdp.c:5514
#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:528
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:3491
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:5470
SCIP_RETCODE SCIPconsSdpGuessInitialPoint(SCIP *scip, SCIP_CONS *cons, SCIP_Real *lambdastar)
Definition: cons_sdp.c:2770
int SCIPrelaxSdpGetNSlaterInfeasibleUnsolved(SCIP_RELAX *relax)
Definition: relax_sdp.c:5657
SCIP_Bool SCIPsdpiSolvedOrig(SCIP_SDPI *sdpi)
Definition: sdpi.c:2865
SCIP_RETCODE SCIPsdpiSlater(SCIP_SDPI *sdpi, SCIP_SDPSLATER *primalslater, SCIP_SDPSLATER *dualslater)
Definition: sdpi.c:3962
#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:4290
#define DEFAULT_WARMSTART_PREOPTIMAL_SOL
Definition: relax_sdp.c:79
constraint handler for saving SDP settings