SCIP-SDP  3.2.0
cons_savesdpsol.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-2020 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-2020 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 /*#define SCIP_MORE_DEBUG *//* shows all cuts added */
40 
41 #include "cons_savesdpsol.h"
42 #include "scip/def.h" /* for SCIP_Real, _Bool, ... */
43 #include <string.h>
44 #include <assert.h>
45 
46 /* constraint handler properties */
47 #define CONSHDLR_NAME "Savesdpsol"
48 #define CONSHDLR_DESC "saving the SDP solution at each node of the tree constraint handler"
49 #define CONSHDLR_ENFOPRIORITY 0
50 #define CONSHDLR_CHECKPRIORITY 0
51 #define CONSHDLR_EAGERFREQ 100
53 #define CONSHDLR_NEEDSCONS TRUE
56 struct SCIP_ConsData
57 {
58  SCIP_Longint node;
59  SCIP_SOL* sol;
60  SCIP_Real maxprimalentry;
61  int nblocks;
62  int* startXnblocknonz;
64  int** startXrow;
66  int** startXcol;
68  SCIP_Real** startXval;
70 };
71 
73 static
74 SCIP_DECL_CONSDELETE(consDeleteSavesdpsol)
75 { /*lint --e{715}*/
76  int b;
77 
78  assert( scip != NULL );
79  assert( conshdlr != NULL );
80  assert( cons != NULL );
81  assert( consdata != NULL );
82  assert( *consdata != NULL );
83 
84  SCIPdebugMsg(scip, "Deleting store node data constraint: <%s>.\n", SCIPconsGetName(cons));
85 
86  for (b = 0; b < (*consdata)->nblocks; b++)
87  {
88  SCIPfreeBlockMemoryArray(scip, &((*consdata)->startXval[b]), (*consdata)->startXnblocknonz[b]);
89  SCIPfreeBlockMemoryArray(scip, &((*consdata)->startXcol[b]), (*consdata)->startXnblocknonz[b]);
90  SCIPfreeBlockMemoryArray(scip, &((*consdata)->startXrow[b]), (*consdata)->startXnblocknonz[b]);
91  }
92  SCIPfreeBlockMemoryArray(scip, &((*consdata)->startXval), (*consdata)->nblocks);
93  SCIPfreeBlockMemoryArray(scip, &((*consdata)->startXcol), (*consdata)->nblocks);
94  SCIPfreeBlockMemoryArray(scip, &((*consdata)->startXrow), (*consdata)->nblocks);
95  SCIPfreeBlockMemoryArray(scip, &((*consdata)->startXnblocknonz), (*consdata)->nblocks);
96 
97  SCIP_CALL( SCIPfreeSol(scip, &((*consdata)->sol)) );
98  SCIPfreeBlockMemory(scip, consdata);
99 
100  return SCIP_OKAY;
101 }
102 
103 
105 static
106 SCIP_DECL_CONSENFORELAX(consEnforelaxSavesdpsol)
107 { /*lint --e{715}*/
108  assert( scip != NULL );
109  assert( conshdlr != NULL );
110  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
111  assert( result != NULL );
112 
113  /* do nothing */
114  *result = SCIP_FEASIBLE;
115 
116  return SCIP_OKAY;
117 }
118 
119 
121 static
122 SCIP_DECL_CONSENFOLP(consEnfolpSavesdpsol)
123 { /*lint --e{715}*/
124  assert( scip != NULL );
125  assert( conshdlr != NULL );
126  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
127  assert( result != NULL );
128 
129  /* do nothing */
130  *result = SCIP_FEASIBLE;
131 
132  return SCIP_OKAY;
133 }
134 
135 
137 static
138 SCIP_DECL_CONSENFOPS(consEnfopsSavesdpsol)
139 { /*lint --e{715}*/
140  assert( scip != NULL );
141  assert( conshdlr != NULL );
142  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
143  assert( result != NULL );
144 
145  /* do nothing */
146  *result = SCIP_FEASIBLE;
147 
148  return SCIP_OKAY;
149 }
150 
151 
153 static
154 SCIP_DECL_CONSCHECK(consCheckSavesdpsol)
155 { /*lint --e{715}*/
156  assert( scip != NULL );
157  assert( conshdlr != NULL );
158  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
159  assert( result != NULL );
160 
161  /* do nothing */
162  *result = SCIP_FEASIBLE;
163 
164  return SCIP_OKAY;
165 }
166 
167 
169 static
170 SCIP_DECL_CONSLOCK(consLockSavesdpsol)
171 { /*lint --e{715}*/
172  assert( scip != NULL );
173  assert( conshdlr != NULL );
174  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
175 
176  /* do nothing */
177  return SCIP_OKAY;
178 }
179 
180 
182 static
183 SCIP_DECL_CONSHDLRCOPY(conshdlrCopySavesdpsol)
184 { /*lint --e{715}*/
185  assert( scip != NULL );
186  assert( conshdlr != NULL );
187  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
188  assert( valid != NULL );
189 
190  /* call inclusion method of constraint handler */
191  SCIP_CALL( SCIPincludeConshdlrSavesdpsol(scip) );
192 
193  *valid = TRUE;
194 
195  return SCIP_OKAY;
196 }
197 
198 
200 static
201 SCIP_DECL_CONSCOPY(consCopySavesdpsol)
202 { /*lint --e{715}*/
203  /* do not do anything: no Savesdpsol constraint should be present in the copy */
204  return SCIP_OKAY;
205 }
206 
207 
209 SCIP_RETCODE SCIPincludeConshdlrSavesdpsol(
210  SCIP* scip
211  )
212 {
213  SCIP_CONSHDLR* conshdlr;
214 
215  /* include constraint handler */
216  conshdlr = NULL;
217  SCIP_CALL( SCIPincludeConshdlrBasic(scip, &conshdlr, CONSHDLR_NAME, CONSHDLR_DESC,
219  consEnfolpSavesdpsol, consEnfopsSavesdpsol, consCheckSavesdpsol, consLockSavesdpsol,
220  NULL) );
221  assert( conshdlr != NULL );
222 
223  /* set additional callbacks */
224  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteSavesdpsol) );
225  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopySavesdpsol, consCopySavesdpsol) );
226  SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxSavesdpsol) );
227 
228  return SCIP_OKAY;
229 }
230 
231 
232 /*
233  * External functions
234  */
235 
237 SCIP_RETCODE createConsSavesdpsol(
238  SCIP* scip,
239  SCIP_CONS** cons,
240  const char* name,
241  SCIP_Longint node,
242  SCIP_SOL* sol,
243  SCIP_Real maxprimalentry,
244  int nblocks,
245  int* startXnblocknonz,
247  int** startXrow,
249  int** startXcol,
251  SCIP_Real** startXval
253  )
254 {
255  SCIP_CONSDATA* consdata = NULL;
256  SCIP_CONSHDLR* conshdlr;
257  int b;
258 
259  assert( scip != NULL );
260  assert( name != NULL );
261  assert( sol != NULL );
262  assert( nblocks >= 0 );
263  assert( nblocks == 0 || startXnblocknonz != NULL );
264  assert( nblocks == 0 || startXrow != NULL );
265  assert( nblocks == 0 || startXcol != NULL );
266  assert( nblocks == 0 || startXval != NULL );
267 
268  SCIPdebugMsg(scip, "Creating Savesdpsol constraint <%s>.\n", name);
269 
270  /* find the node data constraint handler */
271  conshdlr = SCIPfindConshdlr(scip, "Savesdpsol");
272  if ( conshdlr == NULL )
273  {
274  SCIPerrorMessage("Savesdpsol constraint handler not found\n");
275  return SCIP_PLUGINNOTFOUND;
276  }
277 
278  /* create constraint data */
279  SCIP_CALL( SCIPallocBlockMemory(scip, &consdata) );
280 
281  consdata->node = node;
282  SCIP_CALL( SCIPcreateSolCopy(scip, &(consdata->sol), sol) );
283  SCIP_CALL( SCIPunlinkSol(scip, consdata->sol) );
284  consdata->maxprimalentry = maxprimalentry;
285 
286  /* allocate memory for primal solution and copy startXnblocknonz*/
287  if ( startXnblocknonz != NULL )
288  {
289  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->startXnblocknonz, startXnblocknonz, nblocks) );
290  }
291  else
292  consdata->startXnblocknonz = NULL;
293 
294  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->startXrow, nblocks) );
295  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->startXcol, nblocks) );
296  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->startXval, nblocks) );
297 
298  for (b = 0; b < nblocks; b++)
299  {
300  assert( startXnblocknonz != NULL );
301  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->startXrow[b], startXrow[b], startXnblocknonz[b]) );
302  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->startXcol[b], startXcol[b], startXnblocknonz[b]) );
303  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->startXval[b], startXval[b], startXnblocknonz[b]) );
304  }
305 
306  consdata->nblocks = nblocks;
307 
308  /* create constraint */
309  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, FALSE, FALSE, FALSE, FALSE, FALSE,
310  TRUE, FALSE, TRUE, FALSE, TRUE));
311 
312  return SCIP_OKAY;
313 }
314 
316 SCIP_Longint SCIPconsSavesdpsolGetNodeIndex(
317  SCIP* scip,
318  SCIP_CONS* cons
319  )
320 {
321  SCIP_CONSDATA* consdata;
322 
323  assert ( scip != NULL );
324  assert ( cons != NULL );
325 
326  consdata = SCIPconsGetData(cons);
327 
328  assert ( consdata != NULL );
329 
330  return consdata->node;
331 }
332 
335  SCIP* scip,
336  SCIP_CONS* cons
337  )
338 {
339  SCIP_CONSDATA* consdata;
340 
341  assert ( scip != NULL );
342  assert ( cons != NULL );
343 
344  consdata = SCIPconsGetData(cons);
345 
346  assert ( consdata != NULL );
347 
348  return consdata->sol;
349 }
350 
353  SCIP* scip,
354  SCIP_CONS* cons
355  )
356 {
357  SCIP_CONSDATA* consdata;
358 
359  assert ( scip != NULL );
360  assert ( cons != NULL );
361 
362  consdata = SCIPconsGetData(cons);
363 
364  assert ( consdata != NULL );
365 
366  return consdata->maxprimalentry;
367 }
368 
371  SCIP* scip,
372  SCIP_CONS* cons,
373  int nblocks,
374  int* startXnblocknonz
376  )
377 {
378  SCIP_CONSDATA* consdata;
379  int b;
380 
381  assert ( scip != NULL );
382  assert ( cons != NULL );
383 
384  consdata = SCIPconsGetData(cons);
385 
386  assert ( consdata != NULL );
387 
388  if ( nblocks != consdata->nblocks )
389  {
390  SCIPerrorMessage("SCIPconsSavesdpsolGetPrimalMatrix expected nblocks = %d but got %d\n", consdata->nblocks, nblocks);
391  return SCIP_ERROR;
392  }
393 
394  for (b = 0; b < nblocks; b++)
395  startXnblocknonz[b] = consdata->startXnblocknonz[b];
396 
397  return SCIP_OKAY;
398 }
399 
402  SCIP* scip,
403  SCIP_CONS* cons,
404  int nblocks,
405  int* startXnblocknonz,
407  int** startXrow,
408  int** startXcol,
409  SCIP_Real** startXval
410  )
411 {
412  SCIP_CONSDATA* consdata;
413  int b;
414  int i;
415  SCIP_Bool msgthrown = FALSE;
416 
417  assert ( scip != NULL );
418  assert ( cons != NULL );
419 
420  consdata = SCIPconsGetData(cons);
421 
422  assert ( consdata != NULL );
423 
424  if ( nblocks != consdata->nblocks )
425  {
426  SCIPerrorMessage("SCIPconsSavesdpsolGetPrimalMatrix expected nblocks = %d but got %d\n", consdata->nblocks, nblocks);
427  return SCIP_ERROR;
428  }
429 
430  for (b = 0; b < nblocks; b++)
431  {
432  if ( startXnblocknonz[b] < consdata->startXnblocknonz[b] )
433  {
434  if ( ! msgthrown )
435  {
436  SCIPdebugMsg(scip, "Unsufficient arraylength %d for block %d in SCIPconsSavesdpsolGetPrimalMatrix, need at least %d!\n",
437  startXnblocknonz[b], b, consdata->startXnblocknonz[b]);
438  msgthrown = TRUE;
439  }
440  startXnblocknonz[b] = consdata->startXnblocknonz[b];
441  }
442  else
443  {
444  startXnblocknonz[b] = consdata->startXnblocknonz[b];
445  for (i = 0; i < consdata->startXnblocknonz[b]; i++)
446  {
447  startXrow[b][i] = consdata->startXrow[b][i];
448  startXcol[b][i] = consdata->startXcol[b][i];
449  startXval[b][i] = consdata->startXval[b][i];
450  }
451  }
452  }
453 
454  return SCIP_OKAY;
455 }
#define CONSHDLR_NEEDSCONS
static SCIP_DECL_CONSENFOLP(consEnfolpSavesdpsol)
SCIP_Real SCIPconsSavesdpsolGetMaxPrimalEntry(SCIP *scip, SCIP_CONS *cons)
static SCIP_DECL_CONSENFORELAX(consEnforelaxSavesdpsol)
SCIP_RETCODE SCIPconsSavesdpsolGetPrimalMatrixNonzeros(SCIP *scip, SCIP_CONS *cons, int nblocks, int *startXnblocknonz)
#define CONSHDLR_CHECKPRIORITY
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_SOL * SCIPconsSavesdpsolGetDualVector(SCIP *scip, SCIP_CONS *cons)
static SCIP_DECL_CONSCOPY(consCopySavesdpsol)
static SCIP_DECL_CONSLOCK(consLockSavesdpsol)
#define CONSHDLR_ENFOPRIORITY
static SCIP_DECL_CONSENFOPS(consEnfopsSavesdpsol)
static SCIP_DECL_CONSDELETE(consDeleteSavesdpsol)
#define CONSHDLR_EAGERFREQ
SCIP_RETCODE SCIPconsSavesdpsolGetPrimalMatrix(SCIP *scip, SCIP_CONS *cons, int nblocks, int *startXnblocknonz, int **startXrow, int **startXcol, SCIP_Real **startXval)
static SCIP_DECL_CONSCHECK(consCheckSavesdpsol)
SCIP_RETCODE SCIPincludeConshdlrSavesdpsol(SCIP *scip)
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopySavesdpsol)
SCIP_Longint SCIPconsSavesdpsolGetNodeIndex(SCIP *scip, SCIP_CONS *cons)
#define CONSHDLR_DESC
#define CONSHDLR_NAME
char name[SCIP_MAXSTRLEN]
constraint handler for saving SDP solutions in nodes