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