1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2021 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not visit scipopt.org. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15
16 /**@file relax.c
17 * @ingroup OTHER_CFILES
18 * @brief methods and datastructures for relaxation handlers
19 * @author Tobias Achterberg
20 * @author Timo Berthold
21 */
22
23 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
24
25 #include <assert.h>
26 #include <string.h>
27
28 #include "scip/def.h"
29 #include "scip/set.h"
30 #include "scip/tree.h"
31 #include "scip/stat.h"
32 #include "scip/clock.h"
33 #include "scip/paramset.h"
34 #include "scip/scip.h"
35 #include "scip/sol.h"
36 #include "scip/var.h"
37 #include "scip/relax.h"
38 #include "scip/pub_message.h"
39 #include "scip/pub_misc.h"
40
41 #include "scip/struct_relax.h"
42
43
44
45 /** compares two relaxation handlers w. r. to their priority */
SCIP_DECL_SORTPTRCOMP(SCIPrelaxComp)46 SCIP_DECL_SORTPTRCOMP(SCIPrelaxComp)
47 { /*lint --e{715}*/
48 return ((SCIP_RELAX*)elem2)->priority - ((SCIP_RELAX*)elem1)->priority;
49 }
50
51 /** comparison method for sorting relaxators w.r.t. to their name */
SCIP_DECL_SORTPTRCOMP(SCIPrelaxCompName)52 SCIP_DECL_SORTPTRCOMP(SCIPrelaxCompName)
53 {
54 return strcmp(SCIPrelaxGetName((SCIP_RELAX*)elem1), SCIPrelaxGetName((SCIP_RELAX*)elem2));
55 }
56
57 /** method to call, when the priority of a relaxation handler was changed */
58 static
SCIP_DECL_PARAMCHGD(paramChgdRelaxPriority)59 SCIP_DECL_PARAMCHGD(paramChgdRelaxPriority)
60 { /*lint --e{715}*/
61 SCIP_PARAMDATA* paramdata;
62
63 paramdata = SCIPparamGetData(param);
64 assert(paramdata != NULL);
65
66 /* use SCIPsetRelaxPriority() to mark the relaxs unsorted */
67 SCIP_CALL( SCIPsetRelaxPriority(scip, (SCIP_RELAX*)paramdata, SCIPparamGetInt(param)) ); /*lint !e740*/
68
69 return SCIP_OKAY;
70 }
71
72 /** copies the given relaxation handler to a new scip */
SCIPrelaxCopyInclude(SCIP_RELAX * relax,SCIP_SET * set)73 SCIP_RETCODE SCIPrelaxCopyInclude(
74 SCIP_RELAX* relax, /**< relaxation handler */
75 SCIP_SET* set /**< SCIP_SET of SCIP to copy to */
76 )
77 {
78 assert(relax != NULL);
79 assert(set != NULL);
80 assert(set->scip != NULL);
81
82 if( relax->relaxcopy != NULL )
83 {
84 SCIPsetDebugMsg(set, "including relaxation handler %s in subscip %p\n", SCIPrelaxGetName(relax), (void*)set->scip);
85 SCIP_CALL( relax->relaxcopy(set->scip, relax) );
86 }
87 return SCIP_OKAY;
88 }
89
90 /** internal method for creating a relaxation handler */
91 static
doRelaxCreate(SCIP_RELAX ** relax,SCIP_SET * set,SCIP_MESSAGEHDLR * messagehdlr,BMS_BLKMEM * blkmem,const char * name,const char * desc,int priority,int freq,SCIP_DECL_RELAXCOPY ((* relaxcopy)),SCIP_DECL_RELAXFREE ((* relaxfree)),SCIP_DECL_RELAXINIT ((* relaxinit)),SCIP_DECL_RELAXEXIT ((* relaxexit)),SCIP_DECL_RELAXINITSOL ((* relaxinitsol)),SCIP_DECL_RELAXEXITSOL ((* relaxexitsol)),SCIP_DECL_RELAXEXEC ((* relaxexec)),SCIP_RELAXDATA * relaxdata)92 SCIP_RETCODE doRelaxCreate(
93 SCIP_RELAX** relax, /**< pointer to relaxation handler data structure */
94 SCIP_SET* set, /**< global SCIP settings */
95 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
96 BMS_BLKMEM* blkmem, /**< block memory for parameter settings */
97 const char* name, /**< name of relaxation handler */
98 const char* desc, /**< description of relaxation handler */
99 int priority, /**< priority of the relaxation handler (negative: after LP, non-negative: before LP) */
100 int freq, /**< frequency for calling relaxation handler */
101 SCIP_DECL_RELAXCOPY ((*relaxcopy)), /**< copy method of relaxation handler or NULL if you don't want to copy your plugin into sub-SCIPs */
102 SCIP_DECL_RELAXFREE ((*relaxfree)), /**< destructor of relaxation handler */
103 SCIP_DECL_RELAXINIT ((*relaxinit)), /**< initialize relaxation handler */
104 SCIP_DECL_RELAXEXIT ((*relaxexit)), /**< deinitialize relaxation handler */
105 SCIP_DECL_RELAXINITSOL((*relaxinitsol)), /**< solving process initialization method of relaxation handler */
106 SCIP_DECL_RELAXEXITSOL((*relaxexitsol)), /**< solving process deinitialization method of relaxation handler */
107 SCIP_DECL_RELAXEXEC ((*relaxexec)), /**< execution method of relaxation handler */
108 SCIP_RELAXDATA* relaxdata /**< relaxation handler data */
109 )
110 {
111 char paramname[SCIP_MAXSTRLEN];
112 char paramdesc[SCIP_MAXSTRLEN];
113
114 assert(relax != NULL);
115 assert(name != NULL);
116 assert(desc != NULL);
117 assert(freq >= -1);
118 assert(relaxexec != NULL);
119
120 SCIP_ALLOC( BMSallocMemory(relax) );
121 BMSclearMemory(*relax);
122
123 SCIP_ALLOC( BMSduplicateMemoryArray(&(*relax)->name, name, strlen(name)+1) );
124 SCIP_ALLOC( BMSduplicateMemoryArray(&(*relax)->desc, desc, strlen(desc)+1) );
125 (*relax)->priority = priority;
126 (*relax)->freq = freq;
127 (*relax)->relaxcopy = relaxcopy;
128 (*relax)->relaxfree = relaxfree;
129 (*relax)->relaxinit = relaxinit;
130 (*relax)->relaxexit = relaxexit;
131 (*relax)->relaxinitsol = relaxinitsol;
132 (*relax)->relaxexitsol = relaxexitsol;
133 (*relax)->relaxexec = relaxexec;
134 (*relax)->relaxdata = relaxdata;
135 SCIP_CALL( SCIPclockCreate(&(*relax)->setuptime, SCIP_CLOCKTYPE_DEFAULT) );
136 SCIP_CALL( SCIPclockCreate(&(*relax)->relaxclock, SCIP_CLOCKTYPE_DEFAULT) );
137 (*relax)->ncalls = 0;
138 (*relax)->ncutoffs = 0;
139 (*relax)->nimprbounds = 0;
140 (*relax)->imprtime = 0.0;
141 (*relax)->naddedconss = 0;
142 (*relax)->nreduceddom = 0;
143 (*relax)->nseparated = 0;
144 (*relax)->lastsolvednode = -1;
145 (*relax)->initialized = FALSE;
146
147 /* add parameters */
148 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "relaxing/%s/priority", name);
149 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "priority of relaxation handler <%s>", name);
150 SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc,
151 &(*relax)->priority, FALSE, priority, INT_MIN/4, INT_MAX/4,
152 paramChgdRelaxPriority, (SCIP_PARAMDATA*)(*relax)) ); /*lint !e740*/
153 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "relaxing/%s/freq", name);
154 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "frequency for calling relaxation handler <%s> (-1: never, 0: only in root node)", name);
155 SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc,
156 &(*relax)->freq, FALSE, freq, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
157
158 return SCIP_OKAY;
159 }
160
161 /** creates a relaxation handler */
SCIPrelaxCreate(SCIP_RELAX ** relax,SCIP_SET * set,SCIP_MESSAGEHDLR * messagehdlr,BMS_BLKMEM * blkmem,const char * name,const char * desc,int priority,int freq,SCIP_DECL_RELAXCOPY ((* relaxcopy)),SCIP_DECL_RELAXFREE ((* relaxfree)),SCIP_DECL_RELAXINIT ((* relaxinit)),SCIP_DECL_RELAXEXIT ((* relaxexit)),SCIP_DECL_RELAXINITSOL ((* relaxinitsol)),SCIP_DECL_RELAXEXITSOL ((* relaxexitsol)),SCIP_DECL_RELAXEXEC ((* relaxexec)),SCIP_RELAXDATA * relaxdata)162 SCIP_RETCODE SCIPrelaxCreate(
163 SCIP_RELAX** relax, /**< pointer to relaxation handler data structure */
164 SCIP_SET* set, /**< global SCIP settings */
165 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
166 BMS_BLKMEM* blkmem, /**< block memory for parameter settings */
167 const char* name, /**< name of relaxation handler */
168 const char* desc, /**< description of relaxation handler */
169 int priority, /**< priority of the relaxation handler (negative: after LP, non-negative: before LP) */
170 int freq, /**< frequency for calling relaxation handler */
171 SCIP_DECL_RELAXCOPY ((*relaxcopy)), /**< copy method of relaxation handler or NULL if you don't want to copy your plugin into sub-SCIPs */
172 SCIP_DECL_RELAXFREE ((*relaxfree)), /**< destructor of relaxation handler */
173 SCIP_DECL_RELAXINIT ((*relaxinit)), /**< initialize relaxation handler */
174 SCIP_DECL_RELAXEXIT ((*relaxexit)), /**< deinitialize relaxation handler */
175 SCIP_DECL_RELAXINITSOL((*relaxinitsol)), /**< solving process initialization method of relaxation handler */
176 SCIP_DECL_RELAXEXITSOL((*relaxexitsol)), /**< solving process deinitialization method of relaxation handler */
177 SCIP_DECL_RELAXEXEC ((*relaxexec)), /**< execution method of relaxation handler */
178 SCIP_RELAXDATA* relaxdata /**< relaxation handler data */
179 )
180 {
181 assert(relax != NULL);
182 assert(name != NULL);
183 assert(desc != NULL);
184 assert(freq >= -1);
185 assert(relaxexec != NULL);
186
187 SCIP_CALL_FINALLY( doRelaxCreate(relax, set, messagehdlr, blkmem, name, desc, priority, freq, relaxcopy, relaxfree,
188 relaxinit, relaxexit, relaxinitsol, relaxexitsol, relaxexec, relaxdata), (void) SCIPrelaxFree(relax, set) );
189
190 return SCIP_OKAY;
191 }
192
193 /** calls destructor and frees memory of relaxation handler */
SCIPrelaxFree(SCIP_RELAX ** relax,SCIP_SET * set)194 SCIP_RETCODE SCIPrelaxFree(
195 SCIP_RELAX** relax, /**< pointer to relaxation handler data structure */
196 SCIP_SET* set /**< global SCIP settings */
197 )
198 {
199 assert(relax != NULL);
200 if( *relax == NULL )
201 return SCIP_OKAY;
202 assert(!(*relax)->initialized);
203 assert(set != NULL);
204
205 /* call destructor of relaxation handler */
206 if( (*relax)->relaxfree != NULL )
207 {
208 SCIP_CALL( (*relax)->relaxfree(set->scip, *relax) );
209 }
210
211 SCIPclockFree(&(*relax)->relaxclock);
212 SCIPclockFree(&(*relax)->setuptime);
213 BMSfreeMemoryArrayNull(&(*relax)->name);
214 BMSfreeMemoryArrayNull(&(*relax)->desc);
215 BMSfreeMemory(relax);
216
217 return SCIP_OKAY;
218 }
219
220 /** initializes relaxation handler */
SCIPrelaxInit(SCIP_RELAX * relax,SCIP_SET * set)221 SCIP_RETCODE SCIPrelaxInit(
222 SCIP_RELAX* relax, /**< relaxation handler */
223 SCIP_SET* set /**< global SCIP settings */
224 )
225 {
226 assert(relax != NULL);
227 assert(set != NULL);
228
229 if( relax->initialized )
230 {
231 SCIPerrorMessage("relaxation handler <%s> already initialized\n", relax->name);
232 return SCIP_INVALIDCALL;
233 }
234
235 if( set->misc_resetstat )
236 {
237 SCIPclockReset(relax->setuptime);
238 SCIPclockReset(relax->relaxclock);
239 relax->ncalls = 0;
240 relax->ncutoffs = 0;
241 relax->nimprbounds = 0;
242 relax->imprtime = 0.0;
243 relax->naddedconss = 0;
244 relax->nreduceddom = 0;
245 relax->nseparated = 0;
246 relax->lastsolvednode = -1;
247 }
248
249 if( relax->relaxinit != NULL )
250 {
251 /* start timing */
252 SCIPclockStart(relax->setuptime, set);
253
254 SCIP_CALL( relax->relaxinit(set->scip, relax) );
255
256 /* stop timing */
257 SCIPclockStop(relax->setuptime, set);
258 }
259 relax->initialized = TRUE;
260
261 return SCIP_OKAY;
262 }
263
264 /** calls exit method of relaxation handler */
SCIPrelaxExit(SCIP_RELAX * relax,SCIP_SET * set)265 SCIP_RETCODE SCIPrelaxExit(
266 SCIP_RELAX* relax, /**< relaxation handler */
267 SCIP_SET* set /**< global SCIP settings */
268 )
269 {
270 assert(relax != NULL);
271 assert(set != NULL);
272
273 if( !relax->initialized )
274 {
275 SCIPerrorMessage("relaxation handler <%s> not initialized\n", relax->name);
276 return SCIP_INVALIDCALL;
277 }
278
279 if( relax->relaxexit != NULL )
280 {
281 /* start timing */
282 SCIPclockStart(relax->setuptime, set);
283
284 SCIP_CALL( relax->relaxexit(set->scip, relax) );
285
286 /* stop timing */
287 SCIPclockStop(relax->setuptime, set);
288 }
289 relax->initialized = FALSE;
290
291 return SCIP_OKAY;
292 }
293
294 /** informs relaxation handler that the branch and bound process is being started */
SCIPrelaxInitsol(SCIP_RELAX * relax,SCIP_SET * set)295 SCIP_RETCODE SCIPrelaxInitsol(
296 SCIP_RELAX* relax, /**< relaxation handler */
297 SCIP_SET* set /**< global SCIP settings */
298 )
299 {
300 assert(relax != NULL);
301 assert(set != NULL);
302
303 /* call solving process initialization method of relaxation handler */
304 if( relax->relaxinitsol != NULL )
305 {
306 /* start timing */
307 SCIPclockStart(relax->setuptime, set);
308
309 SCIP_CALL( relax->relaxinitsol(set->scip, relax) );
310
311 /* stop timing */
312 SCIPclockStop(relax->setuptime, set);
313 }
314
315 return SCIP_OKAY;
316 }
317
318 /** informs relaxation handler that the branch and bound process data is being freed */
SCIPrelaxExitsol(SCIP_RELAX * relax,SCIP_SET * set)319 SCIP_RETCODE SCIPrelaxExitsol(
320 SCIP_RELAX* relax, /**< relaxation handler */
321 SCIP_SET* set /**< global SCIP settings */
322 )
323 {
324 assert(relax != NULL);
325 assert(set != NULL);
326
327 /* call solving process deinitialization method of relaxation handler */
328 if( relax->relaxexitsol != NULL )
329 {
330 /* start timing */
331 SCIPclockStart(relax->setuptime, set);
332
333 SCIP_CALL( relax->relaxexitsol(set->scip, relax) );
334
335 /* stop timing */
336 SCIPclockStop(relax->setuptime, set);
337 }
338
339 return SCIP_OKAY;
340 }
341
342 /** calls execution method of relaxation handler */
SCIPrelaxExec(SCIP_RELAX * relax,SCIP_SET * set,SCIP_TREE * tree,SCIP_STAT * stat,int depth,SCIP_Real * lowerbound,SCIP_RESULT * result)343 SCIP_RETCODE SCIPrelaxExec(
344 SCIP_RELAX* relax, /**< relaxation handler */
345 SCIP_SET* set, /**< global SCIP settings */
346 SCIP_TREE* tree, /**< branch and bound tree */
347 SCIP_STAT* stat, /**< dynamic problem statistics */
348 int depth, /**< depth of current node */
349 SCIP_Real* lowerbound, /**< pointer to lower bound computed by the relaxation handler */
350 SCIP_RESULT* result /**< pointer to store the result of the callback method */
351 )
352 {
353 assert(relax != NULL);
354 assert(relax->relaxexec != NULL);
355 assert(relax->freq >= -1);
356 assert(set != NULL);
357 assert(set->scip != NULL);
358 assert(depth >= 0);
359 assert(result != NULL);
360
361 *result = SCIP_DIDNOTRUN;
362
363 /* check, if the relaxation is already solved */
364 if( relax->lastsolvednode == stat->ntotalnodes && ! SCIPinProbing(set->scip) )
365 return SCIP_OKAY;
366
367 relax->lastsolvednode = stat->ntotalnodes;
368
369 if( (depth == 0 && relax->freq == 0) || (relax->freq > 0 && depth % relax->freq == 0) )
370 {
371 SCIP_Real starttime;
372
373 SCIPsetDebugMsg(set, "executing relaxation handler <%s>\n", relax->name);
374
375 /* start timing */
376 starttime = SCIPclockGetTime(relax->relaxclock);
377 SCIPclockStart(relax->relaxclock, set);
378
379 /* call external relaxation method */
380 SCIP_CALL( relax->relaxexec(set->scip, relax, lowerbound, result) );
381
382 /* stop timing */
383 SCIPclockStop(relax->relaxclock, set);
384
385 /* evaluate result */
386 if( *result != SCIP_CUTOFF
387 && *result != SCIP_CONSADDED
388 && *result != SCIP_REDUCEDDOM
389 && *result != SCIP_SEPARATED
390 && *result != SCIP_SUCCESS
391 && *result != SCIP_SUSPENDED
392 && *result != SCIP_DIDNOTRUN )
393 {
394 SCIPerrorMessage("execution method of relaxation handler <%s> returned invalid result <%d>\n",
395 relax->name, *result);
396 return SCIP_INVALIDRESULT;
397 }
398 if( *result != SCIP_DIDNOTRUN )
399 {
400 relax->ncalls++;
401 stat->relaxcount++;
402 if( *result == SCIP_SUSPENDED )
403 SCIPrelaxMarkUnsolved(relax);
404 else if( *result == SCIP_CUTOFF || SCIPsetIsInfinity(set, *lowerbound) )
405 {
406 ++relax->ncutoffs;
407 relax->imprtime += SCIPclockGetTime(relax->relaxclock) - starttime;
408 }
409 else
410 {
411 SCIP_NODE* node;
412 SCIP_Real oldlowerbound;
413
414 node = SCIPtreeGetCurrentNode(tree);
415 if( node != NULL )
416 oldlowerbound = SCIPnodeGetLowerbound(node);
417 else
418 oldlowerbound = -SCIPsetInfinity(set);
419
420 if( !SCIPsetIsInfinity(set, -*lowerbound) && SCIPsetIsRelGT(set, *lowerbound, oldlowerbound) )
421 {
422 ++relax->nimprbounds;
423 relax->imprtime += SCIPclockGetTime(relax->relaxclock) - starttime;
424 }
425
426 if( *result == SCIP_CONSADDED )
427 ++relax->naddedconss;
428 else if( *result == SCIP_REDUCEDDOM )
429 ++relax->nreduceddom;
430 else if( *result == SCIP_SEPARATED )
431 ++relax->nseparated;
432 }
433 }
434 }
435
436 return SCIP_OKAY;
437 }
438
439 /** gets user data of relaxation handler */
SCIPrelaxGetData(SCIP_RELAX * relax)440 SCIP_RELAXDATA* SCIPrelaxGetData(
441 SCIP_RELAX* relax /**< relaxation handler */
442 )
443 {
444 assert(relax != NULL);
445
446 return relax->relaxdata;
447 }
448
449 /** sets user data of relaxation handler; user has to free old data in advance! */
SCIPrelaxSetData(SCIP_RELAX * relax,SCIP_RELAXDATA * relaxdata)450 void SCIPrelaxSetData(
451 SCIP_RELAX* relax, /**< relaxation handler */
452 SCIP_RELAXDATA* relaxdata /**< new relaxation handler user data */
453 )
454 {
455 assert(relax != NULL);
456
457 relax->relaxdata = relaxdata;
458 }
459
460 /** set copy method of relaxation handler */
SCIPrelaxSetCopy(SCIP_RELAX * relax,SCIP_DECL_RELAXCOPY ((* relaxcopy)))461 void SCIPrelaxSetCopy(
462 SCIP_RELAX* relax, /**< relaxation handler */
463 SCIP_DECL_RELAXCOPY ((*relaxcopy)) /**< copy method of relaxation handler */
464 )
465 {
466 assert(relax != NULL);
467
468 relax->relaxcopy = relaxcopy;
469 }
470
471 /** set destructor of relaxation handler */
SCIPrelaxSetFree(SCIP_RELAX * relax,SCIP_DECL_RELAXFREE ((* relaxfree)))472 void SCIPrelaxSetFree(
473 SCIP_RELAX* relax, /**< relaxation handler */
474 SCIP_DECL_RELAXFREE ((*relaxfree)) /**< destructor of relaxation handler */
475 )
476 {
477 assert(relax != NULL);
478
479 relax->relaxfree = relaxfree;
480 }
481
482 /** set initialization method of relaxation handler */
SCIPrelaxSetInit(SCIP_RELAX * relax,SCIP_DECL_RELAXINIT ((* relaxinit)))483 void SCIPrelaxSetInit(
484 SCIP_RELAX* relax, /**< relaxation handler */
485 SCIP_DECL_RELAXINIT ((*relaxinit)) /**< initialize relaxation handler */
486 )
487 {
488 assert(relax != NULL);
489
490 relax->relaxinit = relaxinit;
491 }
492
493 /** set deinitialization method of relaxation handler */
SCIPrelaxSetExit(SCIP_RELAX * relax,SCIP_DECL_RELAXEXIT ((* relaxexit)))494 void SCIPrelaxSetExit(
495 SCIP_RELAX* relax, /**< relaxation handler */
496 SCIP_DECL_RELAXEXIT ((*relaxexit)) /**< deinitialize relaxation handler */
497 )
498 {
499 assert(relax != NULL);
500
501 relax->relaxexit = relaxexit;
502 }
503
504 /** set solving process initialization method of relaxation handler */
SCIPrelaxSetInitsol(SCIP_RELAX * relax,SCIP_DECL_RELAXINITSOL ((* relaxinitsol)))505 void SCIPrelaxSetInitsol(
506 SCIP_RELAX* relax, /**< relaxation handler */
507 SCIP_DECL_RELAXINITSOL((*relaxinitsol)) /**< solving process initialization method of relaxation handler */
508 )
509 {
510 assert(relax != NULL);
511
512 relax->relaxinitsol = relaxinitsol;
513 }
514
515 /** set solving process deinitialization method of relaxation handler */
SCIPrelaxSetExitsol(SCIP_RELAX * relax,SCIP_DECL_RELAXEXITSOL ((* relaxexitsol)))516 void SCIPrelaxSetExitsol(
517 SCIP_RELAX* relax, /**< relaxation handler */
518 SCIP_DECL_RELAXEXITSOL((*relaxexitsol)) /**< solving process deinitialization relaxation handler */
519 )
520 {
521 assert(relax != NULL);
522
523 relax->relaxexitsol = relaxexitsol;
524 }
525
526 /** gets name of relaxation handler */
SCIPrelaxGetName(SCIP_RELAX * relax)527 const char* SCIPrelaxGetName(
528 SCIP_RELAX* relax /**< relaxation handler */
529 )
530 {
531 assert(relax != NULL);
532
533 return relax->name;
534 }
535
536 /** gets description of relaxation handler */
SCIPrelaxGetDesc(SCIP_RELAX * relax)537 const char* SCIPrelaxGetDesc(
538 SCIP_RELAX* relax /**< relaxation handler */
539 )
540 {
541 assert(relax != NULL);
542
543 return relax->desc;
544 }
545
546 /** gets priority of relaxation handler */
SCIPrelaxGetPriority(SCIP_RELAX * relax)547 int SCIPrelaxGetPriority(
548 SCIP_RELAX* relax /**< relaxation handler */
549 )
550 {
551 assert(relax != NULL);
552
553 return relax->priority;
554 }
555
556 /** sets priority of relaxation handler */
SCIPrelaxSetPriority(SCIP_RELAX * relax,SCIP_SET * set,int priority)557 void SCIPrelaxSetPriority(
558 SCIP_RELAX* relax, /**< relaxation handler */
559 SCIP_SET* set, /**< global SCIP settings */
560 int priority /**< new priority of the relaxation handler */
561 )
562 {
563 assert(relax != NULL);
564 assert(set != NULL);
565
566 relax->priority = priority;
567 set->relaxssorted = FALSE;
568 }
569
570 /** gets frequency of relaxation handler */
SCIPrelaxGetFreq(SCIP_RELAX * relax)571 int SCIPrelaxGetFreq(
572 SCIP_RELAX* relax /**< relaxation handler */
573 )
574 {
575 assert(relax != NULL);
576
577 return relax->freq;
578 }
579
580 /** gets time in seconds used in this relaxator for setting up for next stages */
SCIPrelaxGetSetupTime(SCIP_RELAX * relax)581 SCIP_Real SCIPrelaxGetSetupTime(
582 SCIP_RELAX* relax /**< relaxator */
583 )
584 {
585 assert(relax != NULL);
586
587 return SCIPclockGetTime(relax->setuptime);
588 }
589
590 /** enables or disables all clocks of \p relax, depending on the value of the flag */
SCIPrelaxEnableOrDisableClocks(SCIP_RELAX * relax,SCIP_Bool enable)591 void SCIPrelaxEnableOrDisableClocks(
592 SCIP_RELAX* relax, /**< the relaxation handler for which all clocks should be enabled or disabled */
593 SCIP_Bool enable /**< should the clocks of the relaxation handler be enabled? */
594 )
595 {
596 assert(relax != NULL);
597
598 SCIPclockEnableOrDisable(relax->setuptime, enable);
599 SCIPclockEnableOrDisable(relax->relaxclock, enable);
600 }
601
602 /** gets time in seconds used in this relaxation handler */
SCIPrelaxGetTime(SCIP_RELAX * relax)603 SCIP_Real SCIPrelaxGetTime(
604 SCIP_RELAX* relax /**< relaxation handler */
605 )
606 {
607 assert(relax != NULL);
608
609 return SCIPclockGetTime(relax->relaxclock);
610 }
611
612 /** gets the total number of times the relaxation handler was called */
SCIPrelaxGetNCalls(SCIP_RELAX * relax)613 SCIP_Longint SCIPrelaxGetNCalls(
614 SCIP_RELAX* relax /**< relaxation handler */
615 )
616 {
617 assert(relax != NULL);
618
619 return relax->ncalls;
620 }
621
622 /** gets the total number of times the relaxation handler cut off a node */
SCIPrelaxGetNCutoffs(SCIP_RELAX * relax)623 SCIP_Longint SCIPrelaxGetNCutoffs(
624 SCIP_RELAX* relax /**< relaxation handler */
625 )
626 {
627 assert(relax != NULL);
628
629 return relax->ncutoffs;
630 }
631
632 /** gets the total number of times the relaxation handler improved a node's lower bound */
SCIPrelaxGetNImprovedLowerbound(SCIP_RELAX * relax)633 SCIP_Longint SCIPrelaxGetNImprovedLowerbound(
634 SCIP_RELAX* relax /**< relaxation handler */
635 )
636 {
637 assert(relax != NULL);
638
639 return relax->nimprbounds;
640 }
641
642 /** gets the total number of times the relaxation handler added constraints */
SCIPrelaxGetNAddedConss(SCIP_RELAX * relax)643 SCIP_Longint SCIPrelaxGetNAddedConss(
644 SCIP_RELAX* relax /**< relaxation handler */
645 )
646 {
647 assert(relax != NULL);
648
649 return relax->naddedconss;
650 }
651
652 /** gets the time in seconds spent for the execution of the relaxation handler when a node's lower bound could be improved (or a cutoff was found) */
SCIPrelaxGetImprovedLowerboundTime(SCIP_RELAX * relax)653 SCIP_Real SCIPrelaxGetImprovedLowerboundTime(
654 SCIP_RELAX* relax /**< relaxation handler */
655 )
656 {
657 assert(relax != NULL);
658
659 return relax->imprtime;
660 }
661
662 /** gets the total number of times the relaxation handler reduced variable domains */
SCIPrelaxGetNReducedDomains(SCIP_RELAX * relax)663 SCIP_Longint SCIPrelaxGetNReducedDomains(
664 SCIP_RELAX* relax /**< relaxation handler */
665 )
666 {
667 assert(relax != NULL);
668
669 return relax->nreduceddom;
670 }
671
672 /** gets the total number of times the relaxation handler separated cutting planes */
SCIPrelaxGetNSeparatedCuts(SCIP_RELAX * relax)673 SCIP_Longint SCIPrelaxGetNSeparatedCuts(
674 SCIP_RELAX* relax /**< relaxation handler */
675 )
676 {
677 assert(relax != NULL);
678
679 return relax->nseparated;
680 }
681
682 /** is relaxation handler initialized? */
SCIPrelaxIsInitialized(SCIP_RELAX * relax)683 SCIP_Bool SCIPrelaxIsInitialized(
684 SCIP_RELAX* relax /**< relaxation handler */
685 )
686 {
687 assert(relax != NULL);
688
689 return relax->initialized;
690 }
691
692 /** returns whether the relaxation was completely solved at the current node */
SCIPrelaxIsSolved(SCIP_RELAX * relax,SCIP_STAT * stat)693 SCIP_Bool SCIPrelaxIsSolved(
694 SCIP_RELAX* relax, /**< relaxation handler */
695 SCIP_STAT* stat /**< dynamic problem statistics */
696 )
697 {
698 assert(relax != NULL);
699 assert(stat != NULL);
700
701 return (relax->lastsolvednode == stat->ntotalnodes);
702 }
703
704 /** marks the current relaxation unsolved, s.t. the relaxation handler is called again in the next solving round */
SCIPrelaxMarkUnsolved(SCIP_RELAX * relax)705 void SCIPrelaxMarkUnsolved(
706 SCIP_RELAX* relax /**< relaxation handler */
707 )
708 {
709 assert(relax != NULL);
710
711 relax->lastsolvednode = -1;
712 }
713
714 /*
715 * methods for the global relaxation data
716 */
717
718 /** creates global relaxation data */
SCIPrelaxationCreate(SCIP_RELAXATION ** relaxation,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_STAT * stat,SCIP_PRIMAL * primal,SCIP_TREE * tree)719 SCIP_RETCODE SCIPrelaxationCreate(
720 SCIP_RELAXATION** relaxation, /**< global relaxation data */
721 BMS_BLKMEM* blkmem, /**< block memory */
722 SCIP_SET* set, /**< global SCIP settings */
723 SCIP_STAT* stat, /**< problem statistics data */
724 SCIP_PRIMAL* primal, /**< primal data */
725 SCIP_TREE* tree /**< branch and bound tree */
726 )
727 {
728 assert(relaxation != NULL);
729 assert(blkmem != NULL);
730 assert(set != NULL);
731 assert(stat != NULL);
732 assert(primal != NULL);
733 assert(tree != NULL);
734
735 SCIP_ALLOC( BMSallocMemory(relaxation) );
736
737 (*relaxation)->relaxsolobjval = 0.0;
738 (*relaxation)->relaxsolvalid = FALSE;
739 (*relaxation)->relaxsolincludeslp = FALSE;
740 (*relaxation)->relaxsolzero = TRUE;
741 (*relaxation)->lastsolrelax = NULL;
742
743 return SCIP_OKAY;
744 }
745
746 /** frees global relaxation data */
SCIPrelaxationFree(SCIP_RELAXATION ** relaxation)747 SCIP_RETCODE SCIPrelaxationFree(
748 SCIP_RELAXATION** relaxation /**< global relaxation data */
749 )
750 {
751 assert(relaxation != NULL);
752
753 BMSfreeMemory(relaxation);
754
755 return SCIP_OKAY;
756 }
757
758 /** sets the relaxsolzero flag in the relaxation data to the given value */
SCIPrelaxationSetSolZero(SCIP_RELAXATION * relaxation,SCIP_Bool iszero)759 void SCIPrelaxationSetSolZero(
760 SCIP_RELAXATION* relaxation, /**< global relaxation data */
761 SCIP_Bool iszero /**< are all values of the relaxation solution set to zero? */
762 )
763 {
764 assert(relaxation != NULL);
765
766 relaxation->relaxsolzero = iszero;
767 }
768
769 /** returns whether the global relaxation solution is cleared and all values are set to zero */
SCIPrelaxationIsSolZero(SCIP_RELAXATION * relaxation)770 SCIP_Bool SCIPrelaxationIsSolZero(
771 SCIP_RELAXATION* relaxation /**< global relaxation data */
772 )
773 {
774 assert(relaxation != NULL);
775
776 return relaxation->relaxsolzero;
777 }
778
779 /** sets the relaxsolvalid and includeslp flags in the relaxation data to the given values */
SCIPrelaxationSetSolValid(SCIP_RELAXATION * relaxation,SCIP_Bool isvalid,SCIP_Bool includeslp)780 void SCIPrelaxationSetSolValid(
781 SCIP_RELAXATION* relaxation, /**< global relaxation data */
782 SCIP_Bool isvalid, /**< is the stored solution valid? */
783 SCIP_Bool includeslp /**< does the relaxator contain all cuts in the LP? */
784 )
785 {
786 assert(relaxation != NULL);
787
788 relaxation->relaxsolvalid = isvalid;
789 relaxation->relaxsolincludeslp = includeslp;
790 }
791
792 /** returns whether the global relaxation solution is valid */
SCIPrelaxationIsSolValid(SCIP_RELAXATION * relaxation)793 SCIP_Bool SCIPrelaxationIsSolValid(
794 SCIP_RELAXATION* relaxation /**< global relaxation data */
795 )
796 {
797 assert(relaxation != NULL);
798
799 return relaxation->relaxsolvalid;
800 }
801
802 /** returns whether the global relaxation solution was computed by a relaxator which included all LP cuts */
SCIPrelaxationIsLpIncludedForSol(SCIP_RELAXATION * relaxation)803 SCIP_Bool SCIPrelaxationIsLpIncludedForSol(
804 SCIP_RELAXATION* relaxation /**< global relaxation data */
805 )
806 {
807 assert(relaxation != NULL);
808
809 return relaxation->relaxsolincludeslp;
810 }
811
812 /** sets the objective value of the global relaxation solution */
SCIPrelaxationSetSolObj(SCIP_RELAXATION * relaxation,SCIP_Real obj)813 void SCIPrelaxationSetSolObj(
814 SCIP_RELAXATION* relaxation, /**< global relaxation data */
815 SCIP_Real obj /**< objective value */
816 )
817 {
818 assert(relaxation != NULL);
819
820 relaxation->relaxsolobjval = obj;
821 }
822
823 /** returns the objective value of the global relaxation solution w.r.t. the transformed problem */
SCIPrelaxationGetSolObj(SCIP_RELAXATION * relaxation)824 SCIP_Real SCIPrelaxationGetSolObj(
825 SCIP_RELAXATION* relaxation /**< global relaxation data */
826 )
827 {
828 assert(relaxation != NULL);
829
830 return relaxation->relaxsolobjval;
831 }
832
833 /** adds the given value to the global relaxation solution's objective value */
SCIPrelaxationSolObjAdd(SCIP_RELAXATION * relaxation,SCIP_Real val)834 void SCIPrelaxationSolObjAdd(
835 SCIP_RELAXATION* relaxation, /**< global relaxation data */
836 SCIP_Real val /**< value to add to the objective value */
837 )
838 {
839 assert(relaxation != NULL);
840
841 relaxation->relaxsolobjval += val;
842 }
843
844 /** updates objective value of current relaxation solution after change of objective coefficient */
SCIPrelaxationUpdateVarObj(SCIP_RELAXATION * relaxation,SCIP_SET * set,SCIP_VAR * var,SCIP_Real oldobj,SCIP_Real newobj)845 void SCIPrelaxationUpdateVarObj(
846 SCIP_RELAXATION* relaxation, /**< global relaxation data */
847 SCIP_SET* set, /**< global SCIP settings */
848 SCIP_VAR* var, /**< variable with changed objective coefficient */
849 SCIP_Real oldobj, /**< old objective coefficient */
850 SCIP_Real newobj /**< new objective coefficient */
851 )
852 {
853 SCIP_Real relaxsolval;
854
855 assert(relaxation != NULL);
856 assert(set != NULL);
857 assert(var != NULL);
858 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
859
860 relaxsolval = SCIPvarGetRelaxSol(var, set);
861 relaxation->relaxsolobjval += (newobj - oldobj) * relaxsolval;
862 }
863
864 /** store the most recent relaxation handler \p relax responsible for the solution */
SCIPrelaxationSetSolRelax(SCIP_RELAXATION * relaxation,SCIP_RELAX * relax)865 void SCIPrelaxationSetSolRelax(
866 SCIP_RELAXATION* relaxation, /**< global relaxation data */
867 SCIP_RELAX* relax /**< responsible relaxation handler, or NULL */
868 )
869 {
870 assert(relaxation != NULL);
871
872 relaxation->lastsolrelax = relax;
873 }
874
875 /** returns the most recent relaxation handler responsible for the solution, or NULL if unspecified */
SCIPrelaxationGetSolRelax(SCIP_RELAXATION * relaxation)876 SCIP_RELAX* SCIPrelaxationGetSolRelax(
877 SCIP_RELAXATION* relaxation /**< global relaxation data */
878 )
879 {
880 assert(relaxation != NULL);
881
882 return relaxation->lastsolrelax;
883 }
884