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