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