SCIP-SDP  3.1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
sdpsolchecker.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of SCIPSDP - a solving framework for mixed-integer */
4 /* semidefinite programs based on SCIP. */
5 /* */
6 /* Copyright (C) 2011-2013 Discrete Optimization, TU Darmstadt */
7 /* EDOM, FAU Erlangen-Nürnberg */
8 /* 2014-2017 Discrete Optimization, TU Darmstadt */
9 /* */
10 /* */
11 /* This program is free software; you can redistribute it and/or */
12 /* modify it under the terms of the GNU Lesser General Public License */
13 /* as published by the Free Software Foundation; either version 3 */
14 /* of the License, or (at your option) any later version. */
15 /* */
16 /* This program is distributed in the hope that it will be useful, */
17 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
18 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
19 /* GNU Lesser General Public License for more details. */
20 /* */
21 /* You should have received a copy of the GNU Lesser General Public License */
22 /* along with this program; if not, write to the Free Software */
23 /* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.*/
24 /* */
25 /* */
26 /* Based on SCIP - Solving Constraint Integer Programs */
27 /* Copyright (C) 2002-2017 Zuse Institute Berlin */
28 /* SCIP is distributed under the terms of the SCIP Academic Licence, */
29 /* see file COPYING in the SCIP distribution. */
30 /* */
31 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
32 
38 /*#define SCIP_DEBUG*/
39 
40 #include "sdpi/sdpsolchecker.h"
41 #include "sdpi/lapack.h"
42 
44 #define BMS_CALL(x) do \
45  { \
46  if( NULL == (x) ) \
47  { \
48  SCIPerrorMessage("No memory in function call.\n"); \
49  return SCIP_NOMEMORY; \
50  } \
51  } \
52  while( FALSE )
53 
58  BMS_BUFMEM* bufmem,
59  int nvars,
60  SCIP_Real* lb,
61  SCIP_Real* ub,
62  int nsdpblocks,
63  int* sdpblocksizes,
64  int* sdpnblockvars,
65  int sdpconstnnonz,
66  int* sdpconstnblocknonz,
68  int** sdpconstrow,
69  int** sdpconstcol,
70  SCIP_Real** sdpconstval,
71  int sdpnnonz,
72  int** sdpnblockvarnonz,
74  int** sdpvar,
76  int*** sdprow,
77  int*** sdpcol,
78  SCIP_Real*** sdpval,
79  int** indchanges,
81  int* nremovedinds,
82  int* blockindchanges,
83  int nlpcons,
84  int noldlpcons,
85  SCIP_Real* lplhs,
86  SCIP_Real* lprhs,
87  int* rownactivevars,
88  int lpnnonz,
89  int* lprow,
90  int* lpcol,
91  SCIP_Real* lpval,
92  SCIP_Real* solvector,
93  SCIP_Real feastol,
94  SCIP_Real epsilon,
95  SCIP_Bool* infeasible
96 )
97 {/*lint --e{818}*/
98  int i;
99  int j;
100  int b;
101  int v;
102  int ind;
103 
104  assert( bufmem != NULL );
105  assert( lb != NULL );
106  assert( ub != NULL );
107  assert( nsdpblocks >= 0 );
108  assert( nsdpblocks == 0 || sdpblocksizes != NULL );
109  assert( nsdpblocks == 0 || sdpnblockvars != NULL );
110  assert( sdpconstnnonz >= 0 );
111  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstnblocknonz != NULL );
112  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstrow != NULL );
113  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstcol != NULL );
114  assert( nsdpblocks == 0 || sdpconstnnonz == 0 || sdpconstval != NULL );
115  assert( sdpnnonz >= 0 );
116  assert( nsdpblocks == 0 || sdpnblockvarnonz != NULL );
117  assert( nsdpblocks == 0 || sdpvar != NULL );
118  assert( nsdpblocks == 0 || sdprow != NULL );
119  assert( nsdpblocks == 0 || sdpcol != NULL );
120  assert( nsdpblocks == 0 || sdpval != NULL );
121  assert( nsdpblocks == 0 || indchanges != NULL );
122  assert( nsdpblocks == 0 || nremovedinds != NULL );
123  assert( nsdpblocks == 0 || blockindchanges != NULL );
124  assert( nlpcons >= 0 );
125  assert( noldlpcons >= nlpcons );
126  assert( nlpcons == 0 || lplhs != NULL );
127  assert( nlpcons == 0 || lprhs != NULL );
128  assert( nlpcons == 0 || rownactivevars != NULL );
129  assert( lpnnonz >= 0 );
130  assert( nlpcons == 0 || lprow != NULL );
131  assert( nlpcons == 0 || lpcol != NULL );
132  assert( nlpcons == 0 || lpval != NULL );
133  assert( solvector != NULL );
134  assert( feastol >= 0 );
135  assert( infeasible != NULL );
136 
137  /* check variable bounds */
138  for (i = 0; i < nvars; i++)
139  {
140  if ( solvector[i] < lb[i] - feastol || solvector[i] > ub[i] + feastol )
141  {
142  SCIPdebugMessage("solution found infeasible (feastol=%f) for variable bounds: x[%d] = %f <|= [%f, %f]\n",
143  feastol, i, solvector[i], lb[i], ub[i]);
144  *infeasible = TRUE;
145  return SCIP_OKAY;
146  }
147  }
148 
149  /* check linear constraints (since DSDP sorts the lp-arrays by cols, we cannot expect them to be sorted) */
150  if ( nlpcons > 0 )
151  {
152  SCIP_Real* lpconsvals;
153 
154  BMS_CALL( BMSallocBufferMemoryArray(bufmem, &lpconsvals, noldlpcons) );
155 
156  /* initialize all rows with zero */
157  for (i = 0; i < noldlpcons; i++)
158  lpconsvals[i] = 0;
159 
160  /* compute the values of all rows */
161  for (i = 0; i < lpnnonz; i++)
162  {
163  if ( lb[lpcol[i]] < ub[lpcol[i]] - epsilon ) /* fixed variables are already included in lhs/rhs */
164  lpconsvals[lprow[i]] += solvector[lpcol[i]] * lpval[i];
165  }
166 
167  /* check all active constraints for feasibility */
168  ind = 0; /* used to iterate over active constraints */
169  for (i = 0; i < noldlpcons; i++)
170  {
171  if ( rownactivevars[i] > 1 )
172  {
173  if ( lpconsvals[i] < lplhs[ind] - feastol || lpconsvals[i] > lprhs[ind] + feastol)
174  {
175  SCIPdebugMessage("solution found infeasible (feastol=%f) for lp constraint: LP-%d = %f <|= [%f,%f]\n",
176  feastol, i, lpconsvals[i], lplhs[ind], lprhs[ind]);
177  BMSfreeBufferMemoryArray(bufmem, &lpconsvals);
178  *infeasible = TRUE;
179  return SCIP_OKAY;
180  }
181 
182  ind++;
183  }
184  }
185  BMSfreeBufferMemoryArray(bufmem, &lpconsvals);
186  }
187 
188  /* check sdp constraints */
189  if ( nsdpblocks > 0 )
190  {
191  SCIP_Real* fullsdpmatrix;
192  SCIP_Real eigenvalue;
193  int maxblocksize = 0;
194 
195  /* allocate memory */
196  if ( nsdpblocks == 1 )
197  maxblocksize = sdpblocksizes[0] - nremovedinds[0];
198  else
199  {
200  /* calculate maximum size of any SDP block to not have to reallocate memory in between */
201  for (b = 0; b < nsdpblocks; b++)
202  {
203  maxblocksize = ((sdpblocksizes[b] - nremovedinds[b]) > maxblocksize) ? sdpblocksizes[b] - nremovedinds[b] : maxblocksize;
204  }
205  }
206 
207  BMS_CALL( BMSallocBufferMemoryArray(bufmem, &fullsdpmatrix, maxblocksize * maxblocksize) );/*lint !e647*/
208 
209  for (b = 0; b < nsdpblocks; b++)
210  {
211  if ( blockindchanges[b] > -1 )
212  {
213  /* initialize lower triangular part of fullsdpmatrix with zero */
214  for (i = 0; i < sdpblocksizes[b] - nremovedinds[b]; i++)
215  {
216  for (j = 0; j <= i; j++)
217  {
218  fullsdpmatrix[i * (sdpblocksizes[b] - nremovedinds[b]) + j] = 0.0; /*lint !e679*/
219  }
220  }
221 
222  /* iterate over all non-fixed variables and add the corresponding nonzeros */
223  for (v = 0; v < sdpnblockvars[b]; v++)
224  {
225  if ( lb[sdpvar[b][v]] < ub[sdpvar[b][v]] - epsilon )
226  {
227  for (i = 0; i < sdpnblockvarnonz[b][v]; i++)
228  {
229  fullsdpmatrix[((sdprow[b][v][i] - indchanges[b][sdprow[b][v][i]]) * (sdpblocksizes[b] - nremovedinds[b])) +
230  sdpcol[b][v][i] - indchanges[b][sdpcol[b][v][i]]] += solvector[sdpvar[b][v]] * sdpval[b][v][i];/*lint !e679*/
231  }
232  }
233  }
234 
235  /* add constant matrix */
236  for (i = 0; i < sdpconstnblocknonz[b]; i++)
237  {
238  fullsdpmatrix[((sdpconstrow[b][i] - indchanges[b][sdpconstrow[b][i]]) * (sdpblocksizes[b] - nremovedinds[b])) +
239  sdpconstcol[b][i] - indchanges[b][sdpconstcol[b][i]]] -= sdpconstval[b][i];/*lint !e679*/
240  }
241 
242  /* extend to full symmetric matrix for LAPACK */
243  for (i = 0; i < sdpblocksizes[b] - nremovedinds[b]; i++)
244  {
245  for (j = 0; j < i; j++)
246  {
247  fullsdpmatrix[j * (sdpblocksizes[b] - nremovedinds[b]) + i] = fullsdpmatrix[i * (sdpblocksizes[b] - nremovedinds[b]) + j];/*lint !e679*/
248  }
249  }
250 
251  /* compute smallest eigenvalue using LAPACK */
252  SCIP_CALL( SCIPlapackComputeIthEigenvalue(bufmem, FALSE, sdpblocksizes[b] - nremovedinds[b], fullsdpmatrix, 1, &eigenvalue, NULL) );
253 
254  if ( eigenvalue < - feastol )
255  {
256  SCIPdebugMessage("solution found infeasible (feastol=%.10f) for sdp constraint %d, smallest eigenvector %.10f\n",
257  feastol, b, eigenvalue);
258  BMSfreeBufferMemoryArray(bufmem, &fullsdpmatrix);
259  *infeasible = TRUE;
260  return SCIP_OKAY;
261  }
262  }
263  }
264 
265  BMSfreeBufferMemoryArray(bufmem, &fullsdpmatrix);
266  }
267 
268  *infeasible = FALSE;
269  return SCIP_OKAY;
270 }
EXTERN SCIP_RETCODE SCIPlapackComputeIthEigenvalue(BMS_BUFMEM *bufmem, SCIP_Bool geteigenvectors, int n, SCIP_Real *A, int i, SCIP_Real *eigenvalue, SCIP_Real *eigenvector)
#define BMS_CALL(x)
Definition: sdpsolchecker.c:44
SCIP_RETCODE SCIPsdpSolcheckerCheck(BMS_BUFMEM *bufmem, int nvars, SCIP_Real *lb, SCIP_Real *ub, int nsdpblocks, int *sdpblocksizes, int *sdpnblockvars, int sdpconstnnonz, int *sdpconstnblocknonz, int **sdpconstrow, int **sdpconstcol, SCIP_Real **sdpconstval, int sdpnnonz, int **sdpnblockvarnonz, int **sdpvar, int ***sdprow, int ***sdpcol, SCIP_Real ***sdpval, int **indchanges, int *nremovedinds, int *blockindchanges, int nlpcons, int noldlpcons, SCIP_Real *lplhs, SCIP_Real *lprhs, int *rownactivevars, int lpnnonz, int *lprow, int *lpcol, SCIP_Real *lpval, SCIP_Real *solvector, SCIP_Real feastol, SCIP_Real epsilon, SCIP_Bool *infeasible)
Definition: sdpsolchecker.c:57
checks a given SDP solution for feasibility
interface methods for eigenvector computation and matrix multiplication using different versions of L...