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