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   expr.c
17   	 * @ingroup OTHER_CFILES
18   	 * @brief  functions for algebraic expressions
19   	 * @author Ksenia Bestuzheva
20   	 * @author Benjamin Mueller
21   	 * @author Felipe Serrano
22   	 * @author Stefan Vigerske
23   	 */
24   	
25   	#include <assert.h>
26   	#include <ctype.h>
27   	
28   	#include "scip/expr.h"
29   	#include "scip/struct_expr.h"
30   	#include "scip/pub_misc.h"
31   	#include "scip/clock.h"
32   	#include "scip/set.h"
33   	#include "scip/pub_var.h"
34   	#include "scip/sol.h"
35   	#include "scip/tree.h"
36   	#include "scip/struct_set.h"
37   	#include "scip/struct_stat.h"
38   	#include "scip/nlpi_ipopt.h" /* for LAPACK */
39   	
40   	/*lint -e440*/
41   	/*lint -e441*/
42   	/*lint -e777*/
43   	
44   	/*
45   	 * Data structures
46   	 */
47   	
48   	/** printing to file data */
49   	struct SCIP_ExprPrintData
50   	{
51   	   FILE*                 file;               /**< file to print to */
52   	   SCIP_EXPRITER*        iterator;           /**< iterator to use */
53   	   SCIP_Bool             closefile;          /**< whether file need to be closed when finished printing */
54   	   SCIP_HASHMAP*         leaveexprs;         /**< hashmap storing leave (no children) expressions */
55   	   SCIP_EXPRPRINT_WHAT   whattoprint;        /**< flags that indicate what to print for each expression */
56   	};
57   	
58   	/*
59   	 * Local methods
60   	 */
61   	
62   	/** frees an expression */
63   	static
64   	SCIP_RETCODE freeExpr(
65   	   BMS_BLKMEM*           blkmem,             /**< block memory */
66   	   SCIP_EXPR**           expr                /**< pointer to free the expression */
67   	   )
68   	{
69   	   assert(expr != NULL);
70   	   assert(*expr != NULL);
71   	   assert((*expr)->nuses == 1);
72   	   assert((*expr)->quaddata == NULL);
73   	   assert((*expr)->ownerdata == NULL);
74   	
75   	   /* free children array, if any */
76   	   BMSfreeBlockMemoryArrayNull(blkmem, &(*expr)->children, (*expr)->childrensize);
77   	
78   	   BMSfreeBlockMemory(blkmem, expr);
79   	   assert(*expr == NULL);
80   	
81   	   return SCIP_OKAY;
82   	}
83   	
84   	/*
85   	 * quadratic representation of expression
86   	 */
87   	
88   	/** first time seen quadratically and
89   	 * seen before linearly --> --nlinterms; assign 2; ++nquadterms
90   	 * not seen before linearly --> assing 1; ++nquadterms
91   	 *
92   	 * seen before --> assign += 1
93   	 */
94   	static
95   	SCIP_RETCODE quadDetectProcessExpr(
96   	   SCIP_EXPR*            expr,               /**< the expression */
97   	   SCIP_HASHMAP*         seenexpr,           /**< hash map */
98   	   int*                  nquadterms,         /**< number of quadratic terms */
99   	   int*                  nlinterms           /**< number of linear terms */
100  	   )
101  	{
102  	   if( SCIPhashmapExists(seenexpr, (void*)expr) )
103  	   {
104  	      int nseen = SCIPhashmapGetImageInt(seenexpr, (void*)expr);
105  	
106  	      if( nseen < 0 )
107  	      {
108  	         /* only seen linearly before */
109  	         assert(nseen == -1);
110  	
111  	         --*nlinterms;
112  	         ++*nquadterms;
113  	         SCIP_CALL( SCIPhashmapSetImageInt(seenexpr, (void*)expr, 2) );
114  	      }
115  	      else
116  	      {
117  	         assert(nseen > 0);
118  	         SCIP_CALL( SCIPhashmapSetImageInt(seenexpr, (void*)expr, nseen + 1) );
119  	      }
120  	   }
121  	   else
122  	   {
123  	      ++*nquadterms;
124  	      SCIP_CALL( SCIPhashmapInsertInt(seenexpr, (void*)expr, 1) );
125  	   }
126  	
127  	   return SCIP_OKAY;
128  	}
129  	
130  	/** returns a quadexprterm that contains the expr
131  	 *
132  	 * it either finds one that already exists or creates a new one
133  	 */
134  	static
135  	SCIP_RETCODE quadDetectGetQuadexprterm(
136  	   BMS_BLKMEM*           blkmem,             /**< block memory */
137  	   SCIP_EXPR*            expr,               /**< the expression */
138  	   SCIP_HASHMAP*         expr2idx,           /**< map: expr to index in quadexpr->quadexprterms */
139  	   SCIP_HASHMAP*         seenexpr,           /**< map: expr to number of times it was seen */
140  	   SCIP_QUADEXPR*        quadexpr,           /**< data of quadratic representation of expression */
141  	   SCIP_QUADEXPR_QUADTERM** quadexprterm     /**< buffer to store quadexprterm */
142  	   )
143  	{
144  	   assert(expr != NULL);
145  	   assert(expr2idx != NULL);
146  	   assert(quadexpr != NULL);
147  	   assert(quadexprterm != NULL);
148  	
149  	   if( SCIPhashmapExists(expr2idx, (void*)expr) )
150  	   {
151  	      *quadexprterm = &quadexpr->quadexprterms[SCIPhashmapGetImageInt(expr2idx, (void*)expr)];
152  	      assert((*quadexprterm)->expr == expr);
153  	   }
154  	   else
155  	   {
156  	      SCIP_CALL( SCIPhashmapInsertInt(expr2idx, expr, quadexpr->nquadexprs) );
157  	      *quadexprterm = &quadexpr->quadexprterms[quadexpr->nquadexprs];
158  	      ++quadexpr->nquadexprs;
159  	
160  	      (*quadexprterm)->expr = expr;
161  	      (*quadexprterm)->sqrcoef = 0.0;
162  	      (*quadexprterm)->sqrexpr = NULL;
163  	      (*quadexprterm)->lincoef = 0.0;
164  	      (*quadexprterm)->nadjbilin = 0;
165  	      (*quadexprterm)->adjbilinsize = SCIPhashmapGetImageInt(seenexpr, (void*)expr);
166  	      SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*quadexprterm)->adjbilin, (*quadexprterm)->adjbilinsize) );
167  	   }
168  	
169  	   return SCIP_OKAY;
170  	}
171  	
172  	
173  	/** evaluate and forward-differentiate expression
174  	 *
175  	 * also initializes derivative and bardot to 0.0
176  	 */
177  	static
178  	SCIP_RETCODE evalAndDiff(
179  	   SCIP_SET*             set,                /**< global SCIP settings */
180  	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
181  	   BMS_BLKMEM*           blkmem,             /**< block memory */
182  	   SCIP_EXPR*            expr,               /**< expression to be evaluated */
183  	   SCIP_SOL*             sol,                /**< solution to be evaluated */
184  	   SCIP_Longint          soltag,             /**< tag that uniquely identifies the solution (with its values), or 0. */
185  	   SCIP_SOL*             direction           /**< direction for directional derivative */
186  	   )
187  	{
188  	   SCIP_EXPRITER* it;
189  	
190  	   assert(set != NULL);
191  	   assert(stat != NULL);
192  	   assert(blkmem != NULL);
193  	   assert(expr != NULL);
194  	
195  	   /* assume we'll get a domain error, so we don't have to get this expr back if we abort the iteration
196  	    * if there is no domain error, then we will overwrite the evalvalue in the last leaveexpr stage
197  	    */
198  	   expr->evalvalue = SCIP_INVALID;
199  	   expr->evaltag = soltag;
200  	   expr->dot = SCIP_INVALID;
201  	
202  	   /* start a new difftag */
203  	   ++stat->exprlastdifftag;
204  	
205  	   SCIP_CALL( SCIPexpriterCreate(stat, blkmem, &it) );
206  	   SCIP_CALL( SCIPexpriterInit(it, expr, SCIP_EXPRITER_DFS, TRUE) );
207  	   SCIPexpriterSetStagesDFS(it, SCIP_EXPRITER_LEAVEEXPR);
208  	
209  	   for( expr = SCIPexpriterGetCurrent(it); !SCIPexpriterIsEnd(it); expr = SCIPexpriterGetNext(it) )
210  	   {
211  	      /* evaluate expression only if necessary */
212  	      if( soltag == 0 || expr->evaltag != soltag )
213  	      {
214  	         SCIP_CALL( SCIPexprhdlrEvalExpr(expr->exprhdlr, set, NULL, expr, &expr->evalvalue, NULL, sol) );
215  	
216  	         expr->evaltag = soltag;
217  	      }
218  	
219  	      if( expr->evalvalue == SCIP_INVALID )
220  	         break;
221  	
222  	      if( expr->difftag != stat->exprlastdifftag )
223  	      {
224  	         /* compute forward diff */
225  	         SCIP_CALL( SCIPexprhdlrFwDiffExpr(expr->exprhdlr, set, expr, &expr->dot, direction) );
226  	
227  	         if( expr->dot == SCIP_INVALID )
228  	            break;
229  	
230  	         expr->derivative = 0.0;
231  	         expr->bardot = 0.0;
232  	         expr->difftag = stat->exprlastdifftag;
233  	      }
234  	   }
235  	
236  	   SCIPexpriterFree(&it);
237  	
238  	   return SCIP_OKAY;
239  	}
240  	
241  	
242  	/*
243  	 * Public methods
244  	 */
245  	
246  	/* Undo the defines from pub_expr.h, which exist if NDEBUG is defined. */
247  	#ifdef NDEBUG
248  	#undef SCIPexprhdlrSetCopyFreeHdlr
249  	#undef SCIPexprhdlrSetCopyFreeData
250  	#undef SCIPexprhdlrSetPrint
251  	#undef SCIPexprhdlrSetParse
252  	#undef SCIPexprhdlrSetCurvature
253  	#undef SCIPexprhdlrSetMonotonicity
254  	#undef SCIPexprhdlrSetIntegrality
255  	#undef SCIPexprhdlrSetHash
256  	#undef SCIPexprhdlrSetCompare
257  	#undef SCIPexprhdlrSetDiff
258  	#undef SCIPexprhdlrSetIntEval
259  	#undef SCIPexprhdlrSetSimplify
260  	#undef SCIPexprhdlrSetReverseProp
261  	#undef SCIPexprhdlrSetEstimate
262  	#undef SCIPexprhdlrGetName
263  	#undef SCIPexprhdlrGetDescription
264  	#undef SCIPexprhdlrGetPrecedence
265  	#undef SCIPexprhdlrGetData
266  	#undef SCIPexprhdlrHasPrint
267  	#undef SCIPexprhdlrHasBwdiff
268  	#undef SCIPexprhdlrHasFwdiff
269  	#undef SCIPexprhdlrHasIntEval
270  	#undef SCIPexprhdlrHasEstimate
271  	#undef SCIPexprhdlrHasInitEstimates
272  	#undef SCIPexprhdlrHasSimplify
273  	#undef SCIPexprhdlrHasCurvature
274  	#undef SCIPexprhdlrHasMonotonicity
275  	#undef SCIPexprhdlrHasReverseProp
276  	#undef SCIPexprhdlrGetNCreated
277  	#undef SCIPexprhdlrGetNIntevalCalls
278  	#undef SCIPexprhdlrGetIntevalTime
279  	#undef SCIPexprhdlrGetNReversepropCalls
280  	#undef SCIPexprhdlrGetReversepropTime
281  	#undef SCIPexprhdlrGetNCutoffs
282  	#undef SCIPexprhdlrGetNDomainReductions
283  	#undef SCIPexprhdlrIncrementNDomainReductions
284  	#undef SCIPexprhdlrGetNEstimateCalls
285  	#undef SCIPexprhdlrGetEstimateTime
286  	#undef SCIPexprhdlrGetNBranchings
287  	#undef SCIPexprhdlrIncrementNBranchings
288  	#undef SCIPexprhdlrGetNSimplifyCalls
289  	#undef SCIPexprhdlrGetSimplifyTime
290  	#undef SCIPexprhdlrGetNSimplifications
291  	#endif
292  	
293  	/** create expression handler */
294  	SCIP_RETCODE SCIPexprhdlrCreate(
295  	   BMS_BLKMEM*           blkmem,             /**< block memory */
296  	   SCIP_EXPRHDLR**       exprhdlr,           /**< buffer where to store created expression handler */
297  	   const char*           name,               /**< name of expression handler (must not be NULL) */
298  	   const char*           desc,               /**< description of expression handler (can be NULL) */
299  	   unsigned int          precedence,         /**< precedence of expression operation (used for printing) */
300  	   SCIP_DECL_EXPREVAL((*eval)),              /**< point evaluation callback (must not be NULL) */
301  	   SCIP_EXPRHDLRDATA*    data                /**< data of expression handler (can be NULL) */
302  	   )
303  	{
304  	   assert(exprhdlr != NULL);
305  	   assert(name != NULL);
306  	
307  	   SCIP_ALLOC( BMSallocClearBlockMemory(blkmem, exprhdlr) );
308  	
309  	   SCIP_ALLOC( BMSduplicateMemoryArray(&(*exprhdlr)->name, name, strlen(name)+1) );
310  	   if( desc != NULL )
311  	   {
312  	      SCIP_ALLOC( BMSduplicateMemoryArray(&(*exprhdlr)->desc, desc, strlen(desc)+1) );
313  	   }
314  	
315  	   (*exprhdlr)->precedence = precedence;
316  	   (*exprhdlr)->eval = eval;
317  	   (*exprhdlr)->data = data;
318  	
319  	   /* create clocks */
320  	   SCIP_CALL( SCIPclockCreate(&(*exprhdlr)->estimatetime, SCIP_CLOCKTYPE_DEFAULT) );
321  	   SCIP_CALL( SCIPclockCreate(&(*exprhdlr)->intevaltime, SCIP_CLOCKTYPE_DEFAULT) );
322  	   SCIP_CALL( SCIPclockCreate(&(*exprhdlr)->proptime, SCIP_CLOCKTYPE_DEFAULT) );
323  	   SCIP_CALL( SCIPclockCreate(&(*exprhdlr)->simplifytime, SCIP_CLOCKTYPE_DEFAULT) );
324  	
325  	   return SCIP_OKAY;
326  	}
327  	
328  	/** frees expression handler */
329  	SCIP_RETCODE SCIPexprhdlrFree(
330  	   SCIP_EXPRHDLR**       exprhdlr,           /**< pointer to expression handler to be freed */
331  	   SCIP_SET*             set,                /**< global SCIP settings */
332  	   BMS_BLKMEM*           blkmem              /**< block memory */
333  	   )
334  	{
335  	   if( (*exprhdlr)->freehdlr != NULL )
336  	   {
337  	      SCIP_CALL( (*exprhdlr)->freehdlr(set->scip, *exprhdlr, &(*exprhdlr)->data) );
338  	   }
339  	
340  	   /* free clocks */
341  	   SCIPclockFree(&(*exprhdlr)->simplifytime);
342  	   SCIPclockFree(&(*exprhdlr)->intevaltime);
343  	   SCIPclockFree(&(*exprhdlr)->proptime);
344  	   SCIPclockFree(&(*exprhdlr)->estimatetime);
345  	
346  	   BMSfreeMemoryArrayNull(&(*exprhdlr)->desc);
347  	   BMSfreeMemoryArray(&(*exprhdlr)->name);
348  	
349  	   BMSfreeBlockMemory(blkmem, exprhdlr);
350  	
351  	   return SCIP_OKAY;
352  	}
353  	
354  	/**@addtogroup PublicExprHandlerMethods
355  	 * @{
356  	 */
357  	
358  	/** set the expression handler callbacks to copy and free an expression handler */
359  	void SCIPexprhdlrSetCopyFreeHdlr(
360  	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
361  	   SCIP_DECL_EXPRCOPYHDLR((*copyhdlr)),      /**< handler copy callback (can be NULL) */
362  	   SCIP_DECL_EXPRFREEHDLR((*freehdlr))       /**< handler free callback (can be NULL) */
363  	   )
364  	{
365  	   assert(exprhdlr != NULL);
366  	
367  	   exprhdlr->copyhdlr = copyhdlr;
368  	   exprhdlr->freehdlr = freehdlr;
369  	}
370  	
371  	/** set the expression handler callbacks to copy and free expression data */
372  	void SCIPexprhdlrSetCopyFreeData(
373  	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
374  	   SCIP_DECL_EXPRCOPYDATA((*copydata)),      /**< expression data copy callback (can be NULL for expressions
375  	                                                  without data) */
376  	   SCIP_DECL_EXPRFREEDATA((*freedata))       /**< expression data free callback (can be NULL if data does not
377  	                                                  need to be freed) */
378  	   )
379  	{  /*lint --e{715}*/
380  	   assert(exprhdlr != NULL);
381  	
382  	   exprhdlr->copydata = copydata;
383  	   exprhdlr->freedata = freedata;
384  	}
385  	
386  	/** set the print callback of an expression handler */
387  	void SCIPexprhdlrSetPrint(
388  	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
389  	   SCIP_DECL_EXPRPRINT((*print))             /**< print callback (can be NULL) */
390  	   )
391  	{
392  	   assert(exprhdlr != NULL);
393  	
394  	   exprhdlr->print = print;
395  	}
396  	
397  	/** set the parse callback of an expression handler */
398  	void SCIPexprhdlrSetParse(
399  	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
400  	   SCIP_DECL_EXPRPARSE((*parse))             /**< parse callback (can be NULL) */
401  	   )
402  	{
403  	   assert(exprhdlr != NULL);
404  	
405  	   exprhdlr->parse = parse;
406  	}
407  	
408  	/** set the curvature detection callback of an expression handler */
409  	void SCIPexprhdlrSetCurvature(
410  	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
411  	   SCIP_DECL_EXPRCURVATURE((*curvature))     /**< curvature detection callback (can be NULL) */
412  	   )
413  	{
414  	   assert(exprhdlr != NULL);
415  	
416  	   exprhdlr->curvature = curvature;
417  	}
418  	
419  	/** set the monotonicity detection callback of an expression handler */
420  	void SCIPexprhdlrSetMonotonicity(
421  	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
422  	   SCIP_DECL_EXPRMONOTONICITY((*monotonicity)) /**< monotonicity detection callback (can be NULL) */
423  	   )
424  	{
425  	   assert(exprhdlr != NULL);
426  	
427  	   exprhdlr->monotonicity = monotonicity;
428  	}
429  	
430  	/** set the integrality detection callback of an expression handler */
431  	void SCIPexprhdlrSetIntegrality(
432  	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
433  	   SCIP_DECL_EXPRINTEGRALITY((*integrality)) /**< integrality detection callback (can be NULL) */
434  	   )
435  	{
436  	   assert(exprhdlr != NULL);
437  	
438  	   exprhdlr->integrality = integrality;
439  	}
440  	
441  	/** set the hash callback of an expression handler */
442  	void SCIPexprhdlrSetHash(
443  	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
444  	   SCIP_DECL_EXPRHASH((*hash))               /**< hash callback (can be NULL) */
445  	   )
446  	{
447  	   assert(exprhdlr != NULL);
448  	
449  	   exprhdlr->hash = hash;
450  	}
451  	
452  	/** set the compare callback of an expression handler */
453  	void SCIPexprhdlrSetCompare(
454  	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
455  	   SCIP_DECL_EXPRCOMPARE((*compare))         /**< compare callback (can be NULL) */
456  	   )
457  	{
458  	   assert(exprhdlr != NULL);
459  	
460  	   exprhdlr->compare = compare;
461  	}
462  	
463  	/** set differentiation callbacks of an expression handler */
464  	void SCIPexprhdlrSetDiff(
465  	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
466  	   SCIP_DECL_EXPRBWDIFF((*bwdiff)),          /**< backward derivative evaluation callback (can be NULL) */
467  	   SCIP_DECL_EXPRFWDIFF((*fwdiff)),          /**< forward derivative evaluation callback (can be NULL) */
468  	   SCIP_DECL_EXPRBWFWDIFF((*bwfwdiff))       /**< backward-forward derivative evaluation callback (can be NULL) */
469  	   )
470  	{
471  	   assert(exprhdlr != NULL);
472  	
473  	   exprhdlr->bwdiff = bwdiff;
474  	   exprhdlr->fwdiff = fwdiff;
475  	   exprhdlr->bwfwdiff = bwfwdiff;
476  	}
477  	
478  	/** set the interval evaluation callback of an expression handler */
479  	void SCIPexprhdlrSetIntEval(
480  	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
481  	   SCIP_DECL_EXPRINTEVAL((*inteval))         /**< interval evaluation callback (can be NULL) */
482  	   )
483  	{
484  	   assert(exprhdlr != NULL);
485  	
486  	   exprhdlr->inteval = inteval;
487  	}
488  	
489  	/** set the simplify callback of an expression handler */
490  	void SCIPexprhdlrSetSimplify(
491  	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
492  	   SCIP_DECL_EXPRSIMPLIFY((*simplify))       /**< simplify callback (can be NULL) */
493  	   )
494  	{
495  	   assert(exprhdlr != NULL);
496  	
497  	   exprhdlr->simplify = simplify;
498  	}
499  	
500  	/** set the reverse propagation callback of an expression handler */
501  	void SCIPexprhdlrSetReverseProp(
502  	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
503  	   SCIP_DECL_EXPRREVERSEPROP((*reverseprop)) /**< reverse propagation callback (can be NULL) */
504  	   )
505  	{
506  	   assert(exprhdlr != NULL);
507  	
508  	   exprhdlr->reverseprop = reverseprop;
509  	}
510  	
511  	/** set the estimation callbacks of an expression handler */
512  	void SCIPexprhdlrSetEstimate(
513  	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
514  	   SCIP_DECL_EXPRINITESTIMATES((*initestimates)), /**< initial estimators callback (can be NULL) */
515  	   SCIP_DECL_EXPRESTIMATE((*estimate))       /**< estimator callback (can be NULL) */
516  	   )
517  	{
518  	   assert(exprhdlr != NULL);
519  	
520  	   exprhdlr->initestimates = initestimates;
521  	   exprhdlr->estimate = estimate;
522  	}
523  	
524  	/** gives the name of an expression handler */
525  	const char* SCIPexprhdlrGetName(
526  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
527  	   )
528  	{
529  	   assert(exprhdlr != NULL);
530  	
531  	   return exprhdlr->name;
532  	}
533  	
534  	/** gives the description of an expression handler (can be NULL) */
535  	const char* SCIPexprhdlrGetDescription(
536  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
537  	   )
538  	{
539  	   assert(exprhdlr != NULL);
540  	
541  	   return exprhdlr->desc;
542  	}
543  	
544  	/** gives the precedence of an expression handler */
545  	unsigned int SCIPexprhdlrGetPrecedence(
546  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
547  	   )
548  	{
549  	   assert(exprhdlr != NULL);
550  	
551  	   return exprhdlr->precedence;
552  	}
553  	
554  	/** gives the data of an expression handler */
555  	SCIP_EXPRHDLRDATA* SCIPexprhdlrGetData(
556  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
557  	   )
558  	{
559  	   assert(exprhdlr != NULL);
560  	
561  	   return exprhdlr->data;
562  	}
563  	
564  	/** returns whether expression handler implements the print callback */
565  	SCIP_Bool SCIPexprhdlrHasPrint(
566  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
567  	   )
568  	{
569  	   assert(exprhdlr != NULL);
570  	
571  	   return exprhdlr->print != NULL;
572  	}
573  	
574  	/** returns whether expression handler implements the backward differentiation callback */
575  	SCIP_Bool SCIPexprhdlrHasBwdiff(
576  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
577  	   )
578  	{
579  	   assert(exprhdlr != NULL);
580  	
581  	   return exprhdlr->bwdiff != NULL;
582  	}
583  	
584  	/** returns whether expression handler implements the forward differentiation callback */
585  	SCIP_Bool SCIPexprhdlrHasFwdiff(
586  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
587  	   )
588  	{
589  	   assert(exprhdlr != NULL);
590  	
591  	   return exprhdlr->fwdiff != NULL;
592  	}
593  	
594  	/** returns whether expression handler implements the interval evaluation callback */
595  	SCIP_Bool SCIPexprhdlrHasIntEval(
596  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
597  	   )
598  	{
599  	   assert(exprhdlr != NULL);
600  	
601  	   return exprhdlr->inteval != NULL;
602  	}
603  	
604  	/** returns whether expression handler implements the estimator callback */
605  	SCIP_Bool SCIPexprhdlrHasEstimate(
606  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
607  	   )
608  	{
609  	   assert(exprhdlr != NULL);
610  	
611  	   return exprhdlr->estimate != NULL;
612  	}
613  	
614  	/** returns whether expression handler implements the initial estimators callback */
615  	SCIP_Bool SCIPexprhdlrHasInitEstimates(
616  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
617  	   )
618  	{
619  	   assert(exprhdlr != NULL);
620  	
621  	   return exprhdlr->initestimates != NULL;
622  	}
623  	
624  	/** returns whether expression handler implements the simplification callback */
625  	SCIP_Bool SCIPexprhdlrHasSimplify(
626  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
627  	   )
628  	{
629  	   assert(exprhdlr != NULL);
630  	
631  	   return exprhdlr->simplify != NULL;
632  	}
633  	
634  	/** returns whether expression handler implements the curvature callback */
635  	SCIP_Bool SCIPexprhdlrHasCurvature(
636  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
637  	   )
638  	{
639  	   assert(exprhdlr != NULL);
640  	
641  	   return exprhdlr->curvature != NULL;
642  	}
643  	
644  	/** returns whether expression handler implements the monotonicity callback */
645  	SCIP_Bool SCIPexprhdlrHasMonotonicity(
646  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
647  	   )
648  	{
649  	   assert(exprhdlr != NULL);
650  	
651  	   return exprhdlr->monotonicity != NULL;
652  	}
653  	
654  	/** returns whether expression handler implements the reverse propagation callback */
655  	SCIP_Bool SCIPexprhdlrHasReverseProp(
656  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
657  	   )
658  	{
659  	   assert(exprhdlr != NULL);
660  	
661  	   return exprhdlr->reverseprop != NULL;
662  	}
663  	
664  	/** compares two expression handler w.r.t. their name */
665  	SCIP_DECL_SORTPTRCOMP(SCIPexprhdlrComp)
666  	{
667  	   return strcmp(((SCIP_EXPRHDLR*)elem1)->name, ((SCIP_EXPRHDLR*)elem2)->name);
668  	}
669  	
670  	/** gets number of times an expression has been created with given expression handler */
671  	unsigned int SCIPexprhdlrGetNCreated(
672  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
673  	   )
674  	{
675  	   assert(exprhdlr != NULL);
676  	
677  	   return exprhdlr->ncreated;
678  	}
679  	
680  	/** gets number of times the interval evaluation callback was called */
681  	SCIP_Longint SCIPexprhdlrGetNIntevalCalls(
682  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
683  	   )
684  	{
685  	   assert(exprhdlr != NULL);
686  	
687  	   return exprhdlr->nintevalcalls;
688  	}
689  	
690  	/** gets time spend in interval evaluation callback */
691  	SCIP_Real SCIPexprhdlrGetIntevalTime(
692  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
693  	   )
694  	{
695  	   assert(exprhdlr != NULL);
696  	
697  	   return SCIPclockGetTime(exprhdlr->intevaltime);
698  	}
699  	
700  	/** gets number of times the reverse propagation callback was called */
701  	SCIP_Longint SCIPexprhdlrGetNReversepropCalls(
702  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
703  	   )
704  	{
705  	   assert(exprhdlr != NULL);
706  	
707  	   return exprhdlr->npropcalls;
708  	}
709  	
710  	/** gets time spend in reverse propagation callback */
711  	SCIP_Real SCIPexprhdlrGetReversepropTime(
712  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
713  	   )
714  	{
715  	   assert(exprhdlr != NULL);
716  	
717  	   return SCIPclockGetTime(exprhdlr->proptime);
718  	}
719  	
720  	/** gets number of times an empty interval was found in reverse propagation */
721  	SCIP_Longint SCIPexprhdlrGetNCutoffs(
722  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
723  	   )
724  	{
725  	   assert(exprhdlr != NULL);
726  	
727  	   return exprhdlr->ncutoffs;
728  	}
729  	
730  	/** gets number of times a bound reduction was found in reverse propagation (and accepted by caller) */
731  	SCIP_Longint SCIPexprhdlrGetNDomainReductions(
732  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
733  	   )
734  	{
735  	   assert(exprhdlr != NULL);
736  	
737  	   return exprhdlr->ndomreds;
738  	}
739  	
740  	/** increments the domain reductions count of an expression handler */
741  	void SCIPexprhdlrIncrementNDomainReductions(
742  	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
743  	   int                   nreductions         /**< number of reductions to add to counter */
744  	   )
745  	{
746  	   assert(exprhdlr != NULL);
747  	   assert(nreductions >= 0);
748  	
749  	   exprhdlr->ndomreds += nreductions;
750  	}
751  	
752  	/** gets number of times the estimation callback was called */
753  	SCIP_Longint SCIPexprhdlrGetNEstimateCalls(
754  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
755  	   )
756  	{
757  	   assert(exprhdlr != NULL);
758  	
759  	   return exprhdlr->nestimatecalls;
760  	}
761  	
762  	/** gets time spend in estimation callback */
763  	SCIP_Real SCIPexprhdlrGetEstimateTime(
764  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
765  	   )
766  	{
767  	   assert(exprhdlr != NULL);
768  	
769  	   return SCIPclockGetTime(exprhdlr->estimatetime);
770  	}
771  	
772  	/** gets number of times branching candidates reported by of this expression handler were used to
773  	 * assemble branching candidates
774  	 *
775  	 * that is, how often did we consider branching on a child of this expression
776  	 */
777  	SCIP_Longint SCIPexprhdlrGetNBranchings(
778  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
779  	   )
780  	{
781  	   assert(exprhdlr != NULL);
782  	
783  	   return exprhdlr->nbranchscores;
784  	}
785  	
786  	/** increments the branching candidates count of an expression handler */
787  	void SCIPexprhdlrIncrementNBranchings(
788  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
789  	   )
790  	{
791  	   assert(exprhdlr != NULL);
792  	
793  	   ++exprhdlr->nbranchscores;
794  	}
795  	
796  	/** gets number of times the simplify callback was called */
797  	SCIP_Longint SCIPexprhdlrGetNSimplifyCalls(
798  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
799  	   )
800  	{
801  	   assert(exprhdlr != NULL);
802  	
803  	   return exprhdlr->nsimplifycalls;
804  	}
805  	
806  	/** gets time spend in simplify callback */
807  	SCIP_Real SCIPexprhdlrGetSimplifyTime(
808  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
809  	   )
810  	{
811  	   assert(exprhdlr != NULL);
812  	
813  	   return SCIPclockGetTime(exprhdlr->simplifytime);
814  	}
815  	
816  	/** gets number of times the simplify callback found a simplification */
817  	SCIP_Longint SCIPexprhdlrGetNSimplifications(
818  	   SCIP_EXPRHDLR*        exprhdlr            /**< expression handler */
819  	   )
820  	{
821  	   assert(exprhdlr != NULL);
822  	
823  	   return exprhdlr->nsimplified;
824  	}
825  	
826  	/** @} */
827  	
828  	/** copies the given expression handler to a new scip */
829  	SCIP_RETCODE SCIPexprhdlrCopyInclude(
830  	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
831  	   SCIP_SET*             targetset           /**< SCIP_SET of SCIP to copy to */
832  	   )
833  	{
834  	   assert(exprhdlr != NULL);
835  	   assert(targetset != NULL);
836  	   assert(targetset->scip != NULL);
837  	
838  	   if( exprhdlr->copyhdlr != NULL )
839  	   {
840  	      SCIPsetDebugMsg(targetset, "including expression handler <%s> in subscip %p\n",
841  	            SCIPexprhdlrGetName(exprhdlr), (void*)targetset->scip);
842  	      SCIP_CALL( exprhdlr->copyhdlr(targetset->scip, exprhdlr) );
843  	   }
844  	   else
845  	   {
846  	      SCIPsetDebugMsg(targetset, "expression handler <%s> cannot be copied to subscip %p due "
847  	            "to missing copyhdlr callback\n", SCIPexprhdlrGetName(exprhdlr), (void*)targetset->scip);
848  	   }
849  	
850  	   return SCIP_OKAY;
851  	}
852  	
853  	/** initialization of expression handler (resets statistics) */
854  	void SCIPexprhdlrInit(
855  	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
856  	   SCIP_SET*             set                 /**< global SCIP settings */
857  	   )
858  	{
859  	   assert(exprhdlr != NULL);
860  	
861  	   if( set->misc_resetstat )
862  	   {
863  	      exprhdlr->ncreated = 0;
864  	      exprhdlr->nestimatecalls = 0;
865  	      exprhdlr->nintevalcalls = 0;
866  	      exprhdlr->npropcalls = 0;
867  	      exprhdlr->ncutoffs = 0;
868  	      exprhdlr->ndomreds = 0;
869  	      exprhdlr->nbranchscores = 0;
870  	      exprhdlr->nsimplifycalls = 0;
871  	      exprhdlr->nsimplified = 0;
872  	
873  	      SCIPclockReset(exprhdlr->estimatetime);
874  	      SCIPclockReset(exprhdlr->intevaltime);
875  	      SCIPclockReset(exprhdlr->proptime);
876  	      SCIPclockReset(exprhdlr->simplifytime);
877  	   }
878  	}
879  	
880  	/** calls the print callback of an expression handler
881  	 *
882  	 * The method prints an expression.
883  	 * It is called while iterating over the expression graph at different stages.
884  	 *
885  	 * @see SCIP_DECL_EXPRPRINT
886  	 */
887  	SCIP_RETCODE SCIPexprhdlrPrintExpr(
888  	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
889  	   SCIP_SET*             set,                /**< global SCIP settings */
890  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
891  	   SCIP_EXPR*            expr,               /**< expression */
892  	   SCIP_EXPRITER_STAGE   stage,              /**< stage of expression iteration */
893  	   int                   currentchild,       /**< index of current child if in stage visitingchild or visitedchild */
894  	   unsigned int          parentprecedence,   /**< precedence of parent */
895  	   FILE*                 file                /**< the file to print to */
896  	   )
897  	{
898  	   assert(exprhdlr != NULL);
899  	   assert(set != NULL);
900  	   assert(expr != NULL);
901  	   assert(expr->exprhdlr == exprhdlr);
902  	   assert(messagehdlr != NULL);
903  	
904  	   if( SCIPexprhdlrHasPrint(exprhdlr) )
905  	   {
906  	      SCIP_CALL( exprhdlr->print(set->scip, expr, stage, currentchild, parentprecedence, file) );
907  	   }
908  	   else
909  	   {
910  	      /* default: <hdlrname>(<child1>, <child2>, ...) */
911  	      switch( stage )
912  	      {
913  	         case SCIP_EXPRITER_ENTEREXPR :
914  	         {
915  	            SCIPmessageFPrintInfo(messagehdlr, file, "%s", SCIPexprhdlrGetName(expr->exprhdlr));
916  	            if( expr->nchildren > 0 )
917  	            {
918  	               SCIPmessageFPrintInfo(messagehdlr, file, "(");
919  	            }
920  	            break;
921  	         }
922  	
923  	         case SCIP_EXPRITER_VISITEDCHILD :
924  	         {
925  	            assert(currentchild >= 0);
926  	            assert(currentchild < expr->nchildren);
927  	            if( currentchild < expr->nchildren-1 )
928  	            {
929  	               SCIPmessageFPrintInfo(messagehdlr, file, ", ");
930  	            }
931  	            else
932  	            {
933  	               SCIPmessageFPrintInfo(messagehdlr, file, ")");
934  	            }
935  	
936  	            break;
937  	         }
938  	
939  	         case SCIP_EXPRITER_VISITINGCHILD :
940  	         case SCIP_EXPRITER_LEAVEEXPR :
941  	         default:
942  	            break;
943  	      }
944  	   }
945  	
946  	   return SCIP_OKAY;
947  	}
948  	
949  	/** calls the parse callback of an expression handler
950  	 *
951  	 * The method parses an expression.
952  	 * It should be called when parsing an expression and an operator with the expr handler name is found.
953  	 *
954  	 * @see SCIP_DECL_EXPRPARSE
955  	 */
956  	SCIP_RETCODE SCIPexprhdlrParseExpr(
957  	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
958  	   SCIP_SET*             set,                /**< global SCIP settings */
959  	   const char*           string,             /**< string containing expression to be parse */
960  	   const char**          endstring,          /**< buffer to store the position of string after parsing */
961  	   SCIP_EXPR**           expr,               /**< buffer to store the parsed expression */
962  	   SCIP_Bool*            success,            /**< buffer to store whether the parsing was successful or not */
963  	   SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call on expression copy to create ownerdata */
964  	   void*                 ownercreatedata     /**< data to pass to ownercreate */
965  	   )
966  	{
967  	   assert(exprhdlr != NULL);
968  	   assert(set != NULL);
969  	   assert(expr != NULL);
970  	
971  	   *expr = NULL;
972  	
973  	   if( exprhdlr->parse == NULL )
974  	   {
975  	      /* TODO we could just look for a comma separated list of operands and try to initialize the expr with this one?
976  	       * That would be sufficient for sin, cos, exp, log, abs, for example.
977  	       */
978  	      SCIPdebugMessage("Expression handler <%s> has no parsing method.\n", SCIPexprhdlrGetName(exprhdlr));
979  	      *success = FALSE;
980  	      return SCIP_OKAY;
981  	   }
982  	
983  	   /* give control to exprhdlr's parser */
984  	   SCIP_CALL( exprhdlr->parse(set->scip, exprhdlr, string, endstring, expr, success, ownercreate, ownercreatedata) );
985  	
986  	   assert(*success || (*expr == NULL));
987  	
988  	   return SCIP_OKAY;
989  	}
990  	
991  	/** calls the curvature check callback of an expression handler
992  	 *
993  	 * @see SCIP_DECL_EXPRCURVATURE
994  	 */
995  	SCIP_RETCODE SCIPexprhdlrCurvatureExpr(
996  	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
997  	   SCIP_SET*             set,                /**< global SCIP settings */
998  	   SCIP_EXPR*            expr,               /**< expression to check the curvature for */
999  	   SCIP_EXPRCURV         exprcurvature,      /**< desired curvature of this expression */
1000 	   SCIP_Bool*            success,            /**< buffer to store whether the desired curvature be obtained */
1001 	   SCIP_EXPRCURV*        childcurv           /**< array to store required curvature for each child */
1002 	   )
1003 	{
1004 	   assert(exprhdlr != NULL);
1005 	   assert(set != NULL);
1006 	   assert(expr != NULL);
1007 	   assert(expr->exprhdlr == exprhdlr);
1008 	   assert(success != NULL);
1009 	
1010 	   *success = FALSE;
1011 	
1012 	   if( exprhdlr->curvature != NULL )
1013 	   {
1014 	      SCIP_CALL( exprhdlr->curvature(set->scip, expr, exprcurvature, success, childcurv) );
1015 	   }
1016 	
1017 	   return SCIP_OKAY;
1018 	}
1019 	
1020 	/** calls the monotonicity check callback of an expression handler
1021 	 *
1022 	 * @see SCIP_DECL_EXPRMONOTONICITY
1023 	 */
1024 	SCIP_RETCODE SCIPexprhdlrMonotonicityExpr(
1025 	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
1026 	   SCIP_SET*             set,                /**< global SCIP settings */
1027 	   SCIP_EXPR*            expr,               /**< expression to check the monotonicity for */
1028 	   int                   childidx,           /**< index of the considered child expression */
1029 	   SCIP_MONOTONE*        result              /**< buffer to store the monotonicity */
1030 	   )
1031 	{
1032 	   assert(exprhdlr != NULL);
1033 	   assert(set != NULL);
1034 	   assert(expr != NULL);
1035 	   assert(expr->exprhdlr == exprhdlr);
1036 	   assert(result != NULL);
1037 	
1038 	   *result = SCIP_MONOTONE_UNKNOWN;
1039 	
1040 	   /* check whether the expression handler implements the monotonicity callback */
1041 	   if( exprhdlr->monotonicity != NULL )
1042 	   {
1043 	      SCIP_CALL( exprhdlr->monotonicity(set->scip, expr, childidx, result) );
1044 	   }
1045 	
1046 	   return SCIP_OKAY;
1047 	}
1048 	
1049 	/** calls the integrality check callback of an expression handler
1050 	 *
1051 	 * @see SCIP_DECL_EXPRINTEGRALITY
1052 	 */
1053 	SCIP_RETCODE SCIPexprhdlrIntegralityExpr(
1054 	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
1055 	   SCIP_SET*             set,                /**< global SCIP settings */
1056 	   SCIP_EXPR*            expr,               /**< expression to check integrality for */
1057 	   SCIP_Bool*            isintegral          /**< buffer to store whether expression is integral */
1058 	   )
1059 	{
1060 	   assert(exprhdlr != NULL);
1061 	   assert(set != NULL);
1062 	   assert(expr != NULL);
1063 	   assert(expr->exprhdlr == exprhdlr);
1064 	   assert(isintegral != NULL);
1065 	
1066 	   *isintegral = FALSE;
1067 	
1068 	   /* check whether the expression handler implements the monotonicity callback */
1069 	   if( exprhdlr->integrality != NULL )
1070 	   {
1071 	      SCIP_CALL( exprhdlr->integrality(set->scip, expr, isintegral) );
1072 	   }
1073 	
1074 	   return SCIP_OKAY;
1075 	}
1076 	
1077 	/** calls the hash callback of an expression handler
1078 	 *
1079 	 * The method hashes an expression by taking the hashes of its children into account.
1080 	 *
1081 	 * @see SCIP_DECL_EXPRHASH
1082 	 */
1083 	SCIP_RETCODE SCIPexprhdlrHashExpr(
1084 	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
1085 	   SCIP_SET*             set,                /**< global SCIP settings */
1086 	   SCIP_EXPR*            expr,               /**< expression to be hashed */
1087 	   unsigned int*         hashkey,            /**< buffer to store the hash value */
1088 	   unsigned int*         childrenhashes      /**< array with hash values of children */
1089 	   )
1090 	{
1091 	   assert(exprhdlr != NULL);
1092 	   assert(set != NULL);
1093 	   assert(expr != NULL);
1094 	   assert(expr->exprhdlr == exprhdlr);
1095 	   assert(hashkey != NULL);
1096 	   assert(childrenhashes != NULL || expr->nchildren == 0);
1097 	
1098 	   if( expr->exprhdlr->hash != NULL )
1099 	   {
1100 	      SCIP_CALL( expr->exprhdlr->hash(set->scip, expr, hashkey, childrenhashes) );
1101 	   }
1102 	   else
1103 	   {
1104 	      int i;
1105 	
1106 	      /* compute initial hash from expression handler name if callback is not implemented
1107 	       * this can lead to more collisions and thus a larger number of expensive expression compare calls
1108 	       */
1109 	      *hashkey = 0;
1110 	      for( i = 0; expr->exprhdlr->name[i] != '\0'; i++ )
1111 	         *hashkey += (unsigned int) expr->exprhdlr->name[i]; /*lint !e571*/
1112 	
1113 	      *hashkey = SCIPcalcFibHash((SCIP_Real)*hashkey);
1114 	
1115 	      /* now make use of the hashkeys of the children */
1116 	      for( i = 0; i < expr->nchildren; ++i )
1117 	         *hashkey ^= childrenhashes[i];
1118 	   }
1119 	
1120 	   return SCIP_OKAY;
1121 	}
1122 	
1123 	/** calls the compare callback of an expression handler
1124 	 *
1125 	 * The method receives two expressions, expr1 and expr2, and returns
1126 	 * - -1 if expr1 < expr2,
1127 	 * - 0  if expr1 = expr2,
1128 	 * - 1  if expr1 > expr2.
1129 	 *
1130 	 * @see SCIP_DECL_EXPRCOMPARE
1131 	 */
1132 	int SCIPexprhdlrCompareExpr(
1133 	   SCIP_SET*             set,                /**< global SCIP settings */
1134 	   SCIP_EXPR*            expr1,              /**< first expression in comparison */
1135 	   SCIP_EXPR*            expr2               /**< second expression in comparison */
1136 	   )
1137 	{
1138 	   int i;
1139 	
1140 	   assert(expr1 != NULL);
1141 	   assert(expr2 != NULL);
1142 	   assert(expr1->exprhdlr == expr2->exprhdlr);
1143 	
1144 	   if( expr1->exprhdlr->compare != NULL )
1145 	   {
1146 	      /* enforces OR1-OR4 */
1147 	      return expr1->exprhdlr->compare(set->scip, expr1, expr2);
1148 	   }
1149 	
1150 	   /* enforces OR5: default comparison method of expressions of the same type:
1151 	    * expr1 < expr2 if and only if expr1_i = expr2_i for all i < k and expr1_k < expr2_k.
1152 	    * if there is no such k, use number of children to decide
1153 	    * if number of children is equal, both expressions are equal
1154 	    * @note: Warning, this method doesn't know about expression data. So if your expressions have special data,
1155 	    * you must implement the compare callback: SCIP_DECL_EXPRCOMPARE
1156 	    */
1157 	   for( i = 0; i < expr1->nchildren && i < expr2->nchildren; ++i )
1158 	   {
1159 	      int compareresult = SCIPexprCompare(set, expr1->children[i], expr2->children[i]);
1160 	      if( compareresult != 0 )
1161 	         return compareresult;
1162 	   }
1163 	
1164 	   return expr1->nchildren == expr2->nchildren ? 0 : expr1->nchildren < expr2->nchildren ? -1 : 1;
1165 	}
1166 	
1167 	/** calls the evaluation callback of an expression handler
1168 	 *
1169 	 * The method evaluates an expression by taking the values of its children into account.
1170 	 *
1171 	 * Further, allows to evaluate w.r.t. given expression and children values instead of those stored in children expressions.
1172 	 *
1173 	 * @see SCIP_DECL_EXPREVAL
1174 	 */
1175 	SCIP_RETCODE SCIPexprhdlrEvalExpr(
1176 	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
1177 	   SCIP_SET*             set,                /**< global SCIP settings */
1178 	   BMS_BUFMEM*           bufmem,             /**< buffer memory, can be NULL if childrenvals is NULL */
1179 	   SCIP_EXPR*            expr,               /**< expression to be evaluated */
1180 	   SCIP_Real*            val,                /**< buffer to store value of expression */
1181 	   SCIP_Real*            childrenvals,       /**< values for children, or NULL if values stored in children should be used */
1182 	   SCIP_SOL*             sol                 /**< solution that is evaluated (can be NULL) */
1183 	   )
1184 	{
1185 	   SCIP_Real* origvals = NULL;
1186 	
1187 	   assert(exprhdlr != NULL);
1188 	   assert(set != NULL);
1189 	   assert(expr != NULL);
1190 	   assert(expr->exprhdlr == exprhdlr);
1191 	   assert(exprhdlr->eval != NULL);
1192 	   assert(val != NULL);
1193 	
1194 	   /* temporarily overwrite the evalvalue in all children with values from childrenvals */
1195 	   if( childrenvals != NULL && expr->nchildren > 0 )
1196 	   {
1197 	      int c;
1198 	
1199 	      assert(bufmem != NULL);
1200 	
1201 	      SCIP_ALLOC( BMSallocBufferMemoryArray(bufmem, &origvals, expr->nchildren) );
1202 	
1203 	      for( c = 0; c < expr->nchildren; ++c )
1204 	      {
1205 	         origvals[c] = expr->children[c]->evalvalue;
1206 	         expr->children[c]->evalvalue = childrenvals[c];
1207 	      }
1208 	   }
1209 	
1210 	   /* call expression eval callback */
1211 	   SCIP_CALL( exprhdlr->eval(set->scip, expr, val, sol) );
1212 	
1213 	   /* if there was some evaluation error (e.g., overflow) that hasn't been caught yet, then do so now */
1214 	   if( !SCIPisFinite(*val) )
1215 	      *val = SCIP_INVALID;
1216 	
1217 	   /* restore original evalvalues in children */
1218 	   if( origvals != NULL )
1219 	   {
1220 	      int c;
1221 	      for( c = 0; c < expr->nchildren; ++c )
1222 	         expr->children[c]->evalvalue = origvals[c];
1223 	
1224 	      BMSfreeBufferMemoryArray(bufmem, &origvals);
1225 	   }
1226 	
1227 	   return SCIP_OKAY;
1228 	}
1229 	
1230 	/** calls the backward derivative evaluation callback of an expression handler
1231 	 *
1232 	 * The method should compute the partial derivative of expr w.r.t its child at childidx.
1233 	 * That is, it returns
1234 	 * \f[
1235 	 *   \frac{\partial \text{expr}}{\partial \text{child}_{\text{childidx}}}
1236 	 * \f]
1237 	 *
1238 	 * Further, allows to differentiate w.r.t. given expression and children values instead of those stored in children expressions.
1239 	 *
1240 	 * @see SCIP_DECL_EXPRBWDIFF
1241 	 */
1242 	SCIP_RETCODE SCIPexprhdlrBwDiffExpr(
1243 	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
1244 	   SCIP_SET*             set,                /**< global SCIP settings */
1245 	   BMS_BUFMEM*           bufmem,             /**< buffer memory, can be NULL if childrenvals is NULL */
1246 	   SCIP_EXPR*            expr,               /**< expression to be differentiated */
1247 	   int                   childidx,           /**< index of the child */
1248 	   SCIP_Real*            derivative,         /**< buffer to store the partial derivative w.r.t. the i-th children */
1249 	   SCIP_Real*            childrenvals,       /**< values for children, or NULL if values stored in children should be used */
1250 	   SCIP_Real             exprval             /**< value for expression, used only if childrenvals is not NULL */
1251 	   )
1252 	{
1253 	   SCIP_Real* origchildrenvals;
1254 	   SCIP_Real origexprval;
1255 	   int c;
1256 	
1257 	   assert(exprhdlr != NULL);
1258 	   assert(set != NULL);
1259 	   assert(expr != NULL);
1260 	   assert(expr->exprhdlr == exprhdlr);
1261 	   assert(derivative != NULL);
1262 	
1263 	   if( exprhdlr->bwdiff == NULL )
1264 	   {
1265 	      *derivative = SCIP_INVALID;
1266 	      return SCIP_OKAY;
1267 	   }
1268 	
1269 	   if( childrenvals != NULL )
1270 	   {
1271 	      /* temporarily overwrite the evalvalue in all children and expr with values from childrenvals and exprval, resp. */
1272 	      if( expr->nchildren > 0 )
1273 	      {
1274 	         assert(bufmem != NULL);
1275 	         SCIP_ALLOC( BMSallocBufferMemoryArray(bufmem, &origchildrenvals, expr->nchildren) );
1276 	
1277 	         for( c = 0; c < expr->nchildren; ++c )
1278 	         {
1279 	            origchildrenvals[c] = expr->children[c]->evalvalue;
1280 	            expr->children[c]->evalvalue = childrenvals[c];
1281 	         }
1282 	      }
1283 	
1284 	      origexprval = expr->evalvalue;
1285 	      expr->evalvalue = exprval;
1286 	   }
1287 	
1288 	   SCIP_CALL( expr->exprhdlr->bwdiff(set->scip, expr, childidx, derivative) );
1289 	
1290 	   /* if there was some evaluation error (e.g., overflow) that hasn't been caught yet, then do so now */
1291 	   if( !SCIPisFinite(*derivative) )
1292 	      *derivative = SCIP_INVALID;
1293 	
1294 	   /* restore original evalvalues in children */
1295 	   if( childrenvals != NULL )
1296 	   {
1297 	      if( expr->nchildren > 0 )
1298 	      {
1299 	         for( c = 0; c < expr->nchildren; ++c )
1300 	            expr->children[c]->evalvalue = origchildrenvals[c];  /*lint !e644*/
1301 	
1302 	         BMSfreeBufferMemoryArray(bufmem, &origchildrenvals);
1303 	      }
1304 	
1305 	      expr->evalvalue = origexprval;   /*lint !e644*/
1306 	   }
1307 	
1308 	   return SCIP_OKAY;
1309 	}
1310 	
1311 	/** calls the forward differentiation callback of an expression handler
1312 	 *
1313 	 * @see SCIP_DECL_EXPRFWDIFF
1314 	 */
1315 	SCIP_RETCODE SCIPexprhdlrFwDiffExpr(
1316 	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
1317 	   SCIP_SET*             set,                /**< global SCIP settings */
1318 	   SCIP_EXPR*            expr,               /**< expression to be differentiated */
1319 	   SCIP_Real*            dot,                /**< buffer to store derivative value */
1320 	   SCIP_SOL*             direction           /**< direction of the derivative (useful only for var expressions) */
1321 	   )
1322 	{
1323 	   assert(exprhdlr != NULL);
1324 	   assert(set != NULL);
1325 	   assert(expr != NULL);
1326 	   assert(expr->exprhdlr == exprhdlr);
1327 	   assert(dot != NULL);
1328 	
1329 	   if( exprhdlr->fwdiff == NULL )
1330 	   {
1331 	      *dot = SCIP_INVALID;
1332 	      return SCIP_OKAY;
1333 	   }
1334 	
1335 	   SCIP_CALL( exprhdlr->fwdiff(set->scip, expr, dot, direction) );
1336 	
1337 	   /* if there was some evaluation error (e.g., overflow) that hasn't been caught yet, then do so now */
1338 	   if( !SCIPisFinite(*dot) )
1339 	      *dot = SCIP_INVALID;
1340 	
1341 	   return SCIP_OKAY;
1342 	}
1343 	
1344 	/** calls the evaluation and forward-differentiation callback of an expression handler
1345 	 *
1346 	 * The method evaluates an expression by taking the values of its children into account.
1347 	 * The method differentiates an expression by taking the values and directional derivatives of its children into account.
1348 	 *
1349 	 * Further, allows to evaluate and differentiate w.r.t. given values for children instead of those stored in children expressions.
1350 	 *
1351 	 * It probably doesn't make sense to call this function for a variable-expression if sol and/or direction are not given.
1352 	 *
1353 	 * @see SCIP_DECL_EXPREVAL
1354 	 * @see SCIP_DECL_EXPRFWDIFF
1355 	 */
1356 	SCIP_RETCODE SCIPexprhdlrEvalFwDiffExpr(
1357 	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
1358 	   SCIP_SET*             set,                /**< global SCIP settings */
1359 	   BMS_BUFMEM*           bufmem,             /**< buffer memory, can be NULL if childrenvals is NULL */
1360 	   SCIP_EXPR*            expr,               /**< expression to be evaluated */
1361 	   SCIP_Real*            val,                /**< buffer to store value of expression */
1362 	   SCIP_Real*            dot,                /**< buffer to store derivative value */
1363 	   SCIP_Real*            childrenvals,       /**< values for children, or NULL if values stored in children should
1364 	                                                  be used */
1365 	   SCIP_SOL*             sol,                /**< solution that is evaluated (can be NULL) */
1366 	   SCIP_Real*            childrendirs,       /**< directional derivatives for children, or NULL if dot-values stored
1367 	                                                  in children should be used */
1368 	   SCIP_SOL*             direction           /**< direction of the derivative (useful only for var expressions, can
1369 	                                                  be NULL if childrendirs is given) */
1370 	   )
1371 	{
1372 	   SCIP_Real origval;
1373 	   SCIP_Real* origvals = NULL;
1374 	   SCIP_Real* origdots = NULL;
1375 	
1376 	   assert(exprhdlr != NULL);
1377 	   assert(set != NULL);
1378 	   assert(expr != NULL);
1379 	   assert(expr->exprhdlr == exprhdlr);
1380 	   assert(exprhdlr->eval != NULL);
1381 	   assert(val != NULL);
1382 	   assert(dot != NULL);
1383 	
1384 	   /* temporarily overwrite the evalvalue in all children with values from childrenvals */
1385 	   if( childrenvals != NULL && expr->nchildren > 0 )
1386 	   {
1387 	      int c;
1388 	
1389 	      assert(bufmem != NULL);
1390 	
1391 	      SCIP_ALLOC( BMSallocBufferMemoryArray(bufmem, &origvals, expr->nchildren) );
1392 	
1393 	      for( c = 0; c < expr->nchildren; ++c )
1394 	      {
1395 	         origvals[c] = expr->children[c]->evalvalue;
1396 	         expr->children[c]->evalvalue = childrenvals[c];
1397 	      }
1398 	   }
1399 	
1400 	   /* temporarily overwrite the dot in all children with values from childrendirs */
1401 	   if( childrendirs != NULL && expr->nchildren > 0 )
1402 	   {
1403 	      int c;
1404 	
1405 	      assert(bufmem != NULL);
1406 	
1407 	      SCIP_ALLOC( BMSallocBufferMemoryArray(bufmem, &origdots, expr->nchildren) );
1408 	
1409 	      for( c = 0; c < expr->nchildren; ++c )
1410 	      {
1411 	         origdots[c] = expr->children[c]->dot;
1412 	         expr->children[c]->dot = childrendirs[c];
1413 	      }
1414 	   }
1415 	
1416 	   /* remember original value */
1417 	   origval = expr->evalvalue;
1418 	
1419 	   /* call expression eval callback */
1420 	   SCIP_CALL( exprhdlr->eval(set->scip, expr, val, sol) );
1421 	
1422 	   /* if there was some evaluation error (e.g., overflow) that hasn't been caught yet, then do so now */
1423 	   if( !SCIPisFinite(*val) )
1424 	      *val = SCIP_INVALID;
1425 	
1426 	   /* temporarily overwrite evalvalue of expr, since some exprhdlr (e.g., product) access this value in fwdiff */
1427 	   expr->evalvalue = *val;
1428 	
1429 	   /* call forward-differentiation callback (if available) */
1430 	   SCIP_CALL( SCIPexprhdlrFwDiffExpr(exprhdlr, set, expr, dot, direction) );
1431 	
1432 	   /* restore original value */
1433 	   expr->evalvalue = origval;
1434 	
1435 	   /* restore original dots in children */
1436 	   if( origdots != NULL )
1437 	   {
1438 	      int c;
1439 	      for( c = 0; c < expr->nchildren; ++c )
1440 	         expr->children[c]->dot = origdots[c];
1441 	
1442 	      BMSfreeBufferMemoryArray(bufmem, &origdots);
1443 	   }
1444 	
1445 	   /* restore original evalvalues in children */
1446 	   if( origvals != NULL )
1447 	   {
1448 	      int c;
1449 	      for( c = 0; c < expr->nchildren; ++c )
1450 	         expr->children[c]->evalvalue = origvals[c];
1451 	
1452 	      BMSfreeBufferMemoryArray(bufmem, &origvals);
1453 	   }
1454 	
1455 	   return SCIP_OKAY;
1456 	}
1457 	
1458 	/** calls the evaluation callback for Hessian directions (backward over forward) of an expression handler
1459 	 *
1460 	 * @see SCIP_DECL_EXPRBWFWDIFF
1461 	 */
1462 	SCIP_RETCODE SCIPexprhdlrBwFwDiffExpr(
1463 	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
1464 	   SCIP_SET*             set,                /**< global SCIP settings */
1465 	   SCIP_EXPR*            expr,               /**< expression to be differentiated */
1466 	   int                   childidx,           /**< index of the child */
1467 	   SCIP_Real*            bardot,             /**< buffer to store derivative value */
1468 	   SCIP_SOL*             direction           /**< direction of the derivative (useful only for var expressions) */
1469 	   )
1470 	{
1471 	   assert(exprhdlr != NULL);
1472 	   assert(set != NULL);
1473 	   assert(expr != NULL);
1474 	   assert(expr->exprhdlr == exprhdlr);
1475 	   assert(childidx >= 0);
1476 	   assert(childidx < expr->nchildren);
1477 	   assert(bardot != NULL);
1478 	
1479 	   if( exprhdlr->bwfwdiff == NULL )
1480 	   {
1481 	      *bardot = SCIP_INVALID;
1482 	      return SCIP_OKAY;
1483 	   }
1484 	
1485 	   SCIP_CALL( expr->exprhdlr->bwfwdiff(set->scip, expr, childidx, bardot, direction) );
1486 	
1487 	   /* if there was some evaluation error (e.g., overflow) that hasn't been caught yet, then do so now */
1488 	   if( !SCIPisFinite(*bardot) )
1489 	      *bardot = SCIP_INVALID;
1490 	
1491 	   return SCIP_OKAY;
1492 	}
1493 	
1494 	/** calls the interval evaluation callback of an expression handler
1495 	 *
1496 	 * @see SCIP_DECL_EXPRINTEVAL
1497 	 */
1498 	SCIP_RETCODE SCIPexprhdlrIntEvalExpr(
1499 	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
1500 	   SCIP_SET*             set,                /**< global SCIP settings */
1501 	   SCIP_EXPR*            expr,               /**< expression to be evaluated */
1502 	   SCIP_INTERVAL*        interval,           /**< buffer where to store interval */
1503 	   SCIP_DECL_EXPR_INTEVALVAR((*intevalvar)), /**< callback to be called when interval-evaluating a variable */
1504 	   void*                 intevalvardata      /**< data to be passed to intevalvar callback */
1505 	   )
1506 	{
1507 	   assert(exprhdlr != NULL);
1508 	   assert(set != NULL);
1509 	   assert(expr != NULL);
1510 	   assert(expr->exprhdlr == exprhdlr);
1511 	   assert(interval != NULL);
1512 	
1513 	   if( exprhdlr->inteval != NULL )
1514 	   {
1515 	      SCIPclockStart(exprhdlr->intevaltime, set);
1516 	      SCIP_CALL( exprhdlr->inteval(set->scip, expr, interval, intevalvar, intevalvardata) );
1517 	      SCIPclockStop(exprhdlr->intevaltime, set);
1518 	
1519 	      ++exprhdlr->nintevalcalls;
1520 	   }
1521 	
1522 	   return SCIP_OKAY;
1523 	}
1524 	
1525 	/** calls the estimator callback of an expression handler
1526 	 *
1527 	 * @see SCIP_DECL_EXPRESTIMATE
1528 	 */
1529 	SCIP_RETCODE SCIPexprhdlrEstimateExpr(
1530 	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
1531 	   SCIP_SET*             set,                /**< global SCIP settings */
1532 	   SCIP_EXPR*            expr,               /**< expression to be estimated */
1533 	   SCIP_INTERVAL*        localbounds,        /**< current bounds for children */
1534 	   SCIP_INTERVAL*        globalbounds,       /**< global bounds for children */
1535 	   SCIP_Real*            refpoint,           /**< children values for the reference point where to estimate */
1536 	   SCIP_Bool             overestimate,       /**< whether the expression needs to be over- or underestimated */
1537 	   SCIP_Real             targetvalue,        /**< a value that the estimator shall exceed, can be +/-infinity */
1538 	   SCIP_Real*            coefs,              /**< array to store coefficients of estimator */
1539 	   SCIP_Real*            constant,           /**< buffer to store constant part of estimator */
1540 	   SCIP_Bool*            islocal,            /**< buffer to store whether estimator is valid locally only */
1541 	   SCIP_Bool*            success,            /**< buffer to indicate whether an estimator could be computed */
1542 	   SCIP_Bool*            branchcand          /**< array to indicate which children (not) to consider for branching */
1543 	   )
1544 	{
1545 	   assert(exprhdlr != NULL);
1546 	   assert(set != NULL);
1547 	   assert(expr != NULL);
1548 	   assert(expr->exprhdlr == exprhdlr);
1549 	   assert(coefs != NULL);
1550 	   assert(islocal != NULL);
1551 	   assert(success != NULL);
1552 	
1553 	   *success = FALSE;
1554 	
1555 	   if( exprhdlr->estimate != NULL )
1556 	   {
1557 	      SCIPclockStart(exprhdlr->estimatetime, set);
1558 	      SCIP_CALL( exprhdlr->estimate(set->scip, expr, localbounds, globalbounds, refpoint, overestimate, targetvalue,
1559 	            coefs, constant, islocal, success, branchcand) );
1560 	      SCIPclockStop(exprhdlr->estimatetime, set);
1561 	
1562 	      /* update statistics */
1563 	      ++exprhdlr->nestimatecalls;
1564 	   }
1565 	
1566 	   return SCIP_OKAY;
1567 	}
1568 	
1569 	/** calls the intitial estimators callback of an expression handler
1570 	 *
1571 	 * @see SCIP_DECL_EXPRINITESTIMATES
1572 	 */
1573 	SCIP_RETCODE SCIPexprhdlrInitEstimatesExpr(
1574 	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
1575 	   SCIP_SET*             set,                /**< global SCIP settings */
1576 	   SCIP_EXPR*            expr,               /**< expression to be estimated */
1577 	   SCIP_INTERVAL*        bounds,             /**< bounds for children */
1578 	   SCIP_Bool             overestimate,       /**< whether the expression shall be overestimated or underestimated */
1579 	   SCIP_Real*            coefs[SCIP_EXPR_MAXINITESTIMATES], /**< buffer to store coefficients of computed estimators */
1580 	   SCIP_Real             constant[SCIP_EXPR_MAXINITESTIMATES], /**< buffer to store constant of computed estimators */
1581 	   int*                  nreturned           /**< buffer to store number of estimators that have been computed */
1582 	   )
1583 	{
1584 	   assert(exprhdlr != NULL);
1585 	   assert(set != NULL);
1586 	   assert(expr != NULL);
1587 	   assert(expr->exprhdlr == exprhdlr);
1588 	   assert(nreturned != NULL);
1589 	
1590 	   *nreturned = 0;
1591 	
1592 	   if( exprhdlr->initestimates )
1593 	   {
1594 	      SCIPclockStart(expr->exprhdlr->estimatetime, set);
1595 	      SCIP_CALL( exprhdlr->initestimates(set->scip, expr, bounds, overestimate, coefs, constant, nreturned) );
1596 	      SCIPclockStop(expr->exprhdlr->estimatetime, set);
1597 	
1598 	      ++exprhdlr->nestimatecalls;
1599 	   }
1600 	
1601 	   return SCIP_OKAY;
1602 	}
1603 	
1604 	/** calls the simplification callback of an expression handler
1605 	 *
1606 	 * @see SCIP_DECL_EXPRSIMPLIFY
1607 	 */
1608 	SCIP_RETCODE SCIPexprhdlrSimplifyExpr(
1609 	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
1610 	   SCIP_SET*             set,                /**< global SCIP settings */
1611 	   SCIP_EXPR*            expr,               /**< expression to simplify */
1612 	   SCIP_EXPR**           simplifiedexpr,     /**< buffer to store the simplified expression */
1613 	   SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call on expression copy to create ownerdata */
1614 	   void*                 ownercreatedata     /**< data to pass to ownercreate */
1615 	   )
1616 	{
1617 	   assert(exprhdlr != NULL);
1618 	   assert(set != NULL);
1619 	   assert(expr != NULL);
1620 	   assert(expr->exprhdlr == exprhdlr);
1621 	   assert(simplifiedexpr != NULL);
1622 	
1623 	   if( exprhdlr->simplify != NULL )
1624 	   {
1625 	      SCIPclockStart(expr->exprhdlr->simplifytime, set);
1626 	      SCIP_CALL( exprhdlr->simplify(set->scip, expr, simplifiedexpr, ownercreate, ownercreatedata) );
1627 	      SCIPclockStop(expr->exprhdlr->simplifytime, set);
1628 	
1629 	      /* update statistics */
1630 	      ++exprhdlr->nsimplifycalls;
1631 	      if( expr != *simplifiedexpr )
1632 	         ++exprhdlr->nsimplified;
1633 	   }
1634 	   else
1635 	   {
1636 	      *simplifiedexpr = expr;
1637 	
1638 	      /* if an expression handler doesn't implement simplify, we assume that it is already simplified
1639 	       * we have to capture it, since it must simulate a "normal" simplified call in which a new expression is created
1640 	       */
1641 	      SCIPexprCapture(expr);
1642 	   }
1643 	
1644 	   return SCIP_OKAY;
1645 	}
1646 	
1647 	/** calls the reverse propagation callback of an expression handler
1648 	 *
1649 	 * The method propagates given bounds over the children of an expression.
1650 	 *
1651 	 * @see SCIP_DECL_EXPRREVERSEPROP
1652 	 */
1653 	SCIP_RETCODE SCIPexprhdlrReversePropExpr(
1654 	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
1655 	   SCIP_SET*             set,                /**< global SCIP settings */
1656 	   SCIP_EXPR*            expr,               /**< expression to propagate */
1657 	   SCIP_INTERVAL         bounds,             /**< the bounds on the expression that should be propagated */
1658 	   SCIP_INTERVAL*        childrenbounds,     /**< array to store computed bounds for children, initialized with
1659 	                                                  current activity */
1660 	   SCIP_Bool*            infeasible          /**< buffer to store whether a children bounds were propagated to
1661 	                                                  an empty interval */
1662 	   )
1663 	{
1664 	   assert(exprhdlr != NULL);
1665 	   assert(set != NULL);
1666 	   assert(expr != NULL);
1667 	   assert(expr->exprhdlr == exprhdlr);
1668 	   assert(childrenbounds != NULL || expr->nchildren == 0);
1669 	   assert(infeasible != NULL);
1670 	
1671 	   *infeasible = FALSE;
1672 	
1673 	   if( exprhdlr->reverseprop != NULL )
1674 	   {
1675 	      SCIPclockStart(exprhdlr->proptime, set);
1676 	      SCIP_CALL( exprhdlr->reverseprop(set->scip, expr, bounds, childrenbounds, infeasible) );
1677 	      SCIPclockStop(exprhdlr->proptime, set);
1678 	
1679 	      /* update statistics */
1680 	      if( *infeasible )
1681 	         ++expr->exprhdlr->ncutoffs;
1682 	      ++expr->exprhdlr->npropcalls;
1683 	   }
1684 	
1685 	   return SCIP_OKAY;
1686 	}
1687 	
1688 	/**@name Expression Methods */
1689 	/**@{ */
1690 	
1691 	/* from expr.h */
1692 	
1693 	#ifdef NDEBUG
1694 	#undef SCIPexprCapture
1695 	#undef SCIPexprIsVar
1696 	#undef SCIPexprIsValue
1697 	#undef SCIPexprIsSum
1698 	#undef SCIPexprIsProduct
1699 	#undef SCIPexprIsPower
1700 	#endif
1701 	
1702 	/** creates and captures an expression with given expression data and children */
1703 	SCIP_RETCODE SCIPexprCreate(
1704 	   SCIP_SET*             set,                /**< global SCIP settings */
1705 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1706 	   SCIP_EXPR**           expr,               /**< pointer where to store expression */
1707 	   SCIP_EXPRHDLR*        exprhdlr,           /**< expression handler */
1708 	   SCIP_EXPRDATA*        exprdata,           /**< expression data (expression assumes ownership) */
1709 	   int                   nchildren,          /**< number of children */
1710 	   SCIP_EXPR**           children,           /**< children (can be NULL if nchildren is 0) */
1711 	   SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
1712 	   void*                 ownercreatedata     /**< data to pass to ownercreate */
1713 	   )
1714 	{
1715 	   int c;
1716 	
1717 	   assert(set != NULL);
1718 	   assert(blkmem != NULL);
1719 	   assert(expr != NULL);
1720 	   assert(exprhdlr != NULL);
1721 	   assert(children != NULL || nchildren == 0);
1722 	   assert(exprdata == NULL || exprhdlr->copydata != NULL); /* copydata must be available if there is expression data */
1723 	   assert(exprdata == NULL || exprhdlr->freedata != NULL); /* freedata must be available if there is expression data */
1724 	
1725 	   SCIP_ALLOC( BMSallocClearBlockMemory(blkmem, expr) );
1726 	
1727 	   (*expr)->exprhdlr = exprhdlr;
1728 	   (*expr)->exprdata = exprdata;
1729 	   (*expr)->activitytag = -1;  /* to be less than initial domchgcount */
1730 	   (*expr)->curvature = SCIP_EXPRCURV_UNKNOWN;
1731 	
1732 	   /* initialize activity to entire interval */
1733 	   SCIPintervalSetEntire(SCIP_INTERVAL_INFINITY, &(*expr)->activity);
1734 	
1735 	   if( nchildren > 0 )
1736 	   {
1737 	      SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*expr)->children, children, nchildren) );
1738 	      (*expr)->nchildren = nchildren;
1739 	      (*expr)->childrensize = nchildren;
1740 	
1741 	      for( c = 0; c < nchildren; ++c )
1742 	         SCIPexprCapture((*expr)->children[c]);
1743 	   }
1744 	
1745 	   SCIPexprCapture(*expr);
1746 	
1747 	   ++exprhdlr->ncreated;
1748 	
1749 	   /* initializes the ownerdata */
1750 	   if( ownercreate != NULL )
1751 	   {
1752 	      SCIP_CALL( ownercreate(set->scip, *expr, &(*expr)->ownerdata, &(*expr)->ownerfree, &(*expr)->ownerprint,
1753 	            &(*expr)->ownerevalactivity, ownercreatedata) );
1754 	   }
1755 	
1756 	   return SCIP_OKAY;
1757 	}
1758 	
1759 	/** appends child to the children list of expr */
1760 	SCIP_RETCODE SCIPexprAppendChild(
1761 	   SCIP_SET*             set,                /**< global SCIP settings */
1762 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1763 	   SCIP_EXPR*            expr,               /**< expression */
1764 	   SCIP_EXPR*            child               /**< expression to be appended */
1765 	   )
1766 	{
1767 	   assert(set != NULL);
1768 	   assert(blkmem != NULL);
1769 	   assert(child != NULL);
1770 	   assert(expr->nchildren <= expr->childrensize);
1771 	
1772 	   if( expr->nchildren == expr->childrensize )
1773 	   {
1774 	      expr->childrensize = SCIPsetCalcMemGrowSize(set, expr->nchildren+1);
1775 	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &expr->children, expr->nchildren, expr->childrensize) );
1776 	   }
1777 	
1778 	   expr->children[expr->nchildren] = child;
1779 	   ++expr->nchildren;
1780 	
1781 	   /* capture child */
1782 	   SCIPexprCapture(child);
1783 	
1784 	   return SCIP_OKAY;
1785 	}
1786 	
1787 	/** overwrites/replaces a child of an expressions
1788 	 *
1789 	 * @note the old child is released and the newchild is captured, unless they are the same (=same pointer)
1790 	 */
1791 	SCIP_RETCODE SCIPexprReplaceChild(
1792 	   SCIP_SET*             set,                /**< global SCIP settings */
1793 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
1794 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1795 	   SCIP_EXPR*            expr,               /**< expression where a child is going to be replaced */
1796 	   int                   childidx,           /**< index of child being replaced */
1797 	   SCIP_EXPR*            newchild            /**< the new child */
1798 	   )
1799 	{
1800 	   assert(set != NULL);
1801 	   assert(blkmem != NULL);
1802 	   assert(expr != NULL);
1803 	   assert(newchild != NULL);
1804 	   assert(childidx >= 0);
1805 	   assert(childidx < expr->nchildren);
1806 	
1807 	   /* do nothing if child is not changing */
1808 	   if( newchild == expr->children[childidx] )
1809 	      return SCIP_OKAY;
1810 	
1811 	   /* capture new child (do this before releasing the old child in case there are equal */
1812 	   SCIPexprCapture(newchild);
1813 	
1814 	   SCIP_CALL( SCIPexprRelease(set, stat, blkmem, &(expr->children[childidx])) );
1815 	   expr->children[childidx] = newchild;
1816 	
1817 	   return SCIP_OKAY;
1818 	}
1819 	
1820 	/** remove all children of expr */
1821 	SCIP_RETCODE SCIPexprRemoveChildren(
1822 	   SCIP_SET*             set,                /**< global SCIP settings */
1823 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
1824 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1825 	   SCIP_EXPR*            expr                /**< expression */
1826 	   )
1827 	{
1828 	   int c;
1829 	
1830 	   assert(set != NULL);
1831 	   assert(blkmem != NULL);
1832 	   assert(expr != NULL);
1833 	
1834 	   for( c = 0; c < expr->nchildren; ++c )
1835 	   {
1836 	      assert(expr->children[c] != NULL);
1837 	      SCIP_CALL( SCIPexprRelease(set, stat, blkmem, &(expr->children[c])) );
1838 	   }
1839 	
1840 	   expr->nchildren = 0;
1841 	
1842 	   return SCIP_OKAY;
1843 	}
1844 	
1845 	/** copies an expression including subexpressions
1846 	 *
1847 	 * @note If copying fails due to an expression handler not being available in the targetscip, then *targetexpr will be set to NULL.
1848 	 *
1849 	 * For all or some expressions, a mapping to an existing expression can be specified via the mapexpr callback.
1850 	 * The mapped expression (including its children) will not be copied in this case and its ownerdata will not be touched.
1851 	 * If, however, the mapexpr callback returns NULL for the targetexpr, then the expr will be copied in the usual way.
1852 	 */
1853 	SCIP_RETCODE SCIPexprCopy(
1854 	   SCIP_SET*             set,                /**< global SCIP settings */
1855 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
1856 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1857 	   SCIP_SET*             targetset,          /**< global SCIP settings data structure where target expression will live */
1858 	   SCIP_STAT*            targetstat,         /**< dynamic problem statistics in target SCIP */
1859 	   BMS_BLKMEM*           targetblkmem,       /**< block memory in target SCIP */
1860 	   SCIP_EXPR*            sourceexpr,         /**< expression to be copied */
1861 	   SCIP_EXPR**           targetexpr,         /**< buffer to store pointer to copy of source expression */
1862 	   SCIP_DECL_EXPR_MAPEXPR((*mapexpr)),       /**< expression mapping function, or NULL for creating new expressions */
1863 	   void*                 mapexprdata,        /**< data of expression mapping function */
1864 	   SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call on expression copy to create ownerdata */
1865 	   void*                 ownercreatedata     /**< data to pass to ownercreate */
1866 	   )
1867 	{
1868 	   SCIP_EXPRITER* it;
1869 	   SCIP_EXPRITER_USERDATA expriteruserdata;
1870 	   SCIP_EXPR* expr;
1871 	   SCIP* sourcescip = set->scip;        /* SCIP data structure corresponding to source expression */
1872 	   SCIP* targetscip = targetset->scip;  /* SCIP data structure where target expression will live */
1873 	
1874 	   assert(set != NULL);
1875 	   assert(stat != NULL);
1876 	   assert(blkmem != NULL);
1877 	   assert(targetset != NULL);
1878 	   assert(sourceexpr != NULL);
1879 	   assert(targetexpr != NULL);
1880 	   assert(sourcescip != NULL);
1881 	   assert(targetscip != NULL);
1882 	
1883 	   SCIP_CALL( SCIPexpriterCreate(stat, blkmem, &it) );
1884 	   SCIP_CALL( SCIPexpriterInit(it, sourceexpr, SCIP_EXPRITER_DFS, TRUE) );  /*TODO use FALSE, i.e., don't duplicate common subexpr? */
1885 	   SCIPexpriterSetStagesDFS(it, SCIP_EXPRITER_ENTEREXPR | SCIP_EXPRITER_VISITEDCHILD);
1886 	
1887 	   expr = sourceexpr;
1888 	   while( !SCIPexpriterIsEnd(it) )
1889 	   {
1890 	      switch( SCIPexpriterGetStageDFS(it) )
1891 	      {
1892 	         case SCIP_EXPRITER_ENTEREXPR :
1893 	         {
1894 	            /* create expr that will hold the copy */
1895 	            SCIP_EXPRHDLR* targetexprhdlr;
1896 	            SCIP_EXPRDATA* targetexprdata;
1897 	            SCIP_EXPR* exprcopy = NULL;
1898 	
1899 	            if( mapexpr != NULL )
1900 	            {
1901 	               SCIP_CALL( mapexpr(targetscip, &exprcopy, sourcescip, expr, ownercreate, ownercreatedata, mapexprdata) );
1902 	               if( exprcopy != NULL )
1903 	               {
1904 	                  /* map callback gave us an expression to use for the copy */
1905 	                  /* store targetexpr */
1906 	                  expriteruserdata.ptrval = exprcopy;
1907 	                  SCIPexpriterSetCurrentUserData(it, expriteruserdata);
1908 	
1909 	                  /* skip subexpression (assume that exprcopy is a complete copy) and continue */
1910 	                  expr = SCIPexpriterSkipDFS(it);
1911 	                  continue;
1912 	               }
1913 	            }
1914 	
1915 	            /* get the exprhdlr of the target scip */
1916 	            if( targetscip != sourcescip )
1917 	            {
1918 	               targetexprhdlr = SCIPsetFindExprhdlr(targetset, expr->exprhdlr->name);
1919 	
1920 	               if( targetexprhdlr == NULL )
1921 	               {
1922 	                  /* expression handler not in target scip (probably did not have a copy callback) -> abort */
1923 	                  expriteruserdata.ptrval = NULL;
1924 	                  SCIPexpriterSetCurrentUserData(it, expriteruserdata);
1925 	
1926 	                  expr = SCIPexpriterSkipDFS(it);
1927 	                  continue;
1928 	               }
1929 	            }
1930 	            else
1931 	            {
1932 	               targetexprhdlr = expr->exprhdlr;
1933 	            }
1934 	            assert(targetexprhdlr != NULL);
1935 	
1936 	            /* copy expression data */
1937 	            if( expr->exprdata != NULL )
1938 	            {
1939 	               assert(expr->exprhdlr->copydata != NULL);
1940 	               SCIP_CALL( expr->exprhdlr->copydata(targetscip, targetexprhdlr, &targetexprdata, sourcescip, expr) );
1941 	            }
1942 	            else
1943 	            {
1944 	               targetexprdata = NULL;
1945 	            }
1946 	
1947 	            /* create in targetexpr an expression of the same type as expr, but without children for now */
1948 	            SCIP_CALL( SCIPexprCreate(targetset, targetblkmem, &exprcopy, targetexprhdlr, targetexprdata, 0, NULL,
1949 	                  ownercreate, ownercreatedata) );
1950 	
1951 	            /* store targetexpr */
1952 	            expriteruserdata.ptrval = exprcopy;
1953 	            SCIPexpriterSetCurrentUserData(it, expriteruserdata);
1954 	
1955 	            break;
1956 	         }
1957 	
1958 	         case SCIP_EXPRITER_VISITEDCHILD :
1959 	         {
1960 	            /* just visited child so a copy of himself should be available; append it */
1961 	            SCIP_EXPR* exprcopy;
1962 	            SCIP_EXPR* childcopy;
1963 	
1964 	            exprcopy = (SCIP_EXPR*)SCIPexpriterGetCurrentUserData(it).ptrval;
1965 	
1966 	            /* get copy of child */
1967 	            childcopy = (SCIP_EXPR*)SCIPexpriterGetChildUserDataDFS(it).ptrval;
1968 	            if( childcopy == NULL )
1969 	            {
1970 	               /* abort */
1971 	               /* release exprcopy (should free also the already copied children) */
1972 	               SCIP_CALL( SCIPexprRelease(targetset, targetstat, targetblkmem, (SCIP_EXPR**)&exprcopy) );
1973 	
1974 	               expriteruserdata.ptrval = NULL;
1975 	               SCIPexpriterSetCurrentUserData(it, expriteruserdata);
1976 	
1977 	               expr = SCIPexpriterSkipDFS(it);
1978 	               continue;
1979 	            }
1980 	
1981 	            /* append child to exprcopy */
1982 	            SCIP_CALL( SCIPexprAppendChild(targetset, targetblkmem, exprcopy, childcopy) );
1983 	
1984 	            /* release childcopy (still captured by exprcopy) */
1985 	            SCIP_CALL( SCIPexprRelease(targetset, targetstat, targetblkmem, &childcopy) );
1986 	
1987 	            break;
1988 	         }
1989 	
1990 	         default:
1991 	            /* we should never be called in this stage */
1992 	            SCIPABORT();
1993 	            break;
1994 	      }
1995 	
1996 	      expr = SCIPexpriterGetNext(it);
1997 	   }
1998 	
1999 	   /* the target expression should be stored in the userdata of the sourceexpr (can be NULL if aborted) */
2000 	   *targetexpr = (SCIP_EXPR*)SCIPexpriterGetExprUserData(it, sourceexpr).ptrval;
2001 	
2002 	   SCIPexpriterFree(&it);
2003 	
2004 	   return SCIP_OKAY;
2005 	}
2006 	
2007 	/** duplicates the given expression without its children */
2008 	SCIP_RETCODE SCIPexprDuplicateShallow(
2009 	   SCIP_SET*             set,                /**< global SCIP settings */
2010 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2011 	   SCIP_EXPR*            expr,               /**< original expression */
2012 	   SCIP_EXPR**           copyexpr,           /**< buffer to store (shallow) duplicate of expr */
2013 	   SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call on expression copy to create ownerdata */
2014 	   void*                 ownercreatedata     /**< data to pass to ownercreate */
2015 	   )
2016 	{
2017 	   SCIP_EXPRDATA* exprdatacopy = NULL;
2018 	
2019 	   assert(set != NULL);
2020 	   assert(blkmem != NULL);
2021 	   assert(expr != NULL);
2022 	   assert(copyexpr != NULL);
2023 	
2024 	   /* copy expression data */
2025 	   if( expr->exprdata != NULL )
2026 	   {
2027 	      assert(expr->exprhdlr->copydata != NULL);
2028 	      SCIP_CALL( expr->exprhdlr->copydata(set->scip, expr->exprhdlr, &exprdatacopy, set->scip, expr) );
2029 	   }
2030 	
2031 	   /* create expression with same handler and copied data, but without children */
2032 	   SCIP_CALL( SCIPexprCreate(set, blkmem, copyexpr, expr->exprhdlr, exprdatacopy, 0, NULL, ownercreate,
2033 	         ownercreatedata) );
2034 	
2035 	   return SCIP_OKAY;
2036 	}
2037 	
2038 	/** captures an expression (increments usage count) */
2039 	void SCIPexprCapture(
2040 	   SCIP_EXPR*            expr                /**< expression */
2041 	   )
2042 	{
2043 	   assert(expr != NULL);
2044 	
2045 	   ++expr->nuses;
2046 	}
2047 	
2048 	/** releases an expression (decrements usage count and possibly frees expression) */
2049 	SCIP_RETCODE SCIPexprRelease(
2050 	   SCIP_SET*             set,                /**< global SCIP settings */
2051 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
2052 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2053 	   SCIP_EXPR**           rootexpr            /**< pointer to expression */
2054 	   )
2055 	{
2056 	   SCIP_EXPRITER* it;
2057 	   SCIP_EXPR* expr;
2058 	
2059 	   assert(rootexpr != NULL);
2060 	   assert(*rootexpr != NULL);
2061 	   assert((*rootexpr)->nuses > 0);
2062 	
2063 	   if( (*rootexpr)->nuses > 1 )
2064 	   {
2065 	      --(*rootexpr)->nuses;
2066 	      *rootexpr = NULL;
2067 	
2068 	      return SCIP_OKAY;
2069 	   }
2070 	
2071 	   /* handle the root expr separately: free ownerdata, quaddata, and exprdata first */
2072 	
2073 	   /* call ownerfree callback, if given
2074 	    * we intentially call this also if ownerdata is NULL, so owner can be notified without storing data
2075 	    */
2076 	   if( (*rootexpr)->ownerfree != NULL )
2077 	   {
2078 	      SCIP_CALL( (*rootexpr)->ownerfree(set->scip, *rootexpr, &(*rootexpr)->ownerdata) );
2079 	      assert((*rootexpr)->ownerdata == NULL);
2080 	   }
2081 	
2082 	   /* free quadratic info */
2083 	   SCIPexprFreeQuadratic(blkmem, *rootexpr);
2084 	
2085 	   /* free expression data */
2086 	   if( (*rootexpr)->exprdata != NULL )
2087 	   {
2088 	      assert((*rootexpr)->exprhdlr->freedata != NULL);
2089 	      SCIP_CALL( (*rootexpr)->exprhdlr->freedata(set->scip, *rootexpr) );
2090 	   }
2091 	
2092 	   /* now release and free children, where no longer in use */
2093 	   SCIP_CALL( SCIPexpriterCreate(stat, blkmem, &it) );
2094 	   SCIP_CALL( SCIPexpriterInit(it, *rootexpr, SCIP_EXPRITER_DFS, TRUE) );
2095 	   SCIPexpriterSetStagesDFS(it, SCIP_EXPRITER_VISITINGCHILD | SCIP_EXPRITER_VISITEDCHILD);
2096 	   for( expr = SCIPexpriterGetCurrent(it); !SCIPexpriterIsEnd(it) ; )
2097 	   {
2098 	      /* expression should be used by its parent and maybe by the iterator (only the root!)
2099 	       * in VISITEDCHILD we assert that expression is only used by its parent
2100 	       */
2101 	      assert(expr != NULL);
2102 	      assert(0 <= expr->nuses && expr->nuses <= 2);
2103 	
2104 	      switch( SCIPexpriterGetStageDFS(it) )
2105 	      {
2106 	         case SCIP_EXPRITER_VISITINGCHILD :
2107 	         {
2108 	            /* check whether a child needs to be visited (nuses == 1)
2109 	             * if not, then we still have to release it
2110 	             */
2111 	            SCIP_EXPR* child;
2112 	
2113 	            child = SCIPexpriterGetChildExprDFS(it);
2114 	            if( child->nuses > 1 )
2115 	            {
2116 	               /* child is not going to be freed: just release it */
2117 	               SCIP_CALL( SCIPexprRelease(set, stat, blkmem, &child) );
2118 	               expr = SCIPexpriterSkipDFS(it);
2119 	               continue;
2120 	            }
2121 	
2122 	            assert(child->nuses == 1);
2123 	
2124 	            /* free child's quaddata, ownerdata, and exprdata when entering child */
2125 	            if( child->ownerfree != NULL )
2126 	            {
2127 	               SCIP_CALL( child->ownerfree(set->scip, child, &child->ownerdata) );
2128 	               assert(child->ownerdata == NULL);
2129 	            }
2130 	
2131 	            /* free quadratic info */
2132 	            SCIPexprFreeQuadratic(blkmem, child);
2133 	
2134 	            /* free expression data */
2135 	            if( child->exprdata != NULL )
2136 	            {
2137 	               assert(child->exprhdlr->freedata != NULL);
2138 	               SCIP_CALL( child->exprhdlr->freedata(set->scip, child) );
2139 	               assert(child->exprdata == NULL);
2140 	            }
2141 	
2142 	            break;
2143 	         }
2144 	
2145 	         case SCIP_EXPRITER_VISITEDCHILD :
2146 	         {
2147 	            /* free child after visiting it */
2148 	            SCIP_EXPR* child;
2149 	
2150 	            child = SCIPexpriterGetChildExprDFS(it);
2151 	            /* child should only be used by its parent */
2152 	            assert(child->nuses == 1);
2153 	
2154 	            /* child should have no data associated */
2155 	            assert(child->exprdata == NULL);
2156 	
2157 	            /* free child expression */
2158 	            SCIP_CALL( freeExpr(blkmem, &child) );
2159 	            expr->children[SCIPexpriterGetChildIdxDFS(it)] = NULL;
2160 	
2161 	            break;
2162 	         }
2163 	
2164 	         default:
2165 	            SCIPABORT(); /* we should never be called in this stage */
2166 	            break;
2167 	      }
2168 	
2169 	      expr = SCIPexpriterGetNext(it);
2170 	   }
2171 	
2172 	   SCIPexpriterFree(&it);
2173 	
2174 	   /* handle the root expr separately: free its children and itself here */
2175 	   SCIP_CALL( freeExpr(blkmem, rootexpr) );
2176 	
2177 	   return SCIP_OKAY;
2178 	}
2179 	
2180 	/** returns whether an expression is a variable expression */
2181 	SCIP_Bool SCIPexprIsVar(
2182 	   SCIP_SET*             set,                /**< global SCIP settings */
2183 	   SCIP_EXPR*            expr                /**< expression */
2184 	   )
2185 	{
2186 	   assert(set != NULL);
2187 	   assert(expr != NULL);
2188 	
2189 	   return expr->exprhdlr == set->exprhdlrvar;
2190 	}
2191 	
2192 	/** returns whether an expression is a value expression */
2193 	SCIP_Bool SCIPexprIsValue(
2194 	   SCIP_SET*             set,                /**< global SCIP settings */
2195 	   SCIP_EXPR*            expr                /**< expression */
2196 	   )
2197 	{
2198 	   assert(set != NULL);
2199 	   assert(expr != NULL);
2200 	
2201 	   return expr->exprhdlr == set->exprhdlrval;
2202 	}
2203 	
2204 	/** returns whether an expression is a sum expression */
2205 	SCIP_Bool SCIPexprIsSum(
2206 	   SCIP_SET*             set,                /**< global SCIP settings */
2207 	   SCIP_EXPR*            expr                /**< expression */
2208 	   )
2209 	{
2210 	   assert(set != NULL);
2211 	   assert(expr != NULL);
2212 	
2213 	   return expr->exprhdlr == set->exprhdlrsum;
2214 	}
2215 	
2216 	/** returns whether an expression is a product expression */
2217 	SCIP_Bool SCIPexprIsProduct(
2218 	   SCIP_SET*             set,                /**< global SCIP settings */
2219 	   SCIP_EXPR*            expr                /**< expression */
2220 	   )
2221 	{
2222 	   assert(set != NULL);
2223 	   assert(expr != NULL);
2224 	
2225 	   return expr->exprhdlr == set->exprhdlrproduct;
2226 	}
2227 	
2228 	/** returns whether an expression is a power expression */
2229 	SCIP_Bool SCIPexprIsPower(
2230 	   SCIP_SET*             set,                /**< global SCIP settings */
2231 	   SCIP_EXPR*            expr                /**< expression */
2232 	   )
2233 	{
2234 	   assert(set != NULL);
2235 	   assert(expr != NULL);
2236 	
2237 	   return expr->exprhdlr == set->exprhdlrpow;
2238 	}
2239 	
2240 	/** print an expression as info-message */
2241 	SCIP_RETCODE SCIPexprPrint(
2242 	   SCIP_SET*             set,                /**< global SCIP settings */
2243 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
2244 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2245 	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
2246 	   FILE*                 file,               /**< file to print to, or NULL for stdout */
2247 	   SCIP_EXPR*            expr                /**< expression to be printed */
2248 	   )
2249 	{
2250 	   SCIP_EXPRITER* it;
2251 	   SCIP_EXPRITER_STAGE stage;
2252 	   int currentchild;
2253 	   unsigned int parentprecedence;
2254 	
2255 	   assert(set != NULL);
2256 	   assert(blkmem != NULL);
2257 	   assert(expr != NULL);
2258 	
2259 	   SCIP_CALL( SCIPexpriterCreate(stat, blkmem, &it) );
2260 	   SCIP_CALL( SCIPexpriterInit(it, expr, SCIP_EXPRITER_DFS, TRUE) );
2261 	   SCIPexpriterSetStagesDFS(it, SCIP_EXPRITER_ALLSTAGES);
2262 	
2263 	   while( !SCIPexpriterIsEnd(it) )
2264 	   {
2265 	      assert(expr->exprhdlr != NULL);
2266 	      stage = SCIPexpriterGetStageDFS(it);
2267 	
2268 	      if( stage == SCIP_EXPRITER_VISITEDCHILD || stage == SCIP_EXPRITER_VISITINGCHILD )
2269 	         currentchild = SCIPexpriterGetChildIdxDFS(it);
2270 	      else
2271 	         currentchild = -1;
2272 	
2273 	      if( SCIPexpriterGetParentDFS(it) != NULL )
2274 	         parentprecedence = SCIPexprhdlrGetPrecedence(SCIPexprGetHdlr(SCIPexpriterGetParentDFS(it)));
2275 	      else
2276 	         parentprecedence = 0;
2277 	
2278 	      SCIP_CALL( SCIPexprhdlrPrintExpr(expr->exprhdlr, set, messagehdlr, expr, stage, currentchild,
2279 	            parentprecedence, file) );
2280 	
2281 	      expr = SCIPexpriterGetNext(it);
2282 	   }
2283 	
2284 	   SCIPexpriterFree(&it);
2285 	
2286 	   return SCIP_OKAY;
2287 	}
2288 	
2289 	/** initializes printing of expressions in dot format to a give FILE* pointer */
2290 	SCIP_RETCODE SCIPexprPrintDotInit(
2291 	   SCIP_SET*             set,                /**< global SCIP settings */
2292 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
2293 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2294 	   SCIP_EXPRPRINTDATA**  printdata,          /**< buffer to store dot printing data */
(1) Event noescape: "SCIPexprPrintDotInit(SCIP_SET *, SCIP_STAT *, BMS_BLKMEM *, SCIP_EXPRPRINTDATA **, FILE *, SCIP_EXPRPRINT_WHAT)" does not free or save its parameter "file".
2295 	   FILE*                 file,               /**< file to print to, or NULL for stdout */
2296 	   SCIP_EXPRPRINT_WHAT   whattoprint         /**< info on what to print for each expression */
2297 	   )
2298 	{
2299 	   assert(set != NULL);
2300 	   assert(stat != NULL);
2301 	   assert(blkmem != NULL);
2302 	   assert(printdata != NULL);
2303 	
2304 	   if( file == NULL )
2305 	      file = stdout;
2306 	
2307 	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, printdata) );
2308 	
2309 	   (*printdata)->file = file;
2310 	   SCIP_CALL( SCIPexpriterCreate(stat, blkmem, &(*printdata)->iterator) );
2311 	   (*printdata)->closefile = FALSE;
2312 	   (*printdata)->whattoprint = whattoprint;
2313 	   SCIP_CALL( SCIPhashmapCreate(&(*printdata)->leaveexprs, blkmem, 100) );
2314 	
2315 	   fputs("strict digraph exprgraph {\n", file);
2316 	   fputs("node [fontcolor=white, style=filled, rankdir=LR]\n", file);
2317 	
2318 	   return SCIP_OKAY;
2319 	}
2320 	
2321 	/** initializes printing of expressions in dot format to a file with given filename */
2322 	SCIP_RETCODE SCIPexprPrintDotInit2(
2323 	   SCIP_SET*             set,                /**< global SCIP settings */
2324 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
2325 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2326 	   SCIP_EXPRPRINTDATA**  printdata,          /**< buffer to store dot printing data */
2327 	   const char*           filename,           /**< name of file to print to */
2328 	   SCIP_EXPRPRINT_WHAT   whattoprint         /**< info on what to print for each expression */
2329 	   )
2330 	{
2331 	   FILE* f;
2332 	
2333 	   assert(set != NULL);
2334 	   assert(stat != NULL);
2335 	   assert(blkmem != NULL);
2336 	   assert(printdata != NULL);
2337 	   assert(filename != NULL);
2338 	
(1) Event alloc_fn: Storage is returned from allocation function "fopen".
(2) Event var_assign: Assigning: "f" = storage returned from "fopen(filename, "w")".
Also see events: [noescape][leaked_storage]
2339 	   f = fopen(filename, "w");
(3) Event cond_false: Condition "f == NULL", taking false branch.
2340 	   if( f == NULL )
2341 	   {
2342 	      SCIPerrorMessage("could not open file <%s> for writing\n", filename);  /* error code would be in errno */
2343 	      return SCIP_FILECREATEERROR;
(4) Event if_end: End of if statement.
2344 	   }
2345 	
(5) Event noescape: Resource "f" is not freed or pointed-to in "SCIPexprPrintDotInit". [details]
(6) Event cond_true: Condition "(_restat_ = SCIPexprPrintDotInit(set, stat, blkmem, printdata, f, whattoprint)) != SCIP_OKAY", taking true branch.
(7) Event leaked_storage: Variable "f" going out of scope leaks the storage it points to.
Also see events: [alloc_fn][var_assign]
2346 	   SCIP_CALL( SCIPexprPrintDotInit(set, stat, blkmem, printdata, f, whattoprint) );
2347 	   (*printdata)->closefile = TRUE;
2348 	
2349 	   return SCIP_OKAY;
2350 	} /*lint !e429*/
2351 	
2352 	/** main part of printing an expression in dot format */
2353 	SCIP_RETCODE SCIPexprPrintDot(
2354 	   SCIP_SET*             set,                /**< global SCIP settings */
2355 	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
2356 	   SCIP_EXPRPRINTDATA*   printdata,          /**< data as initialized by \ref SCIPprintExprDotInit() */
2357 	   SCIP_EXPR*            expr                /**< expression to be printed */
2358 	   )
2359 	{
2360 	   SCIP_Real color;
2361 	   int c;
2362 	
2363 	   assert(set != NULL);
2364 	   assert(printdata != NULL);
2365 	   assert(expr != NULL);
2366 	   assert(expr->exprhdlr != NULL);
2367 	
2368 	   SCIP_CALL( SCIPexpriterInit(printdata->iterator, expr, SCIP_EXPRITER_DFS, FALSE) );
2369 	
2370 	   while( !SCIPexpriterIsEnd(printdata->iterator) )
2371 	   {
2372 	      /* print expression as dot node */
2373 	
2374 	      if( expr->nchildren == 0 )
2375 	      {
2376 	         SCIP_CALL( SCIPhashmapInsert(printdata->leaveexprs, (void*)expr, NULL) );
2377 	      }
2378 	
2379 	      /* make up some color from the expression type (it's name) */
2380 	      color = 0.0;
2381 	      for( c = 0; expr->exprhdlr->name[c] != '\0'; ++c )
2382 	         color += (tolower(expr->exprhdlr->name[c]) - 'a') / 26.0;
2383 	      color = SCIPsetFrac(set, color);
2384 	      fprintf(printdata->file, "n%p [fillcolor=\"%g,%g,%g\", label=\"", (void*)expr, color, color, color);
2385 	
2386 	      if( printdata->whattoprint & SCIP_EXPRPRINT_EXPRHDLR )
2387 	      {
2388 	         fprintf(printdata->file, "%s\\n", expr->exprhdlr->name);
2389 	      }
2390 	
2391 	      if( printdata->whattoprint & SCIP_EXPRPRINT_EXPRSTRING )
2392 	      {
2393 	         SCIP_CALL( SCIPexprhdlrPrintExpr(expr->exprhdlr, set, messagehdlr, expr, SCIP_EXPRITER_ENTEREXPR, -1, 0,
2394 	               printdata->file) );
2395 	         for( c = 0; c < expr->nchildren; ++c )
2396 	         {
2397 	            SCIP_CALL( SCIPexprhdlrPrintExpr(expr->exprhdlr, set, messagehdlr, expr, SCIP_EXPRITER_VISITINGCHILD,
2398 	                  c, 0, printdata->file) );
2399 	            fprintf(printdata->file, "c%d", c);
2400 	            SCIP_CALL( SCIPexprhdlrPrintExpr(expr->exprhdlr, set, messagehdlr, expr, SCIP_EXPRITER_VISITEDCHILD,
2401 	                  c, 0, printdata->file) );
2402 	         }
2403 	         SCIP_CALL( SCIPexprhdlrPrintExpr(expr->exprhdlr, set, messagehdlr, expr, SCIP_EXPRITER_LEAVEEXPR, -1, 0,
2404 	               printdata->file) );
2405 	
2406 	         fputs("\\n", printdata->file);
2407 	      }
2408 	
2409 	      if( printdata->whattoprint & SCIP_EXPRPRINT_NUSES )
2410 	      {
2411 	         /* print number of uses */
2412 	         fprintf(printdata->file, "%d uses\\n", expr->nuses);
2413 	      }
2414 	
2415 	      if( printdata->whattoprint & SCIP_EXPRPRINT_OWNER )
2416 	      {
2417 	         /* print ownerdata */
2418 	         if( expr->ownerprint != NULL )
2419 	         {
2420 	            SCIP_CALL( expr->ownerprint(set->scip, printdata->file, expr, expr->ownerdata) );
2421 	         }
2422 	         else if( expr->ownerdata != NULL )
2423 	         {
2424 	            fprintf(printdata->file, "owner=%p\\n", (void*)expr->ownerdata);
2425 	         }
2426 	      }
2427 	
2428 	      if( printdata->whattoprint & SCIP_EXPRPRINT_EVALVALUE )
2429 	      {
2430 	         /* print eval value */
2431 	         fprintf(printdata->file, "val=%g", expr->evalvalue);
2432 	
2433 	         if( (printdata->whattoprint & SCIP_EXPRPRINT_EVALTAG) == SCIP_EXPRPRINT_EVALTAG )
2434 	         {
2435 	            /* print also eval tag */
2436 	            fprintf(printdata->file, " (%" SCIP_LONGINT_FORMAT ")", expr->evaltag);
2437 	         }
2438 	         fputs("\\n", printdata->file);
2439 	      }
2440 	
2441 	      if( printdata->whattoprint & SCIP_EXPRPRINT_ACTIVITY )
2442 	      {
2443 	         /* print activity */
2444 	         fprintf(printdata->file, "[%g,%g]", expr->activity.inf, expr->activity.sup);
2445 	
2446 	         if( (printdata->whattoprint & SCIP_EXPRPRINT_ACTIVITYTAG) == SCIP_EXPRPRINT_ACTIVITYTAG )
2447 	         {
2448 	            /* print also activity eval tag */
2449 	            fprintf(printdata->file, " (%" SCIP_LONGINT_FORMAT ")", expr->activitytag);
2450 	         }
2451 	         fputs("\\n", printdata->file);
2452 	      }
2453 	
2454 	      fputs("\"]\n", printdata->file);  /* end of label and end of node */
2455 	
2456 	      /* add edges from expr to its children */
2457 	      for( c = 0; c < expr->nchildren; ++c )
2458 	         fprintf(printdata->file, "n%p -> n%p [label=\"c%d\"]\n", (void*)expr, (void*)expr->children[c], c);
2459 	
2460 	      expr = SCIPexpriterGetNext(printdata->iterator);
2461 	   }
2462 	
2463 	   return SCIP_OKAY;
2464 	}
2465 	
2466 	/** finishes printing of expressions in dot format */
2467 	SCIP_RETCODE SCIPexprPrintDotFinal(
2468 	   SCIP_SET*             set,                /**< global SCIP settings */
2469 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
2470 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2471 	   SCIP_EXPRPRINTDATA**  printdata           /**< buffer where dot printing data has been stored */
2472 	   )
2473 	{
2474 	   SCIP_EXPR* expr;
2475 	   SCIP_HASHMAPENTRY* entry;
2476 	   FILE* file;
2477 	   int i;
2478 	
2479 	   assert(set != NULL);
2480 	   assert(stat != NULL);
2481 	   assert(blkmem != NULL);
2482 	   assert(printdata != NULL);
2483 	   assert(*printdata != NULL);
2484 	
2485 	   file = (*printdata)->file;
2486 	   assert(file != NULL);
2487 	
2488 	   /* iterate through all entries of the map */
2489 	   fputs("{rank=same;", file);
2490 	   for( i = 0; i < SCIPhashmapGetNEntries((*printdata)->leaveexprs); ++i )
2491 	   {
2492 	      entry = SCIPhashmapGetEntry((*printdata)->leaveexprs, i);
2493 	
2494 	      if( entry != NULL )
2495 	      {
2496 	         expr = (SCIP_EXPR*) SCIPhashmapEntryGetOrigin(entry);
2497 	         assert(expr != NULL);
2498 	         assert(expr->nchildren == 0);
2499 	
2500 	         fprintf(file, " n%p", (void*)expr);
2501 	      }
2502 	   }
2503 	   fprintf(file, "}\n");
2504 	
2505 	   fprintf(file, "}\n");
2506 	
2507 	   SCIPhashmapFree(&(*printdata)->leaveexprs);
2508 	
2509 	   SCIPexpriterFree(&(*printdata)->iterator);
2510 	
2511 	   if( (*printdata)->closefile )
2512 	      fclose((*printdata)->file);
2513 	
2514 	   BMSfreeBlockMemory(blkmem, printdata);
2515 	
2516 	   return SCIP_OKAY;
2517 	}
2518 	
2519 	/** prints structure of an expression a la Maple's dismantle */
2520 	SCIP_RETCODE SCIPexprDismantle(
2521 	   SCIP_SET*             set,                /**< global SCIP settings */
2522 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
2523 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2524 	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
2525 	   FILE*                 file,               /**< file to print to, or NULL for stdout */
2526 	   SCIP_EXPR*            expr                /**< expression to dismantle */
2527 	   )
2528 	{
2529 	   SCIP_EXPRITER* it;
2530 	   int depth = -1;
2531 	
2532 	   assert(set != NULL);
2533 	   assert(stat != NULL);
2534 	   assert(blkmem != NULL);
2535 	   assert(messagehdlr != NULL);
2536 	   assert(expr != NULL);
2537 	
2538 	   SCIP_CALL( SCIPexpriterCreate(stat, blkmem, &it) );
2539 	   SCIP_CALL( SCIPexpriterInit(it, expr, SCIP_EXPRITER_DFS, TRUE) );
2540 	   SCIPexpriterSetStagesDFS(it, SCIP_EXPRITER_ENTEREXPR | SCIP_EXPRITER_VISITINGCHILD | SCIP_EXPRITER_LEAVEEXPR);
2541 	
2542 	   for( ; !SCIPexpriterIsEnd(it); expr = SCIPexpriterGetNext(it) )
2543 	   {
2544 	      switch( SCIPexpriterGetStageDFS(it) )
2545 	      {
2546 	         case SCIP_EXPRITER_ENTEREXPR:
2547 	         {
2548 	            int nspaces;
2549 	
2550 	            ++depth;
2551 	            nspaces = 3 * depth;
2552 	
2553 	            /* use depth of expression to align output */
2554 	            SCIPmessageFPrintInfo(messagehdlr, file, "%*s[%s]: ", nspaces, "", expr->exprhdlr->name);
2555 	
2556 	            if( SCIPexprIsVar(set, expr) )
2557 	            {
2558 	               SCIP_VAR* var;
2559 	
2560 	               var = SCIPgetVarExprVar(expr);
2561 	               SCIPmessageFPrintInfo(messagehdlr, file, "%s in [%g, %g]", SCIPvarGetName(var), SCIPvarGetLbLocal(var),
2562 	                  SCIPvarGetUbLocal(var));
2563 	            }
2564 	            else if( SCIPexprIsSum(set, expr) )
2565 	               SCIPmessageFPrintInfo(messagehdlr, file, "%g", SCIPgetConstantExprSum(expr));
2566 	            else if( SCIPexprIsProduct(set, expr) )
2567 	               SCIPmessageFPrintInfo(messagehdlr, file, "%g", SCIPgetCoefExprProduct(expr));
2568 	            else if( SCIPexprIsValue(set, expr) )
2569 	               SCIPmessageFPrintInfo(messagehdlr, file, "%g", SCIPgetValueExprValue(expr));
2570 	            else if( SCIPexprIsPower(set, expr) || strcmp(expr->exprhdlr->name, "signpower") == 0)
2571 	               SCIPmessageFPrintInfo(messagehdlr, file, "%g", SCIPgetExponentExprPow(expr));
2572 	
2573 	            SCIPmessageFPrintInfo(messagehdlr, file, "\n");
2574 	
2575 	            if( expr->ownerprint != NULL )
2576 	            {
2577 	               SCIPmessageFPrintInfo(messagehdlr, file, "%*s   ", nspaces, "");
2578 	               SCIP_CALL( expr->ownerprint(set->scip, file, expr, expr->ownerdata) );
2579 	            }
2580 	
2581 	            break;
2582 	         }
2583 	
2584 	         case SCIP_EXPRITER_VISITINGCHILD:
2585 	         {
2586 	            int nspaces = 3 * depth;
2587 	
2588 	            if( SCIPexprIsSum(set, expr) )
2589 	            {
2590 	               SCIPmessageFPrintInfo(messagehdlr, file, "%*s   ", nspaces, "");
2591 	               SCIPmessageFPrintInfo(messagehdlr, file, "[coef]: %g\n", SCIPgetCoefsExprSum(expr)[SCIPexpriterGetChildIdxDFS(it)]);
2592 	            }
2593 	
2594 	            break;
2595 	         }
2596 	
2597 	         case SCIP_EXPRITER_LEAVEEXPR:
2598 	         {
2599 	            --depth;
2600 	            break;
2601 	         }
2602 	
2603 	         default:
2604 	            /* shouldn't be here */
2605 	            SCIPABORT();
2606 	            break;
2607 	      }
2608 	   }
2609 	
2610 	   SCIPexpriterFree(&it);
2611 	
2612 	   return SCIP_OKAY;
2613 	}
2614 	
2615 	/** evaluate an expression in a point
2616 	 *
2617 	 * Iterates over expressions to also evaluate children, if necessary.
2618 	 * Value can be received via SCIPexprGetEvalValue().
2619 	 * If an evaluation error (division by zero, ...) occurs, this value will
2620 	 * be set to SCIP_INVALID.
2621 	 *
2622 	 * If a nonzero \p soltag is passed, then only (sub)expressions are
2623 	 * reevaluated that have a different solution tag. If a soltag of 0
2624 	 * is passed, then subexpressions are always reevaluated.
2625 	 * The tag is stored together with the value and can be received via
2626 	 * SCIPexprGetEvalTag().
2627 	 */
2628 	SCIP_RETCODE SCIPexprEval(
2629 	   SCIP_SET*             set,                /**< global SCIP settings */
2630 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
2631 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2632 	   SCIP_EXPR*            expr,               /**< expression to be evaluated */
2633 	   SCIP_SOL*             sol,                /**< solution to be evaluated */
2634 	   SCIP_Longint          soltag              /**< tag that uniquely identifies the solution (with its values), or 0. */
2635 	   )
2636 	{
2637 	   SCIP_EXPRITER* it;
2638 	
2639 	   assert(set != NULL);
2640 	   assert(stat != NULL);
2641 	   assert(blkmem != NULL);
2642 	   assert(expr != NULL);
2643 	
2644 	   /* if value is up-to-date, then nothing to do */
2645 	   if( soltag != 0 && expr->evaltag == soltag )
2646 	      return SCIP_OKAY;
2647 	
2648 	   /* assume we'll get a domain error, so we don't have to get this expr back if we abort the iteration
2649 	    * if there is no domain error, then we will overwrite the evalvalue in the last leaveexpr stage
2650 	    */
2651 	   expr->evalvalue = SCIP_INVALID;
2652 	   expr->evaltag = soltag;
2653 	
2654 	   SCIP_CALL( SCIPexpriterCreate(stat, blkmem, &it) );
2655 	   SCIP_CALL( SCIPexpriterInit(it, expr, SCIP_EXPRITER_DFS, TRUE) );
2656 	   SCIPexpriterSetStagesDFS(it, SCIP_EXPRITER_VISITINGCHILD | SCIP_EXPRITER_LEAVEEXPR);
2657 	
2658 	   while( !SCIPexpriterIsEnd(it) )
2659 	   {
2660 	      switch( SCIPexpriterGetStageDFS(it) )
2661 	      {
2662 	         case SCIP_EXPRITER_VISITINGCHILD :
2663 	         {
2664 	            SCIP_EXPR* child;
2665 	
2666 	            if( soltag == 0 )
2667 	               break;
2668 	
2669 	            /* check whether child has been evaluated for that solution already */
2670 	            child = SCIPexpriterGetChildExprDFS(it);
2671 	            if( soltag == child->evaltag )
2672 	            {
2673 	               if( child->evalvalue == SCIP_INVALID )
2674 	                  goto TERMINATE;
2675 	
2676 	               /* skip this child
2677 	                * this already returns the next one, so continue with loop
2678 	                */
2679 	               expr = SCIPexpriterSkipDFS(it);
2680 	               continue;
2681 	            }
2682 	
2683 	            break;
2684 	         }
2685 	
2686 	         case SCIP_EXPRITER_LEAVEEXPR :
2687 	         {
2688 	            SCIP_CALL( SCIPexprhdlrEvalExpr(expr->exprhdlr, set, NULL , expr, &expr->evalvalue, NULL, sol) );
2689 	            expr->evaltag = soltag;
2690 	
2691 	            if( expr->evalvalue == SCIP_INVALID )
2692 	               goto TERMINATE;
2693 	
2694 	            break;
2695 	         }
2696 	
2697 	         default :
2698 	            /* we should never be here */
2699 	            SCIPABORT();
2700 	            break;
2701 	      }
2702 	
2703 	      expr = SCIPexpriterGetNext(it);
2704 	   }
2705 	
2706 	TERMINATE:
2707 	   SCIPexpriterFree(&it);
2708 	
2709 	   return SCIP_OKAY;
2710 	}
2711 	
2712 	/** evaluates gradient of an expression for a given point
2713 	 *
2714 	 * Initiates an expression walk to also evaluate children, if necessary.
2715 	 * Value can be received via SCIPgetExprPartialDiffNonlinear().
2716 	 * If an error (division by zero, ...) occurs, this value will
2717 	 * be set to SCIP_INVALID.
2718 	 */
2719 	SCIP_RETCODE SCIPexprEvalGradient(
2720 	   SCIP_SET*             set,                /**< global SCIP settings */
2721 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
2722 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2723 	   SCIP_EXPR*            rootexpr,           /**< expression to be evaluated */
2724 	   SCIP_SOL*             sol,                /**< solution to be evaluated (NULL for the current LP solution) */
2725 	   SCIP_Longint          soltag              /**< tag that uniquely identifies the solution (with its values), or 0. */
2726 	   )
2727 	{
2728 	   SCIP_EXPRITER* it;
2729 	   SCIP_EXPR* expr;
2730 	   SCIP_EXPR* child;
2731 	   SCIP_Real derivative;
2732 	   SCIP_Longint difftag;
2733 	
2734 	   assert(set != NULL);
2735 	   assert(stat != NULL);
2736 	   assert(blkmem != NULL);
2737 	   assert(rootexpr != NULL);
2738 	
2739 	   /* ensure expression is evaluated */
2740 	   SCIP_CALL( SCIPexprEval(set, stat, blkmem, rootexpr, sol, soltag) );
2741 	
2742 	   /* check if expression could not be evaluated */
2743 	   if( SCIPexprGetEvalValue(rootexpr) == SCIP_INVALID )
2744 	   {
2745 	      rootexpr->derivative = SCIP_INVALID;
2746 	      return SCIP_OKAY;
2747 	   }
2748 	
2749 	   if( SCIPexprIsValue(set, rootexpr) )
2750 	   {
2751 	      rootexpr->derivative = 0.0;
2752 	      return SCIP_OKAY;
2753 	   }
2754 	
2755 	   difftag = ++(stat->exprlastdifftag);
2756 	
2757 	   rootexpr->derivative = 1.0;
2758 	   rootexpr->difftag = difftag;
2759 	
2760 	   SCIP_CALL( SCIPexpriterCreate(stat, blkmem, &it) );
2761 	   SCIP_CALL( SCIPexpriterInit(it, rootexpr, SCIP_EXPRITER_DFS, TRUE) );
2762 	   SCIPexpriterSetStagesDFS(it, SCIP_EXPRITER_VISITINGCHILD);
2763 	
2764 	   for( expr = SCIPexpriterGetCurrent(it); !SCIPexpriterIsEnd(it); expr = SCIPexpriterGetNext(it) )
2765 	   {
2766 	      assert(expr->evalvalue != SCIP_INVALID);
2767 	
2768 	      child = SCIPexpriterGetChildExprDFS(it);
2769 	      assert(child != NULL);
2770 	
2771 	      /* reset the value of the partial derivative w.r.t. a variable expression if we see it for the first time */
2772 	      if( child->difftag != difftag && SCIPexprIsVar(set, child) )
2773 	         child->derivative = 0.0;
2774 	
2775 	      /* update differentiation tag of the child */
2776 	      child->difftag = difftag;
2777 	
2778 	      /* call backward differentiation callback */
2779 	      if( SCIPexprIsValue(set, child) )
2780 	      {
2781 	         derivative = 0.0;
2782 	      }
2783 	      else
2784 	      {
2785 	         derivative = SCIP_INVALID;
2786 	         SCIP_CALL( SCIPexprhdlrBwDiffExpr(expr->exprhdlr, set, NULL, expr, SCIPexpriterGetChildIdxDFS(it),
2787 	               &derivative, NULL, 0.0) );
2788 	
2789 	         if( derivative == SCIP_INVALID )
2790 	         {
2791 	            rootexpr->derivative = SCIP_INVALID;
2792 	            break;
2793 	         }
2794 	      }
2795 	
2796 	      /* update partial derivative stored in the child expression
2797 	       * for a variable, we have to sum up the partial derivatives of the root w.r.t. this variable over all parents
2798 	       * for other intermediate expressions, we only store the partial derivative of the root w.r.t. this expression
2799 	       */
2800 	      if( !SCIPexprIsVar(set, child) )
2801 	         child->derivative = expr->derivative * derivative;
2802 	      else
2803 	         child->derivative += expr->derivative * derivative;
2804 	   }
2805 	
2806 	   SCIPexpriterFree(&it);
2807 	
2808 	   return SCIP_OKAY;
2809 	}
2810 	
2811 	/** evaluates Hessian-vector product of an expression for a given point and direction
2812 	 *
2813 	 * Evaluates children, if necessary.
2814 	 * Value can be received via SCIPgetExprPartialDiffGradientDirNonlinear()
2815 	 * If an error (division by zero, ...) occurs, this value will
2816 	 * be set to SCIP_INVALID.
2817 	 */
2818 	SCIP_RETCODE SCIPexprEvalHessianDir(
2819 	   SCIP_SET*             set,                /**< global SCIP settings */
2820 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
2821 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2822 	   SCIP_EXPR*            rootexpr,           /**< expression to be evaluated */
2823 	   SCIP_SOL*             sol,                /**< solution to be evaluated (NULL for the current LP solution) */
2824 	   SCIP_Longint          soltag,             /**< tag that uniquely identifies the solution (with its values), or 0. */
2825 	   SCIP_SOL*             direction           /**< direction */
2826 	   )
2827 	{
2828 	   SCIP_EXPRITER* it;
2829 	   SCIP_EXPR* expr;
2830 	   SCIP_EXPR* child;
2831 	   SCIP_Real derivative;
2832 	   SCIP_Real hessiandir;
2833 	
2834 	   assert(set != NULL);
2835 	   assert(stat != NULL);
2836 	   assert(blkmem != NULL);
2837 	   assert(rootexpr != NULL);
2838 	
2839 	   if( SCIPexprIsValue(set, rootexpr) )
2840 	   {
2841 	      rootexpr->dot = 0.0;
2842 	      rootexpr->bardot = 0.0;
2843 	      return SCIP_OKAY;
2844 	   }
2845 	
2846 	   /* evaluate expression and directional derivative */
2847 	   SCIP_CALL( evalAndDiff(set, stat, blkmem, rootexpr, sol, soltag, direction) );
2848 	
2849 	   if( rootexpr->evalvalue == SCIP_INVALID )
2850 	   {
2851 	      rootexpr->derivative = SCIP_INVALID;
2852 	      rootexpr->bardot = SCIP_INVALID;
2853 	      return SCIP_OKAY;
2854 	   }
2855 	
2856 	   rootexpr->derivative = 1.0;
2857 	
2858 	   SCIP_CALL( SCIPexpriterCreate(stat, blkmem, &it) );
2859 	   SCIP_CALL( SCIPexpriterInit(it, rootexpr, SCIP_EXPRITER_DFS, TRUE) );
2860 	   SCIPexpriterSetStagesDFS(it, SCIP_EXPRITER_VISITINGCHILD);
2861 	
2862 	   /* compute reverse diff and bardots: i.e. hessian times direction */
2863 	   for( expr = SCIPexpriterGetCurrent(it); !SCIPexpriterIsEnd(it); expr = SCIPexpriterGetNext(it) )
2864 	   {
2865 	      assert(expr->evalvalue != SCIP_INVALID);
2866 	
2867 	      child = SCIPexpriterGetChildExprDFS(it);
2868 	      assert(child != NULL);
2869 	
2870 	      /* call backward and forward-backward differentiation callback */
2871 	      if( SCIPexprIsValue(set, child) )
2872 	      {
2873 	         derivative = 0.0;
2874 	         hessiandir = 0.0;
2875 	      }
2876 	      else
2877 	      {
2878 	         derivative = SCIP_INVALID;
2879 	         hessiandir = SCIP_INVALID;
2880 	         SCIP_CALL( SCIPexprhdlrBwDiffExpr(expr->exprhdlr, set, NULL, expr, SCIPexpriterGetChildIdxDFS(it),
2881 	               &derivative, NULL, SCIP_INVALID) );
2882 	         SCIP_CALL( SCIPexprhdlrBwFwDiffExpr(expr->exprhdlr, set, expr, SCIPexpriterGetChildIdxDFS(it),
2883 	               &hessiandir, NULL) );
2884 	
2885 	         if( derivative == SCIP_INVALID || hessiandir == SCIP_INVALID )
2886 	         {
2887 	            rootexpr->derivative = SCIP_INVALID;
2888 	            rootexpr->bardot = SCIP_INVALID;
2889 	            break;
2890 	         }
2891 	      }
2892 	
2893 	      /* update partial derivative and hessian stored in the child expression
2894 	       * for a variable, we have to sum up the partial derivatives of the root w.r.t. this variable over all parents
2895 	       * for other intermediate expressions, we only store the partial derivative of the root w.r.t. this expression
2896 	       */
2897 	      if( !SCIPexprIsVar(set, child) )
2898 	      {
2899 	         child->derivative = expr->derivative * derivative;
2900 	         child->bardot = expr->bardot * derivative + expr->derivative * hessiandir;
2901 	      }
2902 	      else
2903 	      {
2904 	         child->derivative += expr->derivative * derivative;
2905 	         child->bardot += expr->bardot * derivative + expr->derivative * hessiandir;
2906 	      }
2907 	   }
2908 	
2909 	   SCIPexpriterFree(&it);
2910 	
2911 	   return SCIP_OKAY;
2912 	}
2913 	
2914 	/** possibly reevaluates and then returns the activity of the expression
2915 	 *
2916 	 * Reevaluate activity if currently stored is no longer uptodate.
2917 	 * If the expr owner provided a evalactivity-callback, then call this.
2918 	 * Otherwise, loop over descendants and compare activitytag with stat's domchgcount, i.e.,
2919 	 * whether some bound was changed since last evaluation, to check whether exprhdlrs INTEVAL should be called.
2920 	 *
2921 	 * @note If expression is set to be integral, then activities are tightened to integral values.
2922 	 *   Thus, ensure that the integrality information is valid (if set to TRUE; the default (FALSE) is always ok).
2923 	 */
2924 	SCIP_RETCODE SCIPexprEvalActivity(
2925 	   SCIP_SET*             set,                /**< global SCIP settings */
2926 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
2927 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2928 	   SCIP_EXPR*            rootexpr            /**< expression */
2929 	   )
2930 	{
2931 	   SCIP_EXPRITER* it;
2932 	   SCIP_EXPR* expr;
2933 	
2934 	   assert(set != NULL);
2935 	   assert(stat != NULL);
2936 	   assert(blkmem != NULL);
2937 	   assert(rootexpr != NULL);
2938 	
2939 	   if( rootexpr->ownerevalactivity != NULL )
2940 	   {
2941 	      /* call owner callback for activity-eval */
2942 	      SCIP_CALL( rootexpr->ownerevalactivity(set->scip, rootexpr, rootexpr->ownerdata) );
2943 	
2944 	      return SCIP_OKAY;
2945 	   }
2946 	
2947 	   /* fallback if no callback is given */
2948 	
2949 	   assert(rootexpr->activitytag <= stat->domchgcount);
2950 	
2951 	   /* if value is up-to-date, then nothing to do */
2952 	   if( rootexpr->activitytag == stat->domchgcount )
2953 	   {
2954 	#ifdef DEBUG_PROP
2955 	      SCIPsetDebugMsg(set, "activitytag of root expr equals domchgcount (%u), skip evalactivity\n", stat->domchgcount);
2956 	#endif
2957 	
2958 	      return SCIP_OKAY;
2959 	   }
2960 	
2961 	   SCIP_CALL( SCIPexpriterCreate(stat, blkmem, &it) );
2962 	   SCIP_CALL( SCIPexpriterInit(it, rootexpr, SCIP_EXPRITER_DFS, TRUE) );
2963 	   SCIPexpriterSetStagesDFS(it, SCIP_EXPRITER_VISITINGCHILD | SCIP_EXPRITER_LEAVEEXPR);
2964 	
2965 	   for( expr = SCIPexpriterGetCurrent(it); !SCIPexpriterIsEnd(it);  )
2966 	   {
2967 	      switch( SCIPexpriterGetStageDFS(it) )
2968 	      {
2969 	         case SCIP_EXPRITER_VISITINGCHILD :
2970 	         {
2971 	            /* skip child if it has been evaluated already */
2972 	            SCIP_EXPR* child;
2973 	
2974 	            child = SCIPexpriterGetChildExprDFS(it);
2975 	            if( child->activitytag == stat->domchgcount )
2976 	            {
2977 	               expr = SCIPexpriterSkipDFS(it);
2978 	               continue;
2979 	            }
2980 	
2981 	            break;
2982 	         }
2983 	
2984 	         case SCIP_EXPRITER_LEAVEEXPR :
2985 	         {
2986 	            /* we should not have entered this expression if its activity was already uptodate */
2987 	            assert(expr->activitytag < stat->domchgcount);
2988 	
2989 	            /* reset activity to entire if invalid, so we can use it as starting point below */
2990 	            SCIPintervalSetEntire(SCIP_INTERVAL_INFINITY, &expr->activity);
2991 	
2992 	#ifdef DEBUG_PROP
2993 	            SCIPsetDebugMsg(set, "interval evaluation of expr %p ", (void*)expr);
2994 	            SCIP_CALL( SCIPprintExpr(set->scip, expr, NULL) );
2995 	            SCIPsetDebugMsgPrint(set, "\n");
2996 	#endif
2997 	
2998 	            /* call the inteval callback of the exprhdlr */
2999 	            SCIP_CALL( SCIPexprhdlrIntEvalExpr(expr->exprhdlr, set, expr, &expr->activity, NULL, NULL) );
3000 	#ifdef DEBUG_PROP
3001 	            SCIPsetDebugMsg(set, " exprhdlr <%s>::inteval = [%.20g, %.20g]", expr->exprhdlr->name, expr->activity.inf,
3002 	                  expr->activity.sup);
3003 	#endif
3004 	
3005 	            /* if expression is integral, then we try to tighten the interval bounds a bit
3006 	             * this should undo the addition of some unnecessary safety added by use of nextafter() in interval
3007 	             * arithmetics, e.g., when doing pow() it would be ok to use ceil() and floor(), but for safety we
3008 	             * use SCIPceil and SCIPfloor for now the default intevalVar does not relax variables, so can omit
3009 	             * expressions without children (constants should be ok, too)
3010 	             */
3011 	            if( expr->isintegral && expr->nchildren > 0 )
3012 	            {
3013 	               if( expr->activity.inf > -SCIP_INTERVAL_INFINITY )
3014 	                  expr->activity.inf = SCIPsetCeil(set, expr->activity.inf);
3015 	               if( expr->activity.sup <  SCIP_INTERVAL_INFINITY )
3016 	                  expr->activity.sup = SCIPsetFloor(set, expr->activity.sup);
3017 	#ifdef DEBUG_PROP
3018 	               SCIPsetDebugMsg(set, " applying integrality: [%.20g, %.20g]\n", expr->activity.inf, expr->activity.sup);
3019 	#endif
3020 	            }
3021 	
3022 	            /* mark activity as empty if either the lower/upper bound is above/below +/- SCIPinfinity()
3023 	             * TODO this is a problem if dual-presolve fixed a variable to +/- infinity
3024 	             */
3025 	            if( SCIPsetIsInfinity(set, expr->activity.inf) || SCIPsetIsInfinity(set, -expr->activity.sup) )
3026 	            {
3027 	               SCIPsetDebugMsg(set, "treat activity [%g,%g] as empty as beyond infinity\n", expr->activity.inf, expr->activity.sup);
3028 	               SCIPintervalSetEmpty(&expr->activity);
3029 	            }
3030 	
3031 	            /* remember that activity is uptodate now */
3032 	            expr->activitytag = stat->domchgcount;
3033 	
3034 	            break;
3035 	         }
3036 	
3037 	         default:
3038 	            /* you should never be here */
3039 	            SCIPABORT();
3040 	            break;
3041 	      }
3042 	
3043 	      expr = SCIPexpriterGetNext(it);
3044 	   }
3045 	
3046 	   SCIPexpriterFree(&it);
3047 	
3048 	   return SCIP_OKAY;
3049 	}
3050 	
3051 	/** compare expressions
3052 	 *
3053 	 * @return -1, 0 or 1 if expr1 <, =, > expr2, respectively
3054 	 * @note The given expressions are assumed to be simplified.
3055 	 */
3056 	int SCIPexprCompare(
3057 	   SCIP_SET*             set,                /**< global SCIP settings */
3058 	   SCIP_EXPR*            expr1,              /**< first expression */
3059 	   SCIP_EXPR*            expr2               /**< second expression */
3060 	   )
3061 	{
3062 	   SCIP_EXPRHDLR* exprhdlr1;
3063 	   SCIP_EXPRHDLR* exprhdlr2;
3064 	   int retval;
3065 	
3066 	   exprhdlr1 = expr1->exprhdlr;
3067 	   exprhdlr2 = expr2->exprhdlr;
3068 	
3069 	   /* expressions are of the same kind/type; use compare callback or default method */
3070 	   if( exprhdlr1 == exprhdlr2 )
3071 	      return SCIPexprhdlrCompareExpr(set, expr1, expr2);
3072 	
3073 	   /* expressions are of different kind/type */
3074 	   /* enforces OR6 */
3075 	   if( SCIPexprIsValue(set, expr1) )
3076 	   {
3077 	      return -1;
3078 	   }
3079 	   /* enforces OR12 */
3080 	   if( SCIPexprIsValue(set, expr2) )
3081 	      return -SCIPexprCompare(set, expr2, expr1);
3082 	
3083 	   /* enforces OR7 */
3084 	   if( SCIPexprIsSum(set, expr1) )
3085 	   {
3086 	      int compareresult;
3087 	      int nchildren;
3088 	
3089 	      nchildren = expr1->nchildren;
3090 	      compareresult = SCIPexprCompare(set, expr1->children[nchildren-1], expr2);
3091 	
3092 	      if( compareresult != 0 )
3093 	         return compareresult;
3094 	
3095 	      /* "base" of the largest expression of the sum is equal to expr2, coefficient might tell us that
3096 	       * expr2 is larger */
3097 	      if( SCIPgetCoefsExprSum(expr1)[nchildren-1] < 1.0 )
3098 	         return -1;
3099 	
3100 	      /* largest expression of sum is larger or equal than expr2 => expr1 > expr2 */
3101 	      return 1;
3102 	   }
3103 	   /* enforces OR12 */
3104 	   if( SCIPexprIsSum(set, expr2) )
3105 	      return -SCIPexprCompare(set, expr2, expr1);
3106 	
3107 	   /* enforces OR8 */
3108 	   if( SCIPexprIsProduct(set, expr1) )
3109 	   {
3110 	      int compareresult;
3111 	      int nchildren;
3112 	
3113 	      nchildren = expr1->nchildren;
3114 	      compareresult = SCIPexprCompare(set, expr1->children[nchildren-1], expr2);
3115 	
3116 	      if( compareresult != 0 )
3117 	         return compareresult;
3118 	
3119 	      /* largest expression of product is larger or equal than expr2 => expr1 > expr2 */
3120 	      return 1;
3121 	   }
3122 	   /* enforces OR12 */
3123 	   if( SCIPexprIsProduct(set, expr2) )
3124 	      return -SCIPexprCompare(set, expr2, expr1);
3125 	
3126 	   /* enforces OR9 */
3127 	   if( SCIPexprIsPower(set, expr1) )
3128 	   {
3129 	      int compareresult;
3130 	
3131 	      compareresult = SCIPexprCompare(set, expr1->children[0], expr2);
3132 	
3133 	      if( compareresult != 0 )
3134 	         return compareresult;
3135 	
3136 	      /* base equal to expr2, exponent might tell us that expr2 is larger */
3137 	      if( SCIPgetExponentExprPow(expr1) < 1.0 )
3138 	         return -1;
3139 	
3140 	      /* power expression is larger => expr1 > expr2 */
3141 	      return 1;
3142 	   }
3143 	   /* enforces OR12 */
3144 	   if( SCIPexprIsPower(set, expr2) )
3145 	      return -SCIPexprCompare(set, expr2, expr1);
3146 	
3147 	   /* enforces OR10 */
3148 	   if( SCIPexprIsVar(set, expr1) )
3149 	      return -1;
3150 	   /* enforces OR12 */
3151 	   if( SCIPexprIsVar(set, expr2) )
3152 	      return -SCIPexprCompare(set, expr2, expr1);
3153 	
3154 	   /* enforces OR11 */
3155 	   retval = strcmp(SCIPexprhdlrGetName(exprhdlr1), SCIPexprhdlrGetName(exprhdlr2));
3156 	   return retval == 0 ? 0 : retval < 0 ? -1 : 1;
3157 	}
3158 	
3159 	/** simplifies an expression
3160 	 *
3161 	 * @see SCIPsimplifyExpr
3162 	 */
3163 	SCIP_RETCODE SCIPexprSimplify(
3164 	   SCIP_SET*             set,                /**< global SCIP settings */
3165 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
3166 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3167 	   SCIP_EXPR*            rootexpr,           /**< expression to be simplified */
3168 	   SCIP_EXPR**           simplified,         /**< buffer to store simplified expression */
3169 	   SCIP_Bool*            changed,            /**< buffer to store if rootexpr actually changed */
3170 	   SCIP_Bool*            infeasible,         /**< buffer to store whether infeasibility has been detected */
3171 	   SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
3172 	   void*                 ownercreatedata     /**< data to pass to ownercreate */
3173 	   )
3174 	{
3175 	   SCIP_EXPR* expr;
3176 	   SCIP_EXPRITER* it;
3177 	
3178 	   assert(rootexpr != NULL);
3179 	   assert(simplified != NULL);
3180 	   assert(changed != NULL);
3181 	   assert(infeasible != NULL);
3182 	
3183 	   /* simplify bottom up
3184 	    * when leaving an expression it simplifies it and stores the simplified expr in its iterators expression data
3185 	    * after the child was visited, it is replaced with the simplified expr
3186 	    */
3187 	   SCIP_CALL( SCIPexpriterCreate(stat, blkmem, &it) );
3188 	   SCIP_CALL( SCIPexpriterInit(it, rootexpr, SCIP_EXPRITER_DFS, TRUE) );  /* TODO can we set allowrevisited to FALSE?*/
3189 	   SCIPexpriterSetStagesDFS(it, SCIP_EXPRITER_VISITEDCHILD | SCIP_EXPRITER_LEAVEEXPR);
3190 	
3191 	   *changed = FALSE;
3192 	   *infeasible = FALSE;
3193 	   for( expr = SCIPexpriterGetCurrent(it); !SCIPexpriterIsEnd(it); expr = SCIPexpriterGetNext(it) )
3194 	   {
3195 	      switch( SCIPexpriterGetStageDFS(it) )
3196 	      {
3197 	         case SCIP_EXPRITER_VISITEDCHILD:
3198 	         {
3199 	            SCIP_EXPR* newchild;
3200 	            SCIP_EXPR* child;
3201 	
3202 	            newchild = (SCIP_EXPR*)SCIPexpriterGetChildUserDataDFS(it).ptrval;
3203 	            child = SCIPexpriterGetChildExprDFS(it);
3204 	            assert(newchild != NULL);
3205 	
3206 	            /* if child got simplified, replace it with the new child */
3207 	            if( newchild != child )
3208 	            {
3209 	               SCIP_CALL( SCIPexprReplaceChild(set, stat, blkmem, expr, SCIPexpriterGetChildIdxDFS(it), newchild) );
3210 	            }
3211 	
3212 	            /* we do not need to hold newchild anymore */
3213 	            SCIP_CALL( SCIPexprRelease(set, stat, blkmem, &newchild) );
3214 	
3215 	            break;
3216 	         }
3217 	
3218 	         case SCIP_EXPRITER_LEAVEEXPR:
3219 	         {
3220 	            SCIP_EXPR* refexpr = NULL;
3221 	            SCIP_EXPRITER_USERDATA iterdata;
3222 	
3223 	            /* TODO we should do constant folding (handle that all children are value-expressions) here in a generic way
3224 	             * instead of reimplementing it in every handler
3225 	             */
3226 	
3227 	            /* use simplification of expression handlers */
3228 	            SCIP_CALL( SCIPexprhdlrSimplifyExpr(expr->exprhdlr, set, expr, &refexpr, ownercreate, ownercreatedata) );
3229 	            assert(refexpr != NULL);
3230 	            if( expr != refexpr )
3231 	               *changed = TRUE;
3232 	
3233 	            iterdata.ptrval = (void*) refexpr;
3234 	            SCIPexpriterSetCurrentUserData(it, iterdata);
3235 	
3236 	            break;
3237 	         }
3238 	
3239 	         default:
3240 	            SCIPABORT(); /* we should never be called in this stage */
3241 	            break;
3242 	      }
3243 	   }
3244 	
3245 	   *simplified = (SCIP_EXPR*)SCIPexpriterGetExprUserData(it, rootexpr).ptrval;
3246 	   assert(*simplified != NULL);
3247 	
3248 	   SCIPexpriterFree(&it);
3249 	
3250 	   return SCIP_OKAY;
3251 	}
3252 	
3253 	/** checks whether an expression is quadratic
3254 	 *
3255 	 * An expression is quadratic if it is either a power expression with exponent 2.0, a product of two expressions,
3256 	 * or a sum of terms where at least one is a square or a product of two.
3257 	 *
3258 	 * Use \ref SCIPexprGetQuadraticData to get data about the representation as quadratic.
3259 	 */
3260 	SCIP_RETCODE SCIPexprCheckQuadratic(
3261 	   SCIP_SET*             set,                /**< global SCIP settings */
3262 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3263 	   SCIP_EXPR*            expr,               /**< expression */
3264 	   SCIP_Bool*            isquadratic         /**< buffer to store result */
3265 	   )
3266 	{
3267 	   SCIP_HASHMAP* expr2idx;
3268 	   SCIP_HASHMAP* seenexpr = NULL;
3269 	   int nquadterms = 0;
3270 	   int nlinterms = 0;
3271 	   int nbilinterms = 0;
3272 	   int c;
3273 	
3274 	   assert(set != NULL);
3275 	   assert(blkmem != NULL);
3276 	   assert(expr != NULL);
3277 	   assert(isquadratic != NULL);
3278 	
3279 	   if( expr->quadchecked )
3280 	   {
3281 	      *isquadratic = expr->quaddata != NULL;
3282 	      return SCIP_OKAY;
3283 	   }
3284 	   assert(expr->quaddata == NULL);
3285 	
3286 	   expr->quadchecked = TRUE;
3287 	   *isquadratic = FALSE;
3288 	
3289 	   /* check if expression is a quadratic expression */
3290 	   SCIPsetDebugMsg(set, "checking if expr %p is quadratic\n", (void*)expr);
3291 	
3292 	   /* handle single square term */
3293 	   if( SCIPexprIsPower(set, expr) && SCIPgetExponentExprPow(expr) == 2.0 )
3294 	   {
3295 	      SCIPsetDebugMsg(set, "expr %p looks like square: fill data structures\n", (void*)expr);
3296 	      SCIP_ALLOC( BMSallocClearBlockMemory(blkmem, &expr->quaddata) );
3297 	
3298 	      expr->quaddata->nquadexprs = 1;
3299 	      SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &expr->quaddata->quadexprterms, 1) );
3300 	      expr->quaddata->quadexprterms[0].expr = expr->children[0];
3301 	      expr->quaddata->quadexprterms[0].sqrcoef = 1.0;
3302 	
3303 	      expr->quaddata->allexprsarevars = SCIPexprIsVar(set, expr->quaddata->quadexprterms[0].expr);
3304 	
3305 	      *isquadratic = TRUE;
3306 	      return SCIP_OKAY;
3307 	   }
3308 	
3309 	   /* handle single bilinear term */
3310 	   if( SCIPexprIsProduct(set, expr) && SCIPexprGetNChildren(expr) == 2 )
3311 	   {
3312 	      SCIPsetDebugMsg(set, "expr %p looks like bilinear product: fill data structures\n", (void*)expr);
3313 	      SCIP_ALLOC( BMSallocClearBlockMemory(blkmem, &expr->quaddata) );
3314 	      expr->quaddata->nquadexprs = 2;
3315 	
3316 	      SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &expr->quaddata->quadexprterms, 2) );
3317 	      expr->quaddata->quadexprterms[0].expr = SCIPexprGetChildren(expr)[0];
3318 	      expr->quaddata->quadexprterms[0].nadjbilin = 1;
3319 	      SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &expr->quaddata->quadexprterms[0].adjbilin, 1) );
3320 	      expr->quaddata->quadexprterms[0].adjbilin[0] = 0;
3321 	
3322 	      expr->quaddata->quadexprterms[1].expr = SCIPexprGetChildren(expr)[1];
3323 	      expr->quaddata->quadexprterms[1].nadjbilin = 1;
3324 	      SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &expr->quaddata->quadexprterms[1].adjbilin, 1) );
3325 	      expr->quaddata->quadexprterms[1].adjbilin[0] = 0;
3326 	
3327 	      expr->quaddata->nbilinexprterms = 1;
3328 	      SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &expr->quaddata->bilinexprterms, 1) );
3329 	      expr->quaddata->bilinexprterms[0].expr1 = SCIPexprGetChildren(expr)[1];
3330 	      expr->quaddata->bilinexprterms[0].expr2 = SCIPexprGetChildren(expr)[0];
3331 	      expr->quaddata->bilinexprterms[0].coef = 1.0;
3332 	
3333 	      expr->quaddata->allexprsarevars = SCIPexprIsVar(set, expr->quaddata->quadexprterms[0].expr)
3334 	            && SCIPexprIsVar(set, expr->quaddata->quadexprterms[1].expr);
3335 	
3336 	      *isquadratic = TRUE;
3337 	      return SCIP_OKAY;
3338 	   }
3339 	
3340 	   /* neither a sum, nor a square, nor a bilinear term */
3341 	   if( !SCIPexprIsSum(set, expr) )
3342 	      return SCIP_OKAY;
3343 	
3344 	   SCIP_CALL( SCIPhashmapCreate(&seenexpr, blkmem, 2*SCIPexprGetNChildren(expr)) );
3345 	   for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
3346 	   {
3347 	      SCIP_EXPR* child;
3348 	
3349 	      child = SCIPexprGetChildren(expr)[c];
3350 	      assert(child != NULL);
3351 	
3352 	      if( SCIPexprIsPower(set, child) && SCIPgetExponentExprPow(child) == 2.0 ) /* quadratic term */
3353 	      {
3354 	         SCIP_CALL( quadDetectProcessExpr(SCIPexprGetChildren(child)[0], seenexpr, &nquadterms, &nlinterms) );
3355 	      }
3356 	      else if( SCIPexprIsProduct(set, child) && SCIPexprGetNChildren(child) == 2 ) /* bilinear term */
3357 	      {
3358 	         ++nbilinterms;
3359 	         SCIP_CALL( quadDetectProcessExpr(SCIPexprGetChildren(child)[0], seenexpr, &nquadterms, &nlinterms) );
3360 	         SCIP_CALL( quadDetectProcessExpr(SCIPexprGetChildren(child)[1], seenexpr, &nquadterms, &nlinterms) );
3361 	      }
3362 	      else
3363 	      {
3364 	         /* first time seen linearly --> assign -1; ++nlinterms
3365 	          * not first time --> assign +=1;
3366 	          */
3367 	         if( SCIPhashmapExists(seenexpr, (void*)child) )
3368 	         {
3369 	            assert(SCIPhashmapGetImageInt(seenexpr, (void*)child) > 0);
3370 	
3371 	            SCIP_CALL( SCIPhashmapSetImageInt(seenexpr, (void*)child, SCIPhashmapGetImageInt(seenexpr, (void*)child) + 1) );
3372 	         }
3373 	         else
3374 	         {
3375 	            ++nlinterms;
3376 	            SCIP_CALL( SCIPhashmapInsertInt(seenexpr, (void*)child, -1) );
3377 	         }
3378 	      }
3379 	   }
3380 	
3381 	   if( nquadterms == 0 )
3382 	   {
3383 	      /* only linear sum */
3384 	      SCIPhashmapFree(&seenexpr);
3385 	      return SCIP_OKAY;
3386 	   }
3387 	
3388 	   SCIPsetDebugMsg(set, "expr %p looks quadratic: fill data structures\n", (void*)expr);
3389 	
3390 	   /* expr2idx maps expressions to indices; if index > 0, it is its index in the linexprs array, otherwise -index-1 is
3391 	    * its index in the quadexprterms array
3392 	    */
3393 	   SCIP_CALL( SCIPhashmapCreate(&expr2idx, blkmem, nquadterms + nlinterms) );
3394 	
3395 	   /* allocate memory, etc */
3396 	   SCIP_ALLOC( BMSallocClearBlockMemory(blkmem, &expr->quaddata) );
3397 	   SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &expr->quaddata->quadexprterms, nquadterms) );
3398 	   SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &expr->quaddata->linexprs, nlinterms) );
3399 	   SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &expr->quaddata->lincoefs, nlinterms) );
3400 	   SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &expr->quaddata->bilinexprterms, nbilinterms) );
3401 	
3402 	   expr->quaddata->constant = SCIPgetConstantExprSum(expr);
3403 	
3404 	   expr->quaddata->allexprsarevars = TRUE;
3405 	   /* for every term of the sum-expr */
3406 	   for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
3407 	   {
3408 	      SCIP_EXPR* child;
3409 	      SCIP_Real coef;
3410 	
3411 	      child = SCIPexprGetChildren(expr)[c];
3412 	      coef = SCIPgetCoefsExprSum(expr)[c];
3413 	
3414 	      assert(child != NULL);
3415 	      assert(coef != 0.0);
3416 	
3417 	      if( SCIPexprIsPower(set, child) && SCIPgetExponentExprPow(child) == 2.0 ) /* quadratic term */
3418 	      {
3419 	         SCIP_QUADEXPR_QUADTERM* quadexprterm;
3420 	         assert(SCIPexprGetNChildren(child) == 1);
3421 	
3422 	         child = SCIPexprGetChildren(child)[0];
3423 	         assert(SCIPhashmapGetImageInt(seenexpr, (void *)child) > 0);
3424 	
3425 	         SCIP_CALL( quadDetectGetQuadexprterm(blkmem, child, expr2idx, seenexpr, expr->quaddata, &quadexprterm) );
3426 	         assert(quadexprterm->expr == child);
3427 	         quadexprterm->sqrcoef = coef;
3428 	         quadexprterm->sqrexpr = SCIPexprGetChildren(expr)[c];
3429 	
3430 	         if( expr->quaddata->allexprsarevars )
3431 	            expr->quaddata->allexprsarevars = SCIPexprIsVar(set, quadexprterm->expr);
3432 	      }
3433 	      else if( SCIPexprIsProduct(set, child) && SCIPexprGetNChildren(child) == 2 ) /* bilinear term */
3434 	      {
3435 	         SCIP_QUADEXPR_BILINTERM* bilinexprterm;
3436 	         SCIP_QUADEXPR_QUADTERM* quadexprterm;
3437 	         SCIP_EXPR* expr1;
3438 	         SCIP_EXPR* expr2;
3439 	
3440 	         assert(SCIPgetCoefExprProduct(child) == 1.0);
3441 	
3442 	         expr1 = SCIPexprGetChildren(child)[0];
3443 	         expr2 = SCIPexprGetChildren(child)[1];
3444 	         assert(expr1 != NULL && expr2 != NULL);
3445 	
3446 	         bilinexprterm = &expr->quaddata->bilinexprterms[expr->quaddata->nbilinexprterms];
3447 	
3448 	         bilinexprterm->coef = coef;
3449 	         if( SCIPhashmapGetImageInt(seenexpr, (void*)expr1) >= SCIPhashmapGetImageInt(seenexpr, (void*)expr2) )
3450 	         {
3451 	            bilinexprterm->expr1 = expr1;
3452 	            bilinexprterm->expr2 = expr2;
3453 	         }
3454 	         else
3455 	         {
3456 	            bilinexprterm->expr1 = expr2;
3457 	            bilinexprterm->expr2 = expr1;
3458 	         }
3459 	         bilinexprterm->prodexpr = child;
3460 	
3461 	         SCIP_CALL( quadDetectGetQuadexprterm(blkmem, expr1, expr2idx, seenexpr, expr->quaddata, &quadexprterm) );
3462 	         assert(quadexprterm->expr == expr1);
3463 	         quadexprterm->adjbilin[quadexprterm->nadjbilin] = expr->quaddata->nbilinexprterms;
3464 	         ++quadexprterm->nadjbilin;
3465 	
3466 	         if( expr->quaddata->allexprsarevars )
3467 	            expr->quaddata->allexprsarevars = SCIPexprIsVar(set, quadexprterm->expr);
3468 	
3469 	         SCIP_CALL( quadDetectGetQuadexprterm(blkmem, expr2, expr2idx, seenexpr, expr->quaddata, &quadexprterm) );
3470 	         assert(quadexprterm->expr == expr2);
3471 	         quadexprterm->adjbilin[quadexprterm->nadjbilin] = expr->quaddata->nbilinexprterms;
3472 	         ++quadexprterm->nadjbilin;
3473 	
3474 	         if( expr->quaddata->allexprsarevars )
3475 	            expr->quaddata->allexprsarevars = SCIPexprIsVar(set, quadexprterm->expr);
3476 	
3477 	         ++expr->quaddata->nbilinexprterms;
3478 	
3479 	         /* store position of second factor in quadexprterms */
3480 	         bilinexprterm->pos2 = SCIPhashmapGetImageInt(expr2idx, (void*)bilinexprterm->expr2);
3481 	      }
3482 	      else /* linear term */
3483 	      {
3484 	         if( SCIPhashmapGetImageInt(seenexpr, (void*)child) < 0 )
3485 	         {
3486 	            assert(SCIPhashmapGetImageInt(seenexpr, (void*)child) == -1);
3487 	
3488 	            /* expression only appears linearly */
3489 	            expr->quaddata->linexprs[expr->quaddata->nlinexprs] = child;
3490 	            expr->quaddata->lincoefs[expr->quaddata->nlinexprs] = coef;
3491 	            expr->quaddata->nlinexprs++;
3492 	
3493 	            if( expr->quaddata->allexprsarevars )
3494 	               expr->quaddata->allexprsarevars = SCIPexprIsVar(set, child);
3495 	         }
3496 	         else
3497 	         {
3498 	            /* expression appears non-linearly: set lin coef */
3499 	            SCIP_QUADEXPR_QUADTERM* quadexprterm;
3500 	            assert(SCIPhashmapGetImageInt(seenexpr, (void*)child) > 0);
3501 	
3502 	            SCIP_CALL( quadDetectGetQuadexprterm(blkmem, child, expr2idx, seenexpr, expr->quaddata, &quadexprterm) );
3503 	            assert(quadexprterm->expr == child);
3504 	            quadexprterm->lincoef = coef;
3505 	
3506 	            if( expr->quaddata->allexprsarevars )
3507 	               expr->quaddata->allexprsarevars = SCIPexprIsVar(set, quadexprterm->expr);
3508 	         }
3509 	      }
3510 	   }
3511 	   assert(expr->quaddata->nquadexprs == nquadterms);
3512 	   assert(expr->quaddata->nlinexprs == nlinterms);
3513 	   assert(expr->quaddata->nbilinexprterms == nbilinterms);
3514 	
3515 	   SCIPhashmapFree(&seenexpr);
3516 	   SCIPhashmapFree(&expr2idx);
3517 	
3518 	   *isquadratic = TRUE;
3519 	
3520 	   return SCIP_OKAY;
3521 	}
3522 	
3523 	/** frees information on quadratic representation of an expression
3524 	 *
3525 	 * Reverts SCIPexprCheckQuadratic().
3526 	 * Before doing changes to an expression, it can be useful to call this function.
3527 	 */
3528 	void SCIPexprFreeQuadratic(
3529 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3530 	   SCIP_EXPR*            expr                /**< expression */
3531 	   )
3532 	{
3533 	   int i;
3534 	   int n;
3535 	
3536 	   assert(blkmem != NULL);
3537 	   assert(expr != NULL);
3538 	
3539 	   expr->quadchecked = FALSE;
3540 	
3541 	   if( expr->quaddata == NULL )
3542 	      return;
3543 	
3544 	   n = expr->quaddata->nquadexprs;
3545 	
3546 	   BMSfreeBlockMemoryArrayNull(blkmem, &expr->quaddata->linexprs, expr->quaddata->nlinexprs);
3547 	   BMSfreeBlockMemoryArrayNull(blkmem, &expr->quaddata->lincoefs, expr->quaddata->nlinexprs);
3548 	   BMSfreeBlockMemoryArrayNull(blkmem, &expr->quaddata->bilinexprterms, expr->quaddata->nbilinexprterms);
3549 	   BMSfreeBlockMemoryArrayNull(blkmem, &expr->quaddata->eigenvalues, n);
3550 	   BMSfreeBlockMemoryArrayNull(blkmem, &expr->quaddata->eigenvectors, n * n);  /*lint !e647*/
3551 	
3552 	   for( i = 0; i < n; ++i )
3553 	   {
3554 	      BMSfreeBlockMemoryArrayNull(blkmem, &expr->quaddata->quadexprterms[i].adjbilin,
3555 	         expr->quaddata->quadexprterms[i].adjbilinsize);
3556 	   }
3557 	   BMSfreeBlockMemoryArrayNull(blkmem, &expr->quaddata->quadexprterms, n);
3558 	
3559 	   BMSfreeBlockMemory(blkmem, &expr->quaddata);
3560 	}
3561 	
3562 	/** Checks the curvature of the quadratic function stored in quaddata
3563 	 *
3564 	 * For this, it builds the matrix Q of quadratic coefficients and computes its eigenvalues using LAPACK.
3565 	 * If Q is
3566 	 * - semidefinite positive -> curv is set to convex,
3567 	 * - semidefinite negative -> curv is set to concave,
3568 	 * - otherwise -> curv is set to unknown.
3569 	 *
3570 	 * If `assumevarfixed` is given and some expressions in quadratic terms correspond to variables present in
3571 	 * this hashmap, then the corresponding rows and columns are ignored in the matrix Q.
3572 	 */
3573 	SCIP_RETCODE SCIPexprComputeQuadraticCurvature(
3574 	   SCIP_SET*             set,                /**< global SCIP settings */
3575 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3576 	   BMS_BUFMEM*           bufmem,             /**< buffer memory */
3577 	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
3578 	   SCIP_EXPR*            expr,               /**< quadratic expression */
3579 	   SCIP_EXPRCURV*        curv,               /**< pointer to store the curvature of quadratics */
3580 	   SCIP_HASHMAP*         assumevarfixed,     /**< hashmap containing variables that should be assumed to be fixed, or NULL */
3581 	   SCIP_Bool             storeeigeninfo      /**< whether the eigenvalues and eigenvectors should be stored */
3582 	   )
3583 	{
3584 	   SCIP_QUADEXPR* quaddata;
3585 	   SCIP_HASHMAP* expr2matrix;
3586 	   double* matrix;
3587 	   double* alleigval;
3588 	   int nvars;
3589 	   int nn;
3590 	   int n;
3591 	   int i;
3592 	
3593 	   assert(set != NULL);
3594 	   assert(blkmem != NULL);
3595 	   assert(bufmem != NULL);
3596 	   assert(messagehdlr != NULL);
3597 	   assert(expr != NULL);
3598 	   assert(curv != NULL);
3599 	
3600 	   quaddata = expr->quaddata;
3601 	   assert(quaddata != NULL);
3602 	
3603 	   /* do not store eigen information if we are not considering full matrix */
3604 	   if( assumevarfixed != NULL )
3605 	      storeeigeninfo = FALSE;
3606 	
3607 	   if( quaddata->eigeninfostored || (quaddata->curvaturechecked && !storeeigeninfo) )
3608 	   {
3609 	      *curv = quaddata->curvature;
3610 	      /* if we are convex or concave on the full set of variables, then we will also be so on a subset */
3611 	      if( assumevarfixed == NULL || quaddata->curvature != SCIP_EXPRCURV_UNKNOWN )
3612 	         return SCIP_OKAY;
3613 	   }
3614 	   assert(quaddata->curvature == SCIP_EXPRCURV_UNKNOWN || assumevarfixed != NULL
3615 	         || (storeeigeninfo && !quaddata->eigeninfostored));
3616 	
3617 	   *curv = SCIP_EXPRCURV_UNKNOWN;
3618 	
3619 	   n  = quaddata->nquadexprs;
3620 	
3621 	   /* do not check curvature if nn will be too large
3622 	    * we want nn * sizeof(real) to fit into an unsigned int, so n must be <= sqrt(unit_max/sizeof(real))
3623 	    * sqrt(2*214748364/8) = 7327.1475350234
3624 	    */
3625 	   if( n > 7000 )
3626 	   {
3627 	      SCIPmessageFPrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, NULL,
3628 	            "number of quadratic variables is too large (%d) to check the curvature\n", n);
3629 	      return SCIP_OKAY;
3630 	   }
3631 	
3632 	   /* TODO do some simple tests first; like diagonal entries don't change sign, etc */
3633 	
3634 	   if( !SCIPisIpoptAvailableIpopt() )
3635 	      return SCIP_OKAY;
3636 	
3637 	   nn = n * n;
3638 	   assert(nn > 0);
3639 	   assert((unsigned)nn < UINT_MAX / sizeof(SCIP_Real));
3640 	
3641 	   if( storeeigeninfo )
3642 	   {
3643 	      SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &quaddata->eigenvalues, n));
3644 	      SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &quaddata->eigenvectors, nn));
3645 	
3646 	      alleigval = quaddata->eigenvalues;
3647 	      matrix = quaddata->eigenvectors;
3648 	   }
3649 	   else
3650 	   {
3651 	      SCIP_ALLOC( BMSallocBufferMemoryArray(bufmem, &alleigval, n) );
3652 	      SCIP_ALLOC( BMSallocClearBufferMemoryArray(bufmem, &matrix, nn) );
3653 	   }
3654 	
3655 	   SCIP_CALL( SCIPhashmapCreate(&expr2matrix, blkmem, n) );
3656 	
3657 	   /* fill matrix's diagonal */
3658 	   nvars = 0;
3659 	   for( i = 0; i < n; ++i )
3660 	   {
3661 	      SCIP_QUADEXPR_QUADTERM quadexprterm;
3662 	
3663 	      quadexprterm = quaddata->quadexprterms[i];
3664 	
3665 	      assert(!SCIPhashmapExists(expr2matrix, (void*)quadexprterm.expr));
3666 	
3667 	      /* skip expr if it is a variable mentioned in assumevarfixed */
3668 	      if( assumevarfixed != NULL && SCIPexprIsVar(set, quadexprterm.expr)
3669 	          && SCIPhashmapExists(assumevarfixed, (void*)SCIPgetVarExprVar(quadexprterm.expr)) )
3670 	         continue;
3671 	
3672 	      if( quadexprterm.sqrcoef == 0.0 && ! storeeigeninfo )
3673 	      {
3674 	         assert(quadexprterm.nadjbilin > 0);
3675 	         /* SCIPdebugMsg(scip, "var <%s> appears in bilinear term but is not squared
3676 	          * --> indefinite quadratic\n", SCIPvarGetName(quadexprterm.var)); */
3677 	         goto CLEANUP;
3678 	      }
3679 	
3680 	      matrix[nvars * n + nvars] = quadexprterm.sqrcoef;
3681 	
3682 	      /* remember row of variable in matrix */
3683 	      SCIP_CALL( SCIPhashmapInsert(expr2matrix, (void *)quadexprterm.expr, (void *)(size_t)nvars) );
3684 	      nvars++;
3685 	   }
3686 	
3687 	   /* fill matrix's upper-diagonal */
3688 	   for( i = 0; i < quaddata->nbilinexprterms; ++i )
3689 	   {
3690 	      SCIP_QUADEXPR_BILINTERM bilinexprterm;
3691 	      int col;
3692 	      int row;
3693 	
3694 	      bilinexprterm = quaddata->bilinexprterms[i];
3695 	
3696 	      /* each factor should have been added to expr2matrix unless it corresponds to a variable mentioned in assumevarfixed */
3697 	      assert(SCIPhashmapExists(expr2matrix, (void*)bilinexprterm.expr1)
3698 	            || (assumevarfixed != NULL && SCIPexprIsVar(set, bilinexprterm.expr1)
3699 	            && SCIPhashmapExists(assumevarfixed, (void*)SCIPgetVarExprVar(bilinexprterm.expr1))));
3700 	      assert(SCIPhashmapExists(expr2matrix, (void*)bilinexprterm.expr2)
3701 	            || (assumevarfixed != NULL && SCIPexprIsVar(set, bilinexprterm.expr2)
3702 	            && SCIPhashmapExists(assumevarfixed, (void*)SCIPgetVarExprVar(bilinexprterm.expr2))));
3703 	
3704 	      /* skip bilinear terms where at least one of the factors should be assumed to be fixed
3705 	       * (i.e., not present in expr2matrix map) */
3706 	      if( !SCIPhashmapExists(expr2matrix, (void*)bilinexprterm.expr1)
3707 	          || !SCIPhashmapExists(expr2matrix, (void*)bilinexprterm.expr2) )
3708 	         continue;
3709 	
3710 	      row = (int)(size_t)SCIPhashmapGetImage(expr2matrix, bilinexprterm.expr1);
3711 	      col = (int)(size_t)SCIPhashmapGetImage(expr2matrix, bilinexprterm.expr2);
3712 	
3713 	      assert(row != col);
3714 	
3715 	      if( row < col )
3716 	         matrix[row * n + col] = bilinexprterm.coef / 2.0;
3717 	      else
3718 	         matrix[col * n + row] = bilinexprterm.coef / 2.0;
3719 	   }
3720 	
3721 	   /* compute eigenvalues */
3722 	   if( SCIPcallLapackDsyevIpopt(storeeigeninfo, n, matrix, alleigval) != SCIP_OKAY )
3723 	   {
3724 	      SCIPmessagePrintWarning(messagehdlr, "Failed to compute eigenvalues of quadratic coefficient "
3725 	            "matrix --> don't know curvature\n");
3726 	      goto CLEANUP;
3727 	   }
3728 	
3729 	   /* check convexity */
3730 	   if( !SCIPsetIsNegative(set, alleigval[0]) )
3731 	      *curv = SCIP_EXPRCURV_CONVEX;
3732 	   else if( !SCIPsetIsPositive(set, alleigval[n-1]) )
3733 	      *curv = SCIP_EXPRCURV_CONCAVE;
3734 	
3735 	CLEANUP:
3736 	   SCIPhashmapFree(&expr2matrix);
3737 	
3738 	   if( !storeeigeninfo )
3739 	   {
3740 	      BMSfreeBufferMemoryArray(bufmem, &matrix);
3741 	      BMSfreeBufferMemoryArray(bufmem, &alleigval);
3742 	   }
3743 	   else
3744 	   {
3745 	      assert(!quaddata->eigeninfostored);
3746 	      quaddata->eigeninfostored = TRUE;
3747 	   }
3748 	
3749 	   /* if checked convexity on full Q matrix, then remember it
3750 	    * if indefinite on submatrix, then it will also be indefinite on full matrix, so can remember that, too */
3751 	   if( assumevarfixed == NULL || *curv == SCIP_EXPRCURV_UNKNOWN )
3752 	   {
3753 	      quaddata->curvature = *curv;
3754 	      quaddata->curvaturechecked = TRUE;
3755 	   }
3756 	
3757 	   return SCIP_OKAY;
3758 	}
3759 	
3760 	
3761 	/* from pub_expr.h */
3762 	
3763 	#ifdef NDEBUG
3764 	#undef SCIPexprGetNUses
3765 	#undef SCIPexprGetNChildren
3766 	#undef SCIPexprGetChildren
3767 	#undef SCIPexprGetHdlr
3768 	#undef SCIPexprGetData
3769 	#undef SCIPexprSetData
3770 	#undef SCIPexprGetOwnerData
3771 	#undef SCIPexprGetEvalValue
3772 	#undef SCIPexprGetEvalTag
3773 	#undef SCIPexprGetDerivative
3774 	#undef SCIPexprGetDot
3775 	#undef SCIPexprGetBardot
3776 	#undef SCIPexprGetDiffTag
3777 	#undef SCIPexprGetActivity
3778 	#undef SCIPexprGetActivityTag
3779 	#undef SCIPexprSetActivity
3780 	#undef SCIPexprGetCurvature
3781 	#undef SCIPexprSetCurvature
3782 	#undef SCIPexprIsIntegral
3783 	#undef SCIPexprSetIntegrality
3784 	#undef SCIPexprAreQuadraticExprsVariables
3785 	#endif
3786 	
3787 	/** gets the number of times the expression is currently captured */
3788 	int SCIPexprGetNUses(
3789 	   SCIP_EXPR*            expr                /**< expression */
3790 	   )
3791 	{
3792 	   assert(expr != NULL);
3793 	
3794 	   return expr->nuses;
3795 	}
3796 	
3797 	/** gives the number of children of an expression */
3798 	int SCIPexprGetNChildren(
3799 	   SCIP_EXPR*            expr                /**< expression */
3800 	   )
3801 	{
3802 	   assert(expr != NULL);
3803 	
3804 	   return expr->nchildren;
3805 	}
3806 	
3807 	/** gives the children of an expression (can be NULL if no children) */
3808 	SCIP_EXPR** SCIPexprGetChildren(
3809 	   SCIP_EXPR*            expr                /**< expression */
3810 	   )
3811 	{
3812 	   assert(expr != NULL);
3813 	
3814 	   return expr->children;
3815 	}
3816 	
3817 	/** gets the expression handler of an expression
3818 	 *
3819 	 * This identifies the type of the expression (sum, variable, ...).
3820 	 */
3821 	SCIP_EXPRHDLR* SCIPexprGetHdlr(
3822 	   SCIP_EXPR*            expr                /**< expression */
3823 	   )
3824 	{
3825 	   assert(expr != NULL);
3826 	
3827 	   return expr->exprhdlr;
3828 	}
3829 	
3830 	/** gets the expression data of an expression */
3831 	SCIP_EXPRDATA* SCIPexprGetData(
3832 	   SCIP_EXPR*            expr                /**< expression */
3833 	   )
3834 	{
3835 	   assert(expr != NULL);
3836 	
3837 	   return expr->exprdata;
3838 	}
3839 	
3840 	/** sets the expression data of an expression
3841 	 *
3842 	 * The pointer to possible old data is overwritten and the
3843 	 * freedata-callback is not called before.
3844 	 * This function is intended to be used by expression handler only.
3845 	 */
3846 	void SCIPexprSetData(
3847 	   SCIP_EXPR*            expr,               /**< expression */
3848 	   SCIP_EXPRDATA*        exprdata            /**< expression data to be set (can be NULL) */
3849 	   )
3850 	{
3851 	   assert(expr != NULL);
3852 	   assert(exprdata == NULL || expr->exprhdlr->copydata != NULL);  /* copydata must be available if there is expression data */
3853 	   assert(exprdata == NULL || expr->exprhdlr->freedata != NULL);  /* freedata must be available if there is expression data */
3854 	
3855 	   expr->exprdata = exprdata;
3856 	}
3857 	
3858 	/** gets the data that the owner of an expression has stored in an expression */
3859 	SCIP_EXPR_OWNERDATA* SCIPexprGetOwnerData(
3860 	   SCIP_EXPR*            expr                /**< expression */
3861 	   )
3862 	{
3863 	   assert(expr != NULL);
3864 	
3865 	   return expr->ownerdata;
3866 	}
3867 	
3868 	/** gives the value from the last evaluation of an expression (or SCIP_INVALID if there was an eval error)
3869 	 *
3870 	 * @see SCIPevalExpr to evaluate the expression at a given solution.
3871 	 */
3872 	SCIP_Real SCIPexprGetEvalValue(
3873 	   SCIP_EXPR*            expr                /**< expression */
3874 	   )
3875 	{
3876 	   assert(expr != NULL);
3877 	
3878 	   return expr->evalvalue;
3879 	}
3880 	
3881 	/** gives the evaluation tag from the last evaluation, or 0
3882 	 *
3883 	 * @see SCIPevalExpr
3884 	 */
3885 	SCIP_Longint SCIPexprGetEvalTag(
3886 	   SCIP_EXPR*            expr                /**< expression */
3887 	   )
3888 	{
3889 	   assert(expr != NULL);
3890 	
3891 	   return expr->evaltag;
3892 	}
3893 	
3894 	/** returns the derivative stored in an expression (or SCIP_INVALID if there was an evaluation error)
3895 	 *
3896 	 * @see SCIPevalExprGradient
3897 	 */
3898 	SCIP_Real SCIPexprGetDerivative(
3899 	   SCIP_EXPR*            expr                /**< expression */
3900 	   )
3901 	{
3902 	   assert(expr != NULL);
3903 	
3904 	   return expr->derivative;
3905 	}
3906 	
3907 	/** gives the value of directional derivative from the last evaluation of a directional derivative of
3908 	 * expression (or SCIP_INVALID if there was an error)
3909 	 *
3910 	 * @see SCIPevalExprHessianDir
3911 	 */
3912 	SCIP_Real SCIPexprGetDot(
3913 	   SCIP_EXPR*            expr                /**< expression */
3914 	   )
3915 	{
3916 	   assert(expr != NULL);
3917 	
3918 	   return expr->dot;
3919 	}
3920 	
3921 	/** gives the value of directional derivative from the last evaluation of a directional derivative of
3922 	 * derivative of root (or SCIP_INVALID if there was an error)
3923 	 *
3924 	 * @see SCIPevalExprHessianDir
3925 	 */
3926 	SCIP_Real SCIPexprGetBardot(
3927 	   SCIP_EXPR*            expr                /**< expression */
3928 	   )
3929 	{
3930 	   assert(expr != NULL);
3931 	
3932 	   return expr->bardot;
3933 	}
3934 	
3935 	/** returns the difftag stored in an expression
3936 	 *
3937 	 * can be used to check whether partial derivative value is valid
3938 	 *
3939 	 * @see SCIPevalExprGradient
3940 	 */
3941 	SCIP_Longint SCIPexprGetDiffTag(
3942 	   SCIP_EXPR*            expr                /**< expression */
3943 	   )
3944 	{
3945 	   assert(expr != NULL);
3946 	
3947 	   return expr->difftag;
3948 	}
3949 	
3950 	/** returns the activity that is currently stored for an expression
3951 	 *
3952 	 * @see SCIPevalExprActivity
3953 	 */
3954 	SCIP_INTERVAL SCIPexprGetActivity(
3955 	   SCIP_EXPR*            expr                /**< expression */
3956 	   )
3957 	{
3958 	   assert(expr != NULL);
3959 	
3960 	   return expr->activity;
3961 	}
3962 	
3963 	/** returns the tag associated with the activity of the expression
3964 	 *
3965 	 * It can depend on the owner of the expression how to interpret this tag.
3966 	 * SCIPevalExprActivity() compares with `stat->domchgcount`.
3967 	 *
3968 	 * @see SCIPevalExprActivity
3969 	 */
3970 	SCIP_Longint SCIPexprGetActivityTag(
3971 	   SCIP_EXPR*            expr                /**< expression */
3972 	   )
3973 	{
3974 	   assert(expr != NULL);
3975 	
3976 	   return expr->activitytag;
3977 	}
3978 	
3979 	/** set the activity with tag for an expression */
3980 	void SCIPexprSetActivity(
3981 	   SCIP_EXPR*            expr,               /**< expression */
3982 	   SCIP_INTERVAL         activity,           /**< new activity */
3983 	   SCIP_Longint          activitytag         /**< tag associated with activity */
3984 	   )
3985 	{
3986 	   assert(expr != NULL);
3987 	
3988 	   expr->activity = activity;
3989 	   expr->activitytag = activitytag;
3990 	}
3991 	
3992 	/** returns the curvature of an expression
3993 	 *
3994 	 *  @note Call SCIPcomputeExprCurvature() before calling this function.
3995 	 */
3996 	SCIP_EXPRCURV SCIPexprGetCurvature(
3997 	   SCIP_EXPR*            expr                /**< expression */
3998 	   )
3999 	{
4000 	   assert(expr != NULL);
4001 	
4002 	   return expr->curvature;
4003 	}
4004 	
4005 	/** sets the curvature of an expression */
4006 	void SCIPexprSetCurvature(
4007 	   SCIP_EXPR*            expr,               /**< expression */
4008 	   SCIP_EXPRCURV         curvature           /**< curvature of the expression */
4009 	   )
4010 	{
4011 	   assert(expr != NULL);
4012 	
4013 	   expr->curvature = curvature;
4014 	}
4015 	
4016 	/** returns whether an expression is integral */
4017 	SCIP_Bool SCIPexprIsIntegral(
4018 	   SCIP_EXPR*            expr                /**< expression */
4019 	   )
4020 	{
4021 	   assert(expr != NULL);
4022 	
4023 	   return expr->isintegral;
4024 	}
4025 	
4026 	/** sets the integrality flag of an expression */
4027 	void SCIPexprSetIntegrality(
4028 	   SCIP_EXPR*            expr,               /**< expression */
4029 	   SCIP_Bool             isintegral          /**< integrality of the expression */
4030 	   )
4031 	{
4032 	   assert(expr != NULL);
4033 	
4034 	   expr->isintegral = isintegral;
4035 	}
4036 	
4037 	/** gives the coefficients and expressions that define a quadratic expression
4038 	 *
4039 	 * It can return the constant part, the number, arguments, and coefficients of the purely linear part
4040 	 * and the number of quadratic terms and bilinear terms.
4041 	 * Note that for arguments that appear in the quadratic part, a linear coefficient is
4042 	 * stored with the quadratic term.
4043 	 * Use SCIPexprGetQuadraticQuadTerm() and SCIPexprGetQuadraticBilinTerm()
4044 	 * to access the data for a quadratic or bilinear term.
4045 	 *
4046 	 * It can also return the eigenvalues and the eigenvectors of the matrix \f$Q\f$ when the quadratic is written
4047 	 * as \f$x^T Q x + b^T x + c^T y + d\f$, where \f$c^T y\f$ defines the purely linear part.
4048 	 * Note, however, that to have access to them one needs to call SCIPcomputeExprQuadraticCurvature()
4049 	 * with `storeeigeninfo=TRUE`. If the eigen information was not stored or it failed to be computed,
4050 	 * `eigenvalues` and `eigenvectors` will be set to NULL.
4051 	 *
4052 	 * This function returns pointers to internal data in linexprs and lincoefs.
4053 	 * The user must not change this data.
4054 	 *
4055 	 * @attention SCIPcheckExprQuadratic() needs to be called first to check whether expression is quadratic and initialize the data of the quadratic representation.
4056 	 */
4057 	void SCIPexprGetQuadraticData(
4058 	   SCIP_EXPR*            expr,               /**< quadratic expression */
4059 	   SCIP_Real*            constant,           /**< buffer to store constant term, or NULL */
4060 	   int*                  nlinexprs,          /**< buffer to store number of expressions that appear linearly, or NULL */
4061 	   SCIP_EXPR***          linexprs,           /**< buffer to store pointer to array of expressions that appear linearly,
4062 	                                                  or NULL */
4063 	   SCIP_Real**           lincoefs,           /**< buffer to store pointer to array of coefficients of expressions that
4064 	                                                  appear linearly, or NULL */
4065 	   int*                  nquadexprs,         /**< buffer to store number of expressions in quadratic terms, or NULL */
4066 	   int*                  nbilinexprs,        /**< buffer to store number of bilinear expressions terms, or NULL */
4067 	   SCIP_Real**           eigenvalues,        /**< buffer to store pointer to array of eigenvalues of Q, or NULL */
4068 	   SCIP_Real**           eigenvectors        /**< buffer to store pointer to array of eigenvectors of Q, or NULL */
4069 	   )
4070 	{
4071 	   SCIP_QUADEXPR* quaddata;
4072 	
4073 	   assert(expr != NULL);
4074 	
4075 	   quaddata = expr->quaddata;
4076 	   assert(quaddata != NULL);
4077 	
4078 	   if( constant != NULL )
4079 	      *constant = quaddata->constant;
4080 	   if( nlinexprs != NULL )
4081 	      *nlinexprs = quaddata->nlinexprs;
4082 	   if( linexprs != NULL )
4083 	      *linexprs = quaddata->linexprs;
4084 	   if( lincoefs != NULL )
4085 	      *lincoefs = quaddata->lincoefs;
4086 	   if( nquadexprs != NULL )
4087 	      *nquadexprs = quaddata->nquadexprs;
4088 	   if( nbilinexprs != NULL )
4089 	      *nbilinexprs = quaddata->nbilinexprterms;
4090 	   if( eigenvalues != NULL )
4091 	      *eigenvalues = quaddata->eigenvalues;
4092 	   if( eigenvectors != NULL )
4093 	      *eigenvectors = quaddata->eigenvectors;
4094 	}
4095 	
4096 	/** gives the data of a quadratic expression term
4097 	 *
4098 	 * For a term \f$a \cdot \text{expr}^2 + b \cdot \text{expr} + \sum_i (c_i \cdot \text{expr} \cdot \text{otherexpr}_i)\f$, returns
4099 	 * `expr`, \f$a\f$, \f$b\f$, the number of summands, and indices of bilinear terms in the quadratic expressions `bilinexprterms`.
4100 	 *
4101 	 * This function returns pointers to internal data in adjbilin.
4102 	 * The user must not change this data.
4103 	 */
4104 	void SCIPexprGetQuadraticQuadTerm(
4105 	   SCIP_EXPR*            quadexpr,           /**< quadratic expression */
4106 	   int                   termidx,            /**< index of quadratic term */
4107 	   SCIP_EXPR**           expr,               /**< buffer to store pointer to argument expression (the 'x') of this term,
4108 	                                                  or NULL */
4109 	   SCIP_Real*            lincoef,            /**< buffer to store linear coefficient of variable, or NULL */
4110 	   SCIP_Real*            sqrcoef,            /**< buffer to store square coefficient of variable, or NULL */
4111 	   int*                  nadjbilin,          /**< buffer to store number of bilinear terms this variable is involved in,
4112 	                                                  or NULL */
4113 	   int**                 adjbilin,           /**< buffer to store pointer to indices of associated bilinear terms, or NULL */
4114 	   SCIP_EXPR**           sqrexpr             /**< buffer to store pointer to square expression (the 'x^2') of this term
4115 	                                                  or NULL if no square expression, or NULL */
4116 	   )
4117 	{
4118 	   SCIP_QUADEXPR_QUADTERM* quadexprterm;
4119 	
4120 	   assert(quadexpr != NULL);
4121 	   assert(quadexpr->quaddata != NULL);
4122 	   assert(quadexpr->quaddata->quadexprterms != NULL);
4123 	   assert(termidx >= 0);
4124 	   assert(termidx < quadexpr->quaddata->nquadexprs);
4125 	
4126 	   quadexprterm = &quadexpr->quaddata->quadexprterms[termidx];
4127 	
4128 	   if( expr != NULL )
4129 	      *expr = quadexprterm->expr;
4130 	   if( lincoef != NULL )
4131 	      *lincoef = quadexprterm->lincoef;
4132 	   if( sqrcoef != NULL )
4133 	      *sqrcoef = quadexprterm->sqrcoef;
4134 	   if( nadjbilin != NULL )
4135 	      *nadjbilin = quadexprterm->nadjbilin;
4136 	   if( adjbilin != NULL )
4137 	      *adjbilin = quadexprterm->adjbilin;
4138 	   if( sqrexpr != NULL )
4139 	      *sqrexpr = quadexprterm->sqrexpr;
4140 	}
4141 	
4142 	/** gives the data of a bilinear expression term
4143 	 *
4144 	 * For a term a*expr1*expr2, returns expr1, expr2, a, and
4145 	 * the position of the quadratic expression term that uses expr2 in the quadratic expressions `quadexprterms`.
4146 	 */
4147 	void SCIPexprGetQuadraticBilinTerm(
4148 	   SCIP_EXPR*            expr,               /**< quadratic expression */
4149 	   int                   termidx,            /**< index of bilinear term */
4150 	   SCIP_EXPR**           expr1,              /**< buffer to store first factor, or NULL */
4151 	   SCIP_EXPR**           expr2,              /**< buffer to store second factor, or NULL */
4152 	   SCIP_Real*            coef,               /**< buffer to coefficient, or NULL */
4153 	   int*                  pos2,               /**< buffer to position of expr2 in quadexprterms array of quadratic
4154 	                                                  expression, or NULL */
4155 	   SCIP_EXPR**           prodexpr            /**< buffer to store pointer to expression that is product if first
4156 	                                                  and second factor, or NULL */
4157 	   )
4158 	{
4159 	   SCIP_QUADEXPR_BILINTERM* bilinexprterm;
4160 	
4161 	   assert(expr != NULL);
4162 	   assert(expr->quaddata != NULL);
4163 	   assert(expr->quaddata->bilinexprterms != NULL);
4164 	   assert(termidx >= 0);
4165 	   assert(termidx < expr->quaddata->nbilinexprterms);
4166 	
4167 	   bilinexprterm = &expr->quaddata->bilinexprterms[termidx];
4168 	
4169 	   if( expr1 != NULL )
4170 	      *expr1 = bilinexprterm->expr1;
4171 	   if( expr2 != NULL )
4172 	      *expr2 = bilinexprterm->expr2;
4173 	   if( coef != NULL )
4174 	      *coef = bilinexprterm->coef;
4175 	   if( pos2 != NULL )
4176 	      *pos2 = bilinexprterm->pos2;
4177 	   if( prodexpr != NULL )
4178 	      *prodexpr = bilinexprterm->prodexpr;
4179 	}
4180 	
4181 	/** returns whether all expressions that are used in a quadratic expression are variable expressions
4182 	 *
4183 	 * @return TRUE iff all `linexprs` and `quadexprterms[.].expr` are variable expressions
4184 	 */
4185 	SCIP_Bool SCIPexprAreQuadraticExprsVariables(
4186 	   SCIP_EXPR*            expr                /**< quadratic expression */
4187 	   )
4188 	{
4189 	   assert(expr != NULL);
4190 	   assert(expr->quaddata != NULL);
4191 	
4192 	   return expr->quaddata->allexprsarevars;
4193 	}
4194 	
4195 	/**@} */
4196