1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2022 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 scip.zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15
16 /**@file nlhdlr.c
17 * @ingroup OTHER_CFILES
18 * @brief functions for nonlinearity handlers of nonlinear constraint handler
19 * @author Ksenia Bestuzheva
20 * @author Benjamin Mueller
21 * @author Felipe Serrano
22 * @author Stefan Vigerske
23 */
24
25 #include <assert.h>
26
27 #include "scip/pub_nlhdlr.h"
28 #include "scip/nlhdlr.h"
29 #include "scip/struct_nlhdlr.h"
30 #include "scip/scip_timing.h"
31 #include "scip/scip_mem.h"
32 #include "scip/scip_param.h"
33 #include "scip/scip_message.h"
34 #include "scip/pub_misc.h"
35
36 /**@addtogroup PublicNlhdlrInterfaceMethods
37 * @{
38 */
39
40 #ifdef NDEBUG
41 /* Undo the defines from pub_nlhdlr.h, which exist if NDEBUG is defined. */
42 #undef SCIPnlhdlrSetCopyHdlr
43 #undef SCIPnlhdlrSetFreeHdlrData
44 #undef SCIPnlhdlrSetFreeExprData
45 #undef SCIPnlhdlrSetInitExit
46 #undef SCIPnlhdlrSetProp
47 #undef SCIPnlhdlrSetSepa
48 #undef SCIPnlhdlrGetName
49 #undef SCIPnlhdlrGetDesc
50 #undef SCIPnlhdlrGetDetectPriority
51 #undef SCIPnlhdlrGetEnfoPriority
52 #undef SCIPnlhdlrIsEnabled
53 #undef SCIPnlhdlrGetData
54 #undef SCIPnlhdlrHasIntEval
55 #undef SCIPnlhdlrHasReverseProp
56 #undef SCIPnlhdlrHasInitSepa
57 #undef SCIPnlhdlrHasExitSepa
58 #undef SCIPnlhdlrHasEnfo
59 #undef SCIPnlhdlrHasEstimate
60 #endif
61
62 /** sets the copy handler callback of a nonlinear handler */
63 void SCIPnlhdlrSetCopyHdlr(
64 SCIP_NLHDLR* nlhdlr, /**< nonlinear handler */
65 SCIP_DECL_NLHDLRCOPYHDLR((*copy)) /**< copy callback (can be NULL) */
66 )
67 {
68 assert(nlhdlr != NULL);
69
70 nlhdlr->copyhdlr = copy;
71 }
72
73 /** sets the nonlinear handler callback to free the nonlinear handler data */
74 void SCIPnlhdlrSetFreeHdlrData(
75 SCIP_NLHDLR* nlhdlr, /**< nonlinear handler */
76 SCIP_DECL_NLHDLRFREEHDLRDATA((*freehdlrdata)) /**< handler free callback (can be NULL) */
77 )
78 {
79 assert(nlhdlr != NULL);
80
81 nlhdlr->freehdlrdata = freehdlrdata;
82 }
83
84 /** sets the nonlinear handler callback to free expression specific data of nonlinear handler */
85 void SCIPnlhdlrSetFreeExprData(
86 SCIP_NLHDLR* nlhdlr, /**< nonlinear handler */
87 SCIP_DECL_NLHDLRFREEEXPRDATA((*freeexprdata)) /**< nonlinear handler expression data free callback
88 (can be NULL if data does not need to be freed) */
89 )
90 {
91 assert(nlhdlr != NULL);
92
93 nlhdlr->freeexprdata = freeexprdata;
94 }
95
96 /** sets the initialization and deinitialization callback of a nonlinear handler */
97 void SCIPnlhdlrSetInitExit(
98 SCIP_NLHDLR* nlhdlr, /**< nonlinear handler */
99 SCIP_DECL_NLHDLRINIT((*init)), /**< initialization callback (can be NULL) */
100 SCIP_DECL_NLHDLREXIT((*exit_)) /**< deinitialization callback (can be NULL) */
101 )
102 {
103 assert(nlhdlr != NULL);
104
105 nlhdlr->init = init;
106 nlhdlr->exit = exit_;
107 }
108
109 /** sets the propagation callbacks of a nonlinear handler */
110 void SCIPnlhdlrSetProp(
111 SCIP_NLHDLR* nlhdlr, /**< nonlinear handler */
112 SCIP_DECL_NLHDLRINTEVAL((*inteval)), /**< interval evaluation callback (can be NULL) */
113 SCIP_DECL_NLHDLRREVERSEPROP((*reverseprop)) /**< reverse propagation callback (can be NULL) */
114 )
115 {
116 assert(nlhdlr != NULL);
117
118 nlhdlr->inteval = inteval;
119 nlhdlr->reverseprop = reverseprop;
120 }
121
122 /** sets the enforcement callbacks of a nonlinear handler */
123 void SCIPnlhdlrSetSepa(
124 SCIP_NLHDLR* nlhdlr, /**< nonlinear handler */
125 SCIP_DECL_NLHDLRINITSEPA((*initsepa)), /**< separation initialization callback (can be NULL) */
126 SCIP_DECL_NLHDLRENFO((*enfo)), /**< enforcement callback (can be NULL if estimate is not NULL) */
127 SCIP_DECL_NLHDLRESTIMATE((*estimate)), /**< estimation callback (can be NULL if sepa is not NULL) */
128 SCIP_DECL_NLHDLREXITSEPA((*exitsepa)) /**< separation deinitialization callback (can be NULL) */
129 )
130 {
131 assert(nlhdlr != NULL);
132 assert(enfo != NULL || estimate != NULL);
133
134 nlhdlr->initsepa = initsepa;
135 nlhdlr->enfo = enfo;
136 nlhdlr->estimate = estimate;
137 nlhdlr->exitsepa = exitsepa;
138 }
139
140 /** gives name of nonlinear handler */
141 const char* SCIPnlhdlrGetName(
142 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */
143 )
144 {
145 assert(nlhdlr != NULL);
146
147 return nlhdlr->name;
148 }
149
150 /** gives description of nonlinear handler, can be NULL */
151 const char* SCIPnlhdlrGetDesc(
152 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */
153 )
154 {
155 assert(nlhdlr != NULL);
156
157 return nlhdlr->desc;
158 }
159
160 /** gives detection priority of nonlinear handler */
161 int SCIPnlhdlrGetDetectPriority(
162 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */
163 )
164 {
165 assert(nlhdlr != NULL);
166
167 return nlhdlr->detectpriority;
168 }
169
170 /** gives enforcement priority of nonlinear handler */
171 int SCIPnlhdlrGetEnfoPriority(
172 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */
173 )
174 {
175 assert(nlhdlr != NULL);
176
177 return nlhdlr->enfopriority;
178 }
179
180 /** returns whether nonlinear handler is enabled */
181 SCIP_Bool SCIPnlhdlrIsEnabled(
182 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */
183 )
184 {
185 assert(nlhdlr != NULL);
186
187 return nlhdlr->enabled;
188 }
189
190 /** gives handler data of nonlinear handler */
191 SCIP_NLHDLRDATA* SCIPnlhdlrGetData(
192 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */
193 )
194 {
195 assert(nlhdlr != NULL);
196
197 return nlhdlr->data;
198 }
199
200 /** returns whether nonlinear handler implements the interval evaluation callback */
201 SCIP_Bool SCIPnlhdlrHasIntEval(
202 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */
203 )
204 {
205 return nlhdlr->inteval != NULL;
206 }
207
208 /** returns whether nonlinear handler implements the reverse propagation callback */
209 SCIP_Bool SCIPnlhdlrHasReverseProp(
210 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */
211 )
212 {
213 return nlhdlr->reverseprop != NULL;
214 }
215
216 /** returns whether nonlinear handler implements the separation initialization callback */
217 SCIP_Bool SCIPnlhdlrHasInitSepa(
218 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */
219 )
220 {
221 return nlhdlr->initsepa != NULL;
222 }
223
224 /** returns whether nonlinear handler implements the separation deinitialization callback */
225 SCIP_Bool SCIPnlhdlrHasExitSepa(
226 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */
227 )
228 {
229 return nlhdlr->exitsepa != NULL;
230 }
231
232 /** returns whether nonlinear handler implements the enforcement callback */
233 SCIP_Bool SCIPnlhdlrHasEnfo(
234 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */
235 )
236 {
237 return nlhdlr->enfo != NULL;
238 }
239
240 /** returns whether nonlinear handler implements the estimator callback */
241 SCIP_Bool SCIPnlhdlrHasEstimate(
242 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */
243 )
244 {
245 return nlhdlr->estimate != NULL;
246 }
247
248 /** compares two nonlinear handlers by detection priority
249 *
250 * if handlers have same detection priority, then compare by name
251 */
252 SCIP_DECL_SORTPTRCOMP(SCIPnlhdlrComp)
253 {
254 SCIP_NLHDLR* h1;
255 SCIP_NLHDLR* h2;
256
257 assert(elem1 != NULL);
258 assert(elem2 != NULL);
259
260 h1 = (SCIP_NLHDLR*)elem1;
261 h2 = (SCIP_NLHDLR*)elem2;
262
263 if( h1->detectpriority != h2->detectpriority )
264 return h1->detectpriority - h2->detectpriority;
265
266 return strcmp(h1->name, h2->name);
267 }
268
269 #ifdef SCIP_DISABLED_CODE
270 /** compares nonlinear handler by enforcement priority
271 *
272 * if handlers have same enforcement priority, then compare by detection priority, then by name
273 */
274 SCIP_DECL_SORTPTRCOMP(SCIPnlhdlrCompEnfo)
275 {
276 SCIP_NLHDLR* h1;
277 SCIP_NLHDLR* h2;
278
279 assert(elem1 != NULL);
280 assert(elem2 != NULL);
281
282 h1 = (SCIP_NLHDLR*)elem1;
283 h2 = (SCIP_NLHDLR*)elem2;
284
285 if( h1->enfopriority != h2->enfopriority )
286 return h1->enfopriority - h2->enfopriority;
287
288 if( h1->detectpriority != h2->detectpriority )
289 return h1->detectpriority - h2->detectpriority;
290
291 return strcmp(h1->name, h2->name);
292 }
293 #endif
294
295 /** @} */
296
297 /* nlhdlr private API functions from nlhdlr.h */
298
299 #ifndef NDEBUG
300 #undef SCIPnlhdlrResetNDetectionslast
301 #undef SCIPnlhdlrIncrementNCutoffs
302 #undef SCIPnlhdlrIncrementNSeparated
303 #endif
304
305 /** creates a nonlinear handler */
306 SCIP_RETCODE SCIPnlhdlrCreate(
307 SCIP* scip, /**< SCIP data structure */
308 SCIP_NLHDLR** nlhdlr, /**< buffer to store pointer to created nonlinear handler */
309 const char* name, /**< name of nonlinear handler (must not be NULL) */
310 const char* desc, /**< description of nonlinear handler (can be NULL) */
311 int detectpriority, /**< detection priority of nonlinear handler */
312 int enfopriority, /**< enforcement priority of nonlinear handler */
313 SCIP_DECL_NLHDLRDETECT((*detect)), /**< structure detection callback of nonlinear handler */
314 SCIP_DECL_NLHDLREVALAUX((*evalaux)), /**< auxiliary evaluation callback of nonlinear handler */
315 SCIP_NLHDLRDATA* nlhdlrdata /**< data of nonlinear handler (can be NULL) */
316 )
317 {
318 char paramname[SCIP_MAXSTRLEN];
319
320 assert(scip != NULL);
321 assert(nlhdlr != NULL);
322 assert(name != NULL);
323 assert(detect != NULL);
324 assert(evalaux != NULL);
325
(1) Event alloc_fn: |
Storage is returned from allocation function "BMSallocClearMemory_call". [details] |
(2) Event assign: |
Assigning: "*nlhdlr" = "BMSallocClearMemory_call(1UL, 248UL, "/sapmnt/home1/d029903/my_work/SCIPSoPlex_coverity/scipoptsuite-8.0.1/scip/src/scip/nlhdlr.c", 326)". |
(3) Event cond_false: |
Condition "(*nlhdlr = BMSallocClearMemory_call(1UL /* (size_t)1 */, 248UL /* sizeof (**nlhdlr) */, "/sapmnt/home1/d029903/my_work/SCIPSoPlex_coverity/scipoptsuite-8.0.1/scip/src/scip/nlhdlr.c", 326)) == NULL", taking false branch. |
(4) Event cond_false: |
Condition "(_restat_ = (((*nlhdlr = BMSallocClearMemory_call(1UL /* (size_t)1 */, 248UL /* sizeof (**nlhdlr) */, "/sapmnt/home1/d029903/my_work/SCIPSoPlex_coverity/scipoptsuite-8.0.1/scip/src/scip/nlhdlr.c", 326)) == NULL) ? SCIP_NOMEMORY : SCIP_OKAY)) != SCIP_OKAY", taking false branch. |
(5) Event if_end: |
End of if statement. |
326 SCIP_CALL( SCIPallocClearMemory(scip, nlhdlr) );
327
(6) Event cond_false: |
Condition "((*nlhdlr)->name = BMSduplicateMemoryArray_call((void const *)name, (size_t)(ptrdiff_t)(strlen(name) + 1), 1UL /* sizeof (*(*nlhdlr)->name) */, "/sapmnt/home1/d029903/my_work/SCIPSoPlex_coverity/scipoptsuite-8.0.1/scip/src/scip/nlhdlr.c", 328)) == NULL", taking false branch. |
(7) Event cond_false: |
Condition "(_restat_ = ((((*nlhdlr)->name = BMSduplicateMemoryArray_call((void const *)name, (size_t)(ptrdiff_t)(strlen(name) + 1), 1UL /* sizeof (*(*nlhdlr)->name) */, "/sapmnt/home1/d029903/my_work/SCIPSoPlex_coverity/scipoptsuite-8.0.1/scip/src/scip/nlhdlr.c", 328)) == NULL) ? SCIP_NOMEMORY : SCIP_OKAY)) != SCIP_OKAY", taking false branch. |
(8) Event if_end: |
End of if statement. |
328 SCIP_CALL( SCIPduplicateMemoryArray(scip, &(*nlhdlr)->name, name, strlen(name)+1) );
(9) Event cond_true: |
Condition "desc != NULL", taking true branch. |
329 if( desc != NULL )
330 {
(10) Event cond_false: |
Condition "((*nlhdlr)->desc = BMSduplicateMemoryArray_call((void const *)desc, (size_t)(ptrdiff_t)(strlen(desc) + 1), 1UL /* sizeof (*(*nlhdlr)->desc) */, "/sapmnt/home1/d029903/my_work/SCIPSoPlex_coverity/scipoptsuite-8.0.1/scip/src/scip/nlhdlr.c", 331)) == NULL", taking false branch. |
(11) Event cond_false: |
Condition "(_restat_ = ((((*nlhdlr)->desc = BMSduplicateMemoryArray_call((void const *)desc, (size_t)(ptrdiff_t)(strlen(desc) + 1), 1UL /* sizeof (*(*nlhdlr)->desc) */, "/sapmnt/home1/d029903/my_work/SCIPSoPlex_coverity/scipoptsuite-8.0.1/scip/src/scip/nlhdlr.c", 331)) == NULL) ? SCIP_NOMEMORY : SCIP_OKAY)) != SCIP_OKAY", taking false branch. |
(12) Event if_end: |
End of if statement. |
331 SCIP_CALL( SCIPduplicateMemoryArray(scip, &(*nlhdlr)->desc, desc, strlen(desc)+1) );
332 }
333
334 (*nlhdlr)->detectpriority = detectpriority;
335 (*nlhdlr)->enfopriority = enfopriority;
336 (*nlhdlr)->data = nlhdlrdata;
337 (*nlhdlr)->detect = detect;
338 (*nlhdlr)->evalaux = evalaux;
339
(13) Event cond_true: |
Condition "(_restat_ = SCIPcreateClock(scip, &(*nlhdlr)->detecttime)) != SCIP_OKAY", taking true branch. |
340 SCIP_CALL( SCIPcreateClock(scip, &(*nlhdlr)->detecttime) );
341 SCIP_CALL( SCIPcreateClock(scip, &(*nlhdlr)->enfotime) );
342 SCIP_CALL( SCIPcreateClock(scip, &(*nlhdlr)->proptime) );
343 SCIP_CALL( SCIPcreateClock(scip, &(*nlhdlr)->intevaltime) );
344
345 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "nlhdlr/%s/enabled", name);
346 SCIP_CALL( SCIPaddBoolParam(scip, paramname, "should this nonlinear handler be used",
347 &(*nlhdlr)->enabled, FALSE, TRUE, NULL, NULL) );
348
349 return SCIP_OKAY;
350 }
351
352 /** frees a nonlinear handler */
353 SCIP_RETCODE SCIPnlhdlrFree(
354 SCIP* scip, /**< SCIP data structure */
355 SCIP_NLHDLR** nlhdlr /**< pointer to nonlinear handler to be freed */
356 )
357 {
358 assert(nlhdlr != NULL);
359 assert(*nlhdlr != NULL);
360
361 if( (*nlhdlr)->freehdlrdata != NULL )
362 {
363 SCIP_CALL( (*nlhdlr)->freehdlrdata(scip, *nlhdlr, &(*nlhdlr)->data) );
364 }
365
366 /* free clocks */
367 SCIP_CALL( SCIPfreeClock(scip, &(*nlhdlr)->detecttime) );
368 SCIP_CALL( SCIPfreeClock(scip, &(*nlhdlr)->enfotime) );
369 SCIP_CALL( SCIPfreeClock(scip, &(*nlhdlr)->proptime) );
370 SCIP_CALL( SCIPfreeClock(scip, &(*nlhdlr)->intevaltime) );
371
372 SCIPfreeMemory(scip, &(*nlhdlr)->name);
373 SCIPfreeMemoryNull(scip, &(*nlhdlr)->desc);
374
375 SCIPfreeMemory(scip, nlhdlr);
376
377 return SCIP_OKAY;
378 }
379
380 /** call the handler copy callback of a nonlinear handler */
381 SCIP_DECL_NLHDLRCOPYHDLR(SCIPnlhdlrCopyhdlr)
382 {
383 /* TODO for now just don't copy disabled nlhdlr, a clean way would probably be to first copy and disable then */
384 if( sourcenlhdlr->copyhdlr != NULL && sourcenlhdlr->enabled )
385 {
386 SCIP_CALL( sourcenlhdlr->copyhdlr(targetscip, targetconshdlr, sourceconshdlr, sourcenlhdlr) );
387 }
388
389 return SCIP_OKAY;
390 }
391
392 /** call the free expression specific data callback of a nonlinear handler */
393 SCIP_DECL_NLHDLRFREEEXPRDATA(SCIPnlhdlrFreeexprdata)
394 {
395 assert(nlhdlr != NULL);
396 assert(nlhdlrexprdata != NULL);
397 assert(*nlhdlrexprdata != NULL);
398
399 if( nlhdlr->freeexprdata != NULL )
400 {
401 SCIP_CALL( nlhdlr->freeexprdata(scip, nlhdlr, expr, nlhdlrexprdata) );
402 assert(*nlhdlrexprdata == NULL);
403 }
404
405 return SCIP_OKAY;
406 }
407
408 /** call the initialization callback of a nonlinear handler */
409 SCIP_DECL_NLHDLRINIT(SCIPnlhdlrInit)
410 {
411 assert(nlhdlr != NULL);
412
413 nlhdlr->nenfocalls = 0;
414 nlhdlr->nintevalcalls = 0;
415 nlhdlr->npropcalls = 0;
416 nlhdlr->nseparated = 0;
417 nlhdlr->ncutoffs = 0;
418 nlhdlr->ndomreds = 0;
419 nlhdlr->nbranchscores = 0;
420 nlhdlr->ndetections = 0;
421 nlhdlr->ndetectionslast = 0;
422
423 SCIP_CALL( SCIPresetClock(scip, nlhdlr->detecttime) );
424 SCIP_CALL( SCIPresetClock(scip, nlhdlr->enfotime) );
425 SCIP_CALL( SCIPresetClock(scip, nlhdlr->proptime) );
426 SCIP_CALL( SCIPresetClock(scip, nlhdlr->intevaltime) );
427
428 if( nlhdlr->init != NULL )
429 {
430 SCIP_CALL( nlhdlr->init(scip, nlhdlr) );
431 }
432
433 return SCIP_OKAY;
434 }
435
436 /** call the deinitialization callback of a nonlinear handler */
437 SCIP_DECL_NLHDLREXIT(SCIPnlhdlrExit)
438 {
439 assert(nlhdlr != NULL);
440
441 if( nlhdlr->exit != NULL )
442 {
443 SCIP_CALL( nlhdlr->exit(scip, nlhdlr) );
444 }
445
446 return SCIP_OKAY;
447 }
448
449 /** call the detect callback of a nonlinear handler */
450 SCIP_DECL_NLHDLRDETECT(SCIPnlhdlrDetect)
451 {
452 assert(scip != NULL);
453 assert(nlhdlr != NULL);
454 assert(nlhdlr->detect != NULL);
455 assert(nlhdlr->detecttime != NULL);
456 assert(participating != NULL);
457
458 SCIP_CALL( SCIPstartClock(scip, nlhdlr->detecttime) );
459 SCIP_CALL( nlhdlr->detect(scip, conshdlr, nlhdlr, expr, cons, enforcing, participating, nlhdlrexprdata) );
460 SCIP_CALL( SCIPstopClock(scip, nlhdlr->detecttime) );
461
462 if( *participating != SCIP_NLHDLR_METHOD_NONE )
463 {
464 ++nlhdlr->ndetections;
465 ++nlhdlr->ndetectionslast;
466 }
467
468 return SCIP_OKAY;
469 }
470
471 /** call the auxiliary evaluation callback of a nonlinear handler */
472 SCIP_DECL_NLHDLREVALAUX(SCIPnlhdlrEvalaux)
473 {
474 assert(nlhdlr != NULL);
475 assert(nlhdlr->evalaux != NULL);
476
477 SCIP_CALL( nlhdlr->evalaux(scip, nlhdlr, expr, nlhdlrexprdata, auxvalue, sol) );
478
479 return SCIP_OKAY;
480 }
481
482 /** call the interval evaluation callback of a nonlinear handler */
483 SCIP_DECL_NLHDLRINTEVAL(SCIPnlhdlrInteval)
484 {
485 assert(scip != NULL);
486 assert(nlhdlr != NULL);
487 assert(nlhdlr->intevaltime != NULL);
488
489 if( nlhdlr->inteval != NULL )
490 {
491 SCIP_CALL( SCIPstartClock(scip, nlhdlr->intevaltime) );
492 SCIP_CALL( nlhdlr->inteval(scip, nlhdlr, expr, nlhdlrexprdata, interval, intevalvar, intevalvardata) );
493 SCIP_CALL( SCIPstopClock(scip, nlhdlr->intevaltime) );
494
495 ++nlhdlr->nintevalcalls;
496 }
497
498 return SCIP_OKAY;
499 }
500
501 /** call the reverse propagation callback of a nonlinear handler */
502 SCIP_DECL_NLHDLRREVERSEPROP(SCIPnlhdlrReverseprop)
503 {
504 assert(scip != NULL);
505 assert(nlhdlr != NULL);
506 assert(nlhdlr->proptime != NULL);
507 assert(infeasible != NULL);
508 assert(nreductions != NULL);
509
510 if( nlhdlr->reverseprop == NULL )
511 {
512 *infeasible = FALSE;
513 *nreductions = 0;
514
515 return SCIP_OKAY;
516 }
517
518 SCIP_CALL( SCIPstartClock(scip, nlhdlr->proptime) );
519 SCIP_CALL( nlhdlr->reverseprop(scip, conshdlr, nlhdlr, expr, nlhdlrexprdata, bounds, infeasible, nreductions) );
520 SCIP_CALL( SCIPstopClock(scip, nlhdlr->proptime) );
521
522 /* update statistics */
523 nlhdlr->ndomreds += *nreductions;
524 if( *infeasible )
525 ++nlhdlr->ncutoffs;
526 ++nlhdlr->npropcalls;
527
528 return SCIP_OKAY;
529 }
530
531 /** call the separation initialization callback of a nonlinear handler */
532 SCIP_DECL_NLHDLRINITSEPA(SCIPnlhdlrInitsepa)
533 {
534 assert(scip != NULL);
535 assert(nlhdlr != NULL);
536 assert(nlhdlr->enfotime != NULL);
537 assert(infeasible != NULL);
538
539 if( nlhdlr->initsepa == NULL )
540 {
541 *infeasible = FALSE;
542 return SCIP_OKAY;
543 }
544
545 SCIP_CALL( SCIPstartClock(scip, nlhdlr->enfotime) );
546 SCIP_CALL( nlhdlr->initsepa(scip, conshdlr, cons, nlhdlr, expr, nlhdlrexprdata, overestimate, underestimate, infeasible) );
547 SCIP_CALL( SCIPstopClock(scip, nlhdlr->enfotime) );
548
549 ++nlhdlr->nenfocalls;
550 if( *infeasible )
551 ++nlhdlr->ncutoffs;
552
553 return SCIP_OKAY;
554 }
555
556 /** call the separation deinitialization callback of a nonlinear handler */
557 SCIP_DECL_NLHDLREXITSEPA(SCIPnlhdlrExitsepa)
558 {
559 assert(scip != NULL);
560 assert(nlhdlr != NULL);
561 assert(nlhdlr->enfotime != NULL);
562
563 if( nlhdlr->exitsepa != NULL )
564 {
565 SCIP_CALL( SCIPstartClock(scip, nlhdlr->enfotime) );
566 SCIP_CALL( nlhdlr->exitsepa(scip, nlhdlr, expr, nlhdlrexprdata) );
567 SCIP_CALL( SCIPstopClock(scip, nlhdlr->enfotime) );
568 }
569
570 return SCIP_OKAY;
571 }
572
573 /** call the enforcement callback of a nonlinear handler */
574 SCIP_DECL_NLHDLRENFO(SCIPnlhdlrEnfo)
575 {
576 assert(scip != NULL);
577 assert(nlhdlr != NULL);
578 assert(nlhdlr->enfotime != NULL);
579 assert(result != NULL);
580
581 if( nlhdlr->enfo == NULL )
582 {
583 *result = SCIP_DIDNOTRUN;
584 return SCIP_OKAY;
585 }
586
587 #ifndef NDEBUG
588 /* check that auxvalue is correct by reevaluating */
589 {
590 SCIP_Real auxvaluetest;
591 SCIP_CALL( SCIPnlhdlrEvalaux(scip, nlhdlr, expr, nlhdlrexprdata, &auxvaluetest, sol) );
592 /* we should get EXACTLY the same value from calling evalaux with the same solution as before */
593 assert(auxvalue == auxvaluetest); /*lint !e777*/
594 }
595 #endif
596
597 SCIP_CALL( SCIPstartClock(scip, nlhdlr->enfotime) );
598 SCIP_CALL( nlhdlr->enfo(scip, conshdlr, cons, nlhdlr, expr, nlhdlrexprdata, sol, auxvalue,
599 overestimate, allowweakcuts, separated, addbranchscores, result) );
600 SCIP_CALL( SCIPstopClock(scip, nlhdlr->enfotime) );
601
602 /* update statistics */
603 ++nlhdlr->nenfocalls;
604 switch( *result )
605 {
606 case SCIP_SEPARATED :
607 ++nlhdlr->nseparated;
608 break;
609 case SCIP_BRANCHED:
610 ++nlhdlr->nbranchscores;
611 break;
612 case SCIP_CUTOFF:
613 ++nlhdlr->ncutoffs;
614 break;
615 case SCIP_REDUCEDDOM:
616 ++nlhdlr->ndomreds;
617 break;
618 default: ;
619 } /*lint !e788*/
620
621 return SCIP_OKAY;
622 }
623
624 /** call the estimator callback of a nonlinear handler */
625 SCIP_DECL_NLHDLRESTIMATE(SCIPnlhdlrEstimate)
626 {
627 assert(scip != NULL);
628 assert(nlhdlr != NULL);
629 assert(nlhdlr->enfotime != NULL);
630 assert(success != NULL);
631 assert(addedbranchscores != NULL);
632
633 if( nlhdlr->estimate == NULL )
634 {
635 *success = FALSE;
636 *addedbranchscores = FALSE;
637 return SCIP_OKAY;
638 }
639
640 #ifndef NDEBUG
641 /* check that auxvalue is correct by reevaluating */
642 {
643 SCIP_Real auxvaluetest;
644 SCIP_CALL( SCIPnlhdlrEvalaux(scip, nlhdlr, expr, nlhdlrexprdata, &auxvaluetest, sol) );
645 /* we should get EXACTLY the same value from calling evalaux with the same solution as before */
646 assert(auxvalue == auxvaluetest); /*lint !e777*/
647 }
648 #endif
649
650 SCIP_CALL( SCIPstartClock(scip, nlhdlr->enfotime) );
651 SCIP_CALL( nlhdlr->estimate(scip, conshdlr, nlhdlr, expr, nlhdlrexprdata, sol, auxvalue, overestimate, targetvalue, addbranchscores, rowpreps, success, addedbranchscores) );
652 SCIP_CALL( SCIPstopClock(scip, nlhdlr->enfotime) );
653
654 /* update statistics */
655 ++nlhdlr->nenfocalls;
656
657 return SCIP_OKAY;
658 }
659
660 /** reset number of detections counter for last round */
661 void SCIPnlhdlrResetNDetectionslast(
662 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */
663 )
664 {
665 assert(nlhdlr != NULL);
666 nlhdlr->ndetectionslast = 0;
667 }
668
669 /** increments number of cutoffs in statistics */
670 void SCIPnlhdlrIncrementNCutoffs(
671 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */
672 )
673 {
674 assert(nlhdlr != NULL);
675 ++nlhdlr->ncutoffs;
676 }
677
678 /** increments number of separations in statistics */
679 void SCIPnlhdlrIncrementNSeparated(
680 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */
681 )
682 {
683 assert(nlhdlr != NULL);
684 ++nlhdlr->nseparated;
685 }
686
687 /** print statistics for nonlinear handlers */
688 void SCIPnlhdlrPrintStatistics(
689 SCIP* scip, /**< SCIP data structure */
690 SCIP_NLHDLR** nlhdlrs, /**< nonlinear handlers */
691 int nnlhdlrs, /**< number of nonlinear handlers */
692 FILE* file /**< file handle, or NULL for standard out */
693 )
694 {
695 int i;
696
697 SCIPinfoMessage(scip, file, "Nlhdlrs : %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s\n",
698 "Detects", "DetectAll", "DetectTime",
699 "#IntEval", "IntEvalTi",
700 "#RevProp", "RevPropTi", "DomReds", "Cutoffs",
701 "#Enforce", "EnfoTime", "Cuts", "Branching");
702
703 for( i = 0; i < nnlhdlrs; ++i )
704 {
705 /* skip disabled nlhdlr */
706 if( !nlhdlrs[i]->enabled )
707 continue;
708
709 SCIPinfoMessage(scip, file, " %-17s:", nlhdlrs[i]->name);
710 SCIPinfoMessage(scip, file, " %10lld", nlhdlrs[i]->ndetectionslast);
711 SCIPinfoMessage(scip, file, " %10lld", nlhdlrs[i]->ndetections);
712 SCIPinfoMessage(scip, file, " %10.2f", SCIPgetClockTime(scip, nlhdlrs[i]->detecttime));
713
714 SCIPinfoMessage(scip, file, " %10lld", nlhdlrs[i]->nintevalcalls);
715 SCIPinfoMessage(scip, file, " %10.2f", SCIPgetClockTime(scip, nlhdlrs[i]->intevaltime));
716
717 SCIPinfoMessage(scip, file, " %10lld", nlhdlrs[i]->npropcalls);
718 SCIPinfoMessage(scip, file, " %10.2f", SCIPgetClockTime(scip, nlhdlrs[i]->proptime));
719 SCIPinfoMessage(scip, file, " %10lld", nlhdlrs[i]->ndomreds);
720 SCIPinfoMessage(scip, file, " %10lld", nlhdlrs[i]->ncutoffs);
721
722 SCIPinfoMessage(scip, file, " %10lld", nlhdlrs[i]->nenfocalls);
723 SCIPinfoMessage(scip, file, " %10.2f", SCIPgetClockTime(scip, nlhdlrs[i]->enfotime));
724 SCIPinfoMessage(scip, file, " %10lld", nlhdlrs[i]->nseparated);
725 SCIPinfoMessage(scip, file, " %10lld", nlhdlrs[i]->nbranchscores);
726
727 SCIPinfoMessage(scip, file, "\n");
728 }
729 }
730