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