1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This file is part of the program and library             */
4    	/*         SCIP --- Solving Constraint Integer Programs                      */
5    	/*                                                                           */
6    	/*    Copyright (C) 2002-2022 Konrad-Zuse-Zentrum                            */
7    	/*                            fuer Informationstechnik Berlin                */
8    	/*                                                                           */
9    	/*  SCIP is distributed under the terms of the ZIB Academic License.         */
10   	/*                                                                           */
11   	/*  You should have received a copy of the ZIB Academic License              */
12   	/*  along with SCIP; see the file COPYING. If not visit scipopt.org.         */
13   	/*                                                                           */
14   	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15   	
16   	/**@file   var.c
17   	 * @ingroup OTHER_CFILES
18   	 * @brief  methods for problem variables
19   	 * @author Tobias Achterberg
20   	 * @author Timo Berthold
21   	 * @author Gerald Gamrath
22   	 * @author Stefan Heinz
23   	 * @author Marc Pfetsch
24   	 * @author Michael Winkler
25   	 * @author Kati Wolter
26   	 * @author Stefan Vigerske
27   	 *
28   	 * @todo Possibly implement the access of bounds of multi-aggregated variables by accessing the
29   	 * corresponding linear constraint if it exists. This seems to require some work, since the linear
30   	 * constraint has to be stored. Moreover, it has even to be created in case the original constraint
31   	 * was deleted after multi-aggregation, but the bounds of the multi-aggregated variable should be
32   	 * changed. This has to be done with care in order to not loose the performance gains of
33   	 * multi-aggregation.
34   	 */
35   	
36   	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
37   	
38   	#include "scip/cons.h"
39   	#include "scip/event.h"
40   	#include "scip/history.h"
41   	#include "scip/implics.h"
42   	#include "scip/lp.h"
43   	#include "scip/primal.h"
44   	#include "scip/prob.h"
45   	#include "scip/pub_cons.h"
46   	#include "scip/pub_history.h"
47   	#include "scip/pub_implics.h"
48   	#include "scip/pub_lp.h"
49   	#include "scip/pub_message.h"
50   	#include "scip/pub_misc.h"
51   	#include "scip/pub_misc_sort.h"
52   	#include "scip/pub_prop.h"
53   	#include "scip/pub_var.h"
54   	#include "scip/relax.h"
55   	#include "scip/set.h"
56   	#include "scip/sol.h"
57   	#include "scip/stat.h"
58   	#include "scip/struct_event.h"
59   	#include "scip/struct_lp.h"
60   	#include "scip/struct_prob.h"
61   	#include "scip/struct_set.h"
62   	#include "scip/struct_stat.h"
63   	#include "scip/struct_var.h"
64   	#include "scip/tree.h"
65   	#include "scip/var.h"
66   	#include <string.h>
67   	
68   	#define MAXIMPLSCLOSURE 100  /**< maximal number of descendants of implied variable for building closure
69   	                              *   in implication graph */
70   	#define MAXABSVBCOEF    1e+5 /**< maximal absolute coefficient in variable bounds added due to implications */
71   	
72   	
73   	/*
74   	 * Debugging variable release and capture
75   	 *
76   	 * Define DEBUGUSES_VARNAME to the name of the variable for which to print
77   	 * a backtrace when it is captured and released.
78   	 * Optionally define DEBUGUSES_PROBNAME to the name of a SCIP problem to consider.
79   	 * Have DEBUGUSES_NOADDR2LINE defined if you do not have addr2line installed on your system.
80   	 */
81   	/* #define DEBUGUSES_VARNAME "t_t_b7" */
82   	/* #define DEBUGUSES_PROBNAME "t_st_e35_rens" */
83   	/* #define DEBUGUSES_NOADDR2LINE */
84   	
85   	#ifdef DEBUGUSES_VARNAME
86   	#include <execinfo.h>
87   	#include <stdio.h>
88   	#include <stdlib.h>
89   	#include "scip/struct_scip.h"
90   	
91   	/** obtains a backtrace and prints it to stdout. */
92   	static
93   	void print_backtrace(void)
94   	{
95   	   void* array[10];
96   	   char** strings;
97   	   int size;
98   	   int i;
99   	
100  	   size = backtrace(array, 10);
101  	   strings = backtrace_symbols(array, size);
102  	   if( strings == NULL )
103  	      return;
104  	
105  	   /* skip first entry, which is the print_backtrace function */
106  	   for( i = 1; i < size; ++i )
107  	   {
108  	      /* if string is something like
109  	       *  /path/to/scip/bin/../lib/shared/libscip-7.0.1.3.linux.x86_64.gnu.dbg.so(+0x2675dd3)
110  	       * (that is, no function name because it is a inlined function), then call
111  	       * addr2line -e <libname> <addr> to get func and code line
112  	       * dladdr() may be an alternative
113  	       */
114  	      char* openpar;
115  	      char* closepar = NULL;
116  	#ifndef DEBUGUSES_NOADDR2LINE
117  	      openpar = strchr(strings[i], '(');
118  	      if( openpar != NULL && openpar[1] == '+' )
119  	         closepar = strchr(openpar+2, ')');
120  	#endif
121  	      if( closepar != NULL )
122  	      {
123  	         char cmd[SCIP_MAXSTRLEN];
124  	         (void) SCIPsnprintf(cmd, SCIP_MAXSTRLEN, "addr2line -f -p -e \"%.*s\" %.*s", openpar - strings[i], strings[i], closepar-openpar-1, openpar+1);
125  	         printf("  ");
126  	         fflush(stdout);
127  	         system(cmd);
128  	      }
129  	      else
130  	         printf("  %s\n", strings[i]);
131  	    }
132  	
133  	  free(strings);
134  	}
135  	#endif
136  	
137  	/*
138  	 * hole, holelist, and domain methods
139  	 */
140  	
141  	/** creates a new holelist element */
142  	static
143  	SCIP_RETCODE holelistCreate(
144  	   SCIP_HOLELIST**       holelist,           /**< pointer to holelist to create */
145  	   BMS_BLKMEM*           blkmem,             /**< block memory for target holelist */
146  	   SCIP_SET*             set,                /**< global SCIP settings */
147  	   SCIP_Real             left,               /**< left bound of open interval in new hole */
148  	   SCIP_Real             right               /**< right bound of open interval in new hole */
149  	   )
150  	{
151  	   assert(holelist != NULL);
152  	   assert(blkmem != NULL);
153  	   assert(SCIPsetIsLT(set, left, right));
154  	
155  	   SCIPsetDebugMsg(set, "create hole list element (%.15g,%.15g) in blkmem %p\n", left, right, (void*)blkmem);
156  	
157  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, holelist) );
158  	   (*holelist)->hole.left = left;
159  	   (*holelist)->hole.right = right;
160  	   (*holelist)->next = NULL;
161  	
162  	   return SCIP_OKAY;
163  	}
164  	
165  	/** frees all elements in the holelist */
166  	static
167  	void holelistFree(
168  	   SCIP_HOLELIST**       holelist,           /**< pointer to holelist to free */
169  	   BMS_BLKMEM*           blkmem              /**< block memory for target holelist */
170  	   )
171  	{
172  	   assert(holelist != NULL);
173  	   assert(blkmem != NULL);
174  	
175  	   while( *holelist != NULL )
176  	   {
177  	      SCIP_HOLELIST* next;
178  	
179  	      SCIPdebugMessage("free hole list element (%.15g,%.15g) in blkmem %p\n", 
180  	         (*holelist)->hole.left, (*holelist)->hole.right, (void*)blkmem);
181  	
182  	      next = (*holelist)->next;
183  	      BMSfreeBlockMemory(blkmem, holelist);
184  	      assert(*holelist == NULL);
185  	
186  	      *holelist = next;
187  	   }
188  	   assert(*holelist == NULL);
189  	}
190  	
191  	/** duplicates a list of holes */
192  	static
193  	SCIP_RETCODE holelistDuplicate(
194  	   SCIP_HOLELIST**       target,             /**< pointer to target holelist */
195  	   BMS_BLKMEM*           blkmem,             /**< block memory for target holelist */
196  	   SCIP_SET*             set,                /**< global SCIP settings */
197  	   SCIP_HOLELIST*        source              /**< holelist to duplicate */
198  	   )
199  	{
200  	   assert(target != NULL);
201  	
202  	   while( source != NULL )
203  	   {
204  	      assert(source->next == NULL || SCIPsetIsGE(set, source->next->hole.left, source->hole.right));
205  	      SCIP_CALL( holelistCreate(target, blkmem, set, source->hole.left, source->hole.right) );
206  	      source = source->next;
207  	      target = &(*target)->next;
208  	   }
209  	
210  	   return SCIP_OKAY;
211  	}
212  	
213  	/** adds a hole to the domain */
214  	static
215  	SCIP_RETCODE domAddHole(
216  	   SCIP_DOM*             dom,                /**< domain to add hole to */
217  	   BMS_BLKMEM*           blkmem,             /**< block memory */
218  	   SCIP_SET*             set,                /**< global SCIP settings */
219  	   SCIP_Real             left,               /**< left bound of open interval in new hole */
220  	   SCIP_Real             right,              /**< right bound of open interval in new hole */
221  	   SCIP_Bool*            added               /**< pointer to store whether the hole was added (variable didn't had that hole before), or NULL */
222  	   )
223  	{
224  	   SCIP_HOLELIST** insertpos;
225  	   SCIP_HOLELIST* next;
226  	
227  	   assert(dom != NULL);
228  	   assert(added != NULL);
229  	
230  	   /* search for the position of the new hole */
231  	   insertpos = &dom->holelist;
232  	   while( *insertpos != NULL && (*insertpos)->hole.left < left )
233  	      insertpos = &(*insertpos)->next;
234  	
235  	   /* check if new hole already exists in the hole list or is a sub hole of an existing one */
236  	   if( *insertpos != NULL && (*insertpos)->hole.left == left && (*insertpos)->hole.right >= right )  /*lint !e777 */
237  	   {
238  	      SCIPsetDebugMsg(set, "new hole (%.15g,%.15g) is redundant through known hole (%.15g,%.15g)\n",
239  	         left, right, (*insertpos)->hole.left, (*insertpos)->hole.right);
240  	      *added = FALSE;
241  	      return SCIP_OKAY;
242  	   }
243  	
244  	   /* add hole */
245  	   *added = TRUE;
246  	
247  	   next = *insertpos;
248  	   SCIP_CALL( holelistCreate(insertpos, blkmem, set, left, right) );
249  	   (*insertpos)->next = next;
250  	
251  	   return SCIP_OKAY;
252  	}
253  	
254  	/** merges overlapping holes into single holes, computes and moves lower and upper bound, respectively */
255  	/**@todo  the domMerge() method is currently called if a lower or an upper bound locally or globally changed; this could
256  	 *        be more efficient if performed with the knowledge if it was a lower or an upper bound which triggered this
257  	 *        merge */
258  	static
259  	void domMerge(
260  	   SCIP_DOM*             dom,                /**< domain to merge */
261  	   BMS_BLKMEM*           blkmem,             /**< block memory */
262  	   SCIP_SET*             set,                /**< global SCIP settings */
263  	   SCIP_Real*            newlb,              /**< pointer to store new lower bound */
264  	   SCIP_Real*            newub               /**< pointer to store new upper bound */
265  	   )
266  	{
267  	   SCIP_HOLELIST** holelistptr;
268  	   SCIP_HOLELIST** lastnextptr;
269  	   SCIP_Real* lastrightptr;
270  	
271  	   assert(dom != NULL);
272  	   assert(SCIPsetIsLE(set, dom->lb, dom->ub));
273  	
274  	#ifndef NDEBUG
275  	   {
276  	      /* check if the holelist is sorted w.r.t. to the left interval bounds */
277  	      SCIP_Real lastleft;
278  	
279  	      holelistptr = &dom->holelist;
280  	
281  	      lastleft = -SCIPsetInfinity(set);
282  	
283  	      while( *holelistptr != NULL )
284  	      {
285  	         if( (*holelistptr)->next != NULL )
286  	         {
287  	            assert( SCIPsetIsLE(set, lastleft, (*holelistptr)->hole.left) );
288  	            lastleft = (*holelistptr)->hole.left;
289  	         }
290  	
291  	         holelistptr = &(*holelistptr)->next;
292  	      }   
293  	   }
294  	#endif
295  	
296  	   SCIPsetDebugMsg(set, "merge hole list\n");
297  	
298  	   holelistptr = &dom->holelist;
299  	   lastrightptr = &dom->lb;  /* lower bound is the right bound of the hole (-infinity,lb) */
300  	   lastnextptr = holelistptr;
301  	
302  	   while( *holelistptr != NULL )
303  	   {
304  	      SCIPsetDebugMsg(set, "check hole (%.15g,%.15g) last right interval was <%.15g>\n", (*holelistptr)->hole.left, (*holelistptr)->hole.right, *lastrightptr);
305  	
306  	      /* check that the hole is not empty */
307  	      assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right));
308  	
309  	      if( SCIPsetIsGE(set, (*holelistptr)->hole.left, dom->ub) )
310  	      {
311  	         /* the remaining holes start behind the upper bound: remove them */
312  	         SCIPsetDebugMsg(set, "remove remaining hole since upper bound <%.15g> is less then the left hand side of the current hole\n", dom->ub);
313  	         holelistFree(holelistptr, blkmem);
314  	         assert(*holelistptr == NULL);
315  	
316  	         /* unlink this hole from the previous hole */
317  	         *lastnextptr = NULL;
318  	      }
319  	      else if( SCIPsetIsGT(set, (*holelistptr)->hole.right, dom->ub) )
320  	      {
321  	         /* the hole overlaps the upper bound: decrease upper bound, remove this hole and all remaining holes */
322  	         SCIPsetDebugMsg(set, "upper bound <%.15g> lays in current hole; store new upper bound and remove this and all remaining holes\n", dom->ub);
323  	
324  	         assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, dom->ub));
325  	
326  	         /* adjust upper bound */
327  	         dom->ub = (*holelistptr)->hole.left;
328  	
329  	         if(newub != NULL )
330  	            *newub = (*holelistptr)->hole.left;
331  	
332  	         /* remove remaining hole list */
333  	         holelistFree(holelistptr, blkmem);
334  	         assert(*holelistptr == NULL);
335  	
336  	         /* unlink this hole from the previous hole */
337  	         *lastnextptr = NULL;
338  	      }
339  	      else if( SCIPsetIsGT(set, *lastrightptr, (*holelistptr)->hole.left) )
340  	      {
341  	         /* the right bound of the last hole is greater than the left bound of this hole: increase the right bound of
342  	          * the last hole, delete this hole */
343  	         SCIP_HOLELIST* nextholelist;
344  	
345  	         if( SCIPsetIsEQ(set, *lastrightptr, dom->lb ) )
346  	         {
347  	            /* the reason for the overlap results from the lower bound hole (-infinity,lb); therefore, we can increase
348  	             * the lower bound */
349  	            SCIPsetDebugMsg(set, "lower bound <%.15g> lays in current hole; store new lower bound and remove hole\n", dom->lb);
350  	            *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
351  	
352  	            /* adjust lower bound */
353  	            dom->lb = *lastrightptr;
354  	
355  	            if(newlb != NULL )
356  	               *newlb = *lastrightptr;
357  	         }
358  	         else
359  	         {
360  	            SCIPsetDebugMsg(set, "current hole overlaps with the previous one (...,%.15g); merge to (...,%.15g)\n",
361  	               *lastrightptr, MAX(*lastrightptr, (*holelistptr)->hole.right) );
362  	            *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
363  	         }
364  	         nextholelist = (*holelistptr)->next;
365  	         (*holelistptr)->next = NULL;
366  	         holelistFree(holelistptr, blkmem);
367  	
368  	         /* connect the linked list after removing the hole */
369  	         *lastnextptr = nextholelist;
370  	
371  	         /* get next hole */
372  	         *holelistptr = nextholelist;
373  	      }
374  	      else
375  	      {
376  	         /* the holes do not overlap: update lastholelist and lastrightptr */
377  	         lastrightptr = &(*holelistptr)->hole.right;
378  	         lastnextptr = &(*holelistptr)->next;
379  	
380  	         /* get next hole */
381  	         holelistptr = &(*holelistptr)->next;
382  	      }
383  	   }
384  	
385  	#ifndef NDEBUG
386  	   {
387  	      /* check that holes are merged */
388  	      SCIP_Real lastright;
389  	
390  	      lastright = dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
391  	      holelistptr = &dom->holelist;
392  	
393  	      while( *holelistptr != NULL )
394  	      {
395  	         /* check the the last right interval is smaller or equal to the current left interval (none overlapping) */
396  	         assert( SCIPsetIsLE(set, lastright, (*holelistptr)->hole.left) );
397  	
398  	         /* check the hole property (check that the hole is not empty) */
399  	         assert( SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right) );
400  	         lastright = (*holelistptr)->hole.right;
401  	
402  	         /* get next hole */
403  	         holelistptr = &(*holelistptr)->next;
404  	      }   
405  	
406  	      /* check the the last right interval is smaller or equal to the upper bound (none overlapping) */     
407  	      assert( SCIPsetIsLE(set, lastright, dom->ub) );
408  	   }
409  	#endif
410  	}
411  	
412  	/*
413  	 * domain change methods
414  	 */
415  	
416  	/** ensures, that bound change info array for lower bound changes can store at least num entries */
417  	static
418  	SCIP_RETCODE varEnsureLbchginfosSize(
419  	   SCIP_VAR*             var,                /**< problem variable */
420  	   BMS_BLKMEM*           blkmem,             /**< block memory */
421  	   SCIP_SET*             set,                /**< global SCIP settings */
422  	   int                   num                 /**< minimum number of entries to store */
423  	   )
424  	{
425  	   assert(var != NULL);
426  	   assert(var->nlbchginfos <= var->lbchginfossize);
427  	   assert(SCIPvarIsTransformed(var));
428  	
429  	   if( num > var->lbchginfossize )
430  	   {
431  	      int newsize;
432  	
433  	      newsize = SCIPsetCalcMemGrowSize(set, num);
434  	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->lbchginfos, var->lbchginfossize, newsize) );
435  	      var->lbchginfossize = newsize;
436  	   }
437  	   assert(num <= var->lbchginfossize);
438  	
439  	   return SCIP_OKAY;
440  	}
441  	
442  	/** ensures, that bound change info array for upper bound changes can store at least num entries */
443  	static
444  	SCIP_RETCODE varEnsureUbchginfosSize(
445  	   SCIP_VAR*             var,                /**< problem variable */
446  	   BMS_BLKMEM*           blkmem,             /**< block memory */
447  	   SCIP_SET*             set,                /**< global SCIP settings */
448  	   int                   num                 /**< minimum number of entries to store */
449  	   )
450  	{
451  	   assert(var != NULL);
452  	   assert(var->nubchginfos <= var->ubchginfossize);
453  	   assert(SCIPvarIsTransformed(var));
454  	
455  	   if( num > var->ubchginfossize )
456  	   {
457  	      int newsize;
458  	
459  	      newsize = SCIPsetCalcMemGrowSize(set, num);
460  	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->ubchginfos, var->ubchginfossize, newsize) );
461  	      var->ubchginfossize = newsize;
462  	   }
463  	   assert(num <= var->ubchginfossize);
464  	
465  	   return SCIP_OKAY;
466  	}
467  	
468  	/** adds domain change info to the variable's lower bound change info array */
469  	static
470  	SCIP_RETCODE varAddLbchginfo(
471  	   SCIP_VAR*             var,                /**< problem variable */
472  	   BMS_BLKMEM*           blkmem,             /**< block memory */
473  	   SCIP_SET*             set,                /**< global SCIP settings */
474  	   SCIP_Real             oldbound,           /**< old value for bound */
475  	   SCIP_Real             newbound,           /**< new value for bound */
476  	   int                   depth,              /**< depth in the tree, where the bound change takes place */
477  	   int                   pos,                /**< position of the bound change in its bound change array */
478  	   SCIP_VAR*             infervar,           /**< variable that was changed (parent of var, or var itself) */
479  	   SCIP_CONS*            infercons,          /**< constraint that infered this bound change, or NULL */
480  	   SCIP_PROP*            inferprop,          /**< propagator that deduced the bound change, or NULL */
481  	   int                   inferinfo,          /**< user information for inference to help resolving the conflict */
482  	   SCIP_BOUNDTYPE        inferboundtype,     /**< type of bound for inference var: lower or upper bound */
483  	   SCIP_BOUNDCHGTYPE     boundchgtype        /**< bound change type: branching decision or infered bound change */
484  	   )
485  	{
486  	   assert(var != NULL);
487  	   assert(SCIPsetIsLT(set, oldbound, newbound));
488  	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, oldbound));
489  	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
490  	   assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 0.0));
491  	   assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 1.0));
492  	   assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
493  	   assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
494  	   assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
495  	
496  	   SCIPsetDebugMsg(set, "adding lower bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
497  	      SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
498  	      infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
499  	      oldbound, newbound);
500  	
501  	   SCIP_CALL( varEnsureLbchginfosSize(var, blkmem, set, var->nlbchginfos+1) );
502  	   var->lbchginfos[var->nlbchginfos].oldbound = oldbound;
503  	   var->lbchginfos[var->nlbchginfos].newbound = newbound;
504  	   var->lbchginfos[var->nlbchginfos].var = var;
505  	   var->lbchginfos[var->nlbchginfos].bdchgidx.depth = depth;
506  	   var->lbchginfos[var->nlbchginfos].bdchgidx.pos = pos;
507  	   var->lbchginfos[var->nlbchginfos].pos = var->nlbchginfos; /*lint !e732*/
508  	   var->lbchginfos[var->nlbchginfos].boundchgtype = boundchgtype; /*lint !e641*/
509  	   var->lbchginfos[var->nlbchginfos].boundtype = SCIP_BOUNDTYPE_LOWER; /*lint !e641*/
510  	   var->lbchginfos[var->nlbchginfos].redundant = FALSE;
511  	   var->lbchginfos[var->nlbchginfos].inferboundtype = inferboundtype; /*lint !e641*/
512  	   var->lbchginfos[var->nlbchginfos].inferencedata.var = infervar;
513  	   var->lbchginfos[var->nlbchginfos].inferencedata.info = inferinfo;
514  	
515  	   /**@note The "pos" data member of the bound change info has a size of 27 bits */
516  	   assert(var->nlbchginfos < 1 << 27);
517  	
518  	   switch( boundchgtype )
519  	   {
520  	   case SCIP_BOUNDCHGTYPE_BRANCHING:
521  	      break;
522  	   case SCIP_BOUNDCHGTYPE_CONSINFER:
523  	      assert(infercons != NULL);
524  	      var->lbchginfos[var->nlbchginfos].inferencedata.reason.cons = infercons;
525  	      break;
526  	   case SCIP_BOUNDCHGTYPE_PROPINFER:
527  	      var->lbchginfos[var->nlbchginfos].inferencedata.reason.prop = inferprop;
528  	      break;
529  	   default:
530  	      SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
531  	      return SCIP_INVALIDDATA;
532  	   }
533  	
534  	   var->nlbchginfos++;
535  	
536  	   assert(var->nlbchginfos < 2
537  	      || SCIPbdchgidxIsEarlier(&var->lbchginfos[var->nlbchginfos-2].bdchgidx,
538  	         &var->lbchginfos[var->nlbchginfos-1].bdchgidx));
539  	
540  	   return SCIP_OKAY;
541  	}
542  	
543  	/** adds domain change info to the variable's upper bound change info array */
544  	static
545  	SCIP_RETCODE varAddUbchginfo(
546  	   SCIP_VAR*             var,                /**< problem variable */
547  	   BMS_BLKMEM*           blkmem,             /**< block memory */
548  	   SCIP_SET*             set,                /**< global SCIP settings */
549  	   SCIP_Real             oldbound,           /**< old value for bound */
550  	   SCIP_Real             newbound,           /**< new value for bound */
551  	   int                   depth,              /**< depth in the tree, where the bound change takes place */
552  	   int                   pos,                /**< position of the bound change in its bound change array */
553  	   SCIP_VAR*             infervar,           /**< variable that was changed (parent of var, or var itself) */
554  	   SCIP_CONS*            infercons,          /**< constraint that infered this bound change, or NULL */
555  	   SCIP_PROP*            inferprop,          /**< propagator that deduced the bound change, or NULL */
556  	   int                   inferinfo,          /**< user information for inference to help resolving the conflict */
557  	   SCIP_BOUNDTYPE        inferboundtype,     /**< type of bound for inference var: lower or upper bound */
558  	   SCIP_BOUNDCHGTYPE     boundchgtype        /**< bound change type: branching decision or infered bound change */
559  	   )
560  	{
561  	   assert(var != NULL);
562  	   assert(SCIPsetIsGT(set, oldbound, newbound));
563  	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, oldbound));
564  	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
565  	   assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 1.0));
566  	   assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 0.0));
567  	   assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
568  	   assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
569  	   assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
570  	
571  	   SCIPsetDebugMsg(set, "adding upper bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
572  	      SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
573  	      infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
574  	      oldbound, newbound);
575  	
576  	   SCIP_CALL( varEnsureUbchginfosSize(var, blkmem, set, var->nubchginfos+1) );
577  	   var->ubchginfos[var->nubchginfos].oldbound = oldbound;
578  	   var->ubchginfos[var->nubchginfos].newbound = newbound;
579  	   var->ubchginfos[var->nubchginfos].var = var;
580  	   var->ubchginfos[var->nubchginfos].bdchgidx.depth = depth;
581  	   var->ubchginfos[var->nubchginfos].bdchgidx.pos = pos;
582  	   var->ubchginfos[var->nubchginfos].pos = var->nubchginfos; /*lint !e732*/
583  	   var->ubchginfos[var->nubchginfos].boundchgtype = boundchgtype; /*lint !e641*/
584  	   var->ubchginfos[var->nubchginfos].boundtype = SCIP_BOUNDTYPE_UPPER; /*lint !e641*/
585  	   var->ubchginfos[var->nubchginfos].redundant = FALSE;
586  	   var->ubchginfos[var->nubchginfos].inferboundtype = inferboundtype; /*lint !e641*/
587  	   var->ubchginfos[var->nubchginfos].inferencedata.var = infervar;
588  	   var->ubchginfos[var->nubchginfos].inferencedata.info = inferinfo;
589  	
590  	   /**@note The "pos" data member of the bound change info has a size of 27 bits */
591  	   assert(var->nubchginfos < 1 << 27);
592  	
593  	   switch( boundchgtype )
594  	   {
595  	   case SCIP_BOUNDCHGTYPE_BRANCHING:
596  	      break;
597  	   case SCIP_BOUNDCHGTYPE_CONSINFER:
598  	      assert(infercons != NULL);
599  	      var->ubchginfos[var->nubchginfos].inferencedata.reason.cons = infercons;
600  	      break;
601  	   case SCIP_BOUNDCHGTYPE_PROPINFER:
602  	      var->ubchginfos[var->nubchginfos].inferencedata.reason.prop = inferprop;
603  	      break;
604  	   default:
605  	      SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
606  	      return SCIP_INVALIDDATA;
607  	   }
608  	
609  	   var->nubchginfos++;
610  	
611  	   assert(var->nubchginfos < 2
612  	      || SCIPbdchgidxIsEarlier(&var->ubchginfos[var->nubchginfos-2].bdchgidx,
613  	         &var->ubchginfos[var->nubchginfos-1].bdchgidx));
614  	
615  	   return SCIP_OKAY;
616  	}
617  	
618  	/** applies single bound change */
619  	SCIP_RETCODE SCIPboundchgApply(
620  	   SCIP_BOUNDCHG*        boundchg,           /**< bound change to apply */
621  	   BMS_BLKMEM*           blkmem,             /**< block memory */
622  	   SCIP_SET*             set,                /**< global SCIP settings */
623  	   SCIP_STAT*            stat,               /**< problem statistics */
624  	   SCIP_LP*              lp,                 /**< current LP data */
625  	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
626  	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
627  	   int                   depth,              /**< depth in the tree, where the bound change takes place */
628  	   int                   pos,                /**< position of the bound change in its bound change array */
629  	   SCIP_Bool*            cutoff              /**< pointer to store whether an infeasible bound change was detected */
630  	   )
631  	{
632  	   SCIP_VAR* var;
633  	
634  	   assert(boundchg != NULL);
635  	   assert(stat != NULL);
636  	   assert(depth > 0);
637  	   assert(pos >= 0);
638  	   assert(cutoff != NULL);
639  	
640  	   *cutoff = FALSE;
641  	
642  	   /* ignore redundant bound changes */
643  	   if( boundchg->redundant )
644  	      return SCIP_OKAY;
645  	
646  	   var = boundchg->var;
647  	   assert(var != NULL);
648  	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
649  	   assert(!SCIPvarIsIntegral(var) || SCIPsetIsFeasIntegral(set, boundchg->newbound));
650  	
651  	   /* apply bound change */
652  	   switch( boundchg->boundtype )
653  	   {
654  	   case SCIP_BOUNDTYPE_LOWER:
655  	      /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
656  	      if( SCIPsetIsGT(set, boundchg->newbound, var->locdom.lb) )
657  	      {
658  	         if( SCIPsetIsLE(set, boundchg->newbound, var->locdom.ub) )
659  	         {
660  	            /* add the bound change info to the variable's bound change info array */
661  	            switch( boundchg->boundchgtype )
662  	            {
663  	            case SCIP_BOUNDCHGTYPE_BRANCHING:
664  	               SCIPsetDebugMsg(set, " -> branching: new lower bound of <%s>[%g,%g]: %g\n",
665  	                  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
666  	               SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
667  	                     NULL, NULL, NULL, 0, SCIP_BOUNDTYPE_LOWER, SCIP_BOUNDCHGTYPE_BRANCHING) );
668  	               stat->lastbranchvar = var;
669  	               stat->lastbranchdir = SCIP_BRANCHDIR_UPWARDS;
670  	               stat->lastbranchvalue = boundchg->newbound;
671  	               break;
672  	
673  	            case SCIP_BOUNDCHGTYPE_CONSINFER:
674  	               assert(boundchg->data.inferencedata.reason.cons != NULL);
675  	               SCIPsetDebugMsg(set, " -> constraint <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
676  	                  SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
677  	                  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
678  	               SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
679  	                     boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
680  	                     boundchg->data.inferencedata.info,
681  	                     (SCIP_BOUNDTYPE)(boundchg->inferboundtype), SCIP_BOUNDCHGTYPE_CONSINFER) );
682  	               break;
683  	
684  	            case SCIP_BOUNDCHGTYPE_PROPINFER:
685  	               SCIPsetDebugMsg(set, " -> propagator <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
686  	                  boundchg->data.inferencedata.reason.prop != NULL
687  	                  ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
688  	                  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
689  	               SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
690  	                     boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
691  	                     boundchg->data.inferencedata.info,
692  	                     (SCIP_BOUNDTYPE)(boundchg->inferboundtype), SCIP_BOUNDCHGTYPE_PROPINFER) );
693  	               break;
694  	
695  	            default:
696  	               SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
697  	               return SCIP_INVALIDDATA;
698  	            }
699  	
700  	            /* change local bound of variable */
701  	            SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
702  	         }
703  	         else
704  	         {
705  	            SCIPsetDebugMsg(set, " -> cutoff: new lower bound of <%s>[%g,%g]: %g\n",
706  	               SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
707  	            *cutoff = TRUE;
708  	            boundchg->redundant = TRUE; /* bound change has not entered the lbchginfos array of the variable! */
709  	         }
710  	      }
711  	      else
712  	      {
713  	         /* mark bound change to be inactive */
714  	         SCIPsetDebugMsg(set, " -> inactive %s: new lower bound of <%s>[%g,%g]: %g\n",
715  	            (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
716  	            SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
717  	         boundchg->redundant = TRUE;
718  	      }
719  	      break;
720  	
721  	   case SCIP_BOUNDTYPE_UPPER:
722  	      /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
723  	      if( SCIPsetIsLT(set, boundchg->newbound, var->locdom.ub) )
724  	      {
725  	         if( SCIPsetIsGE(set, boundchg->newbound, var->locdom.lb) )
726  	         {
727  	            /* add the bound change info to the variable's bound change info array */
728  	            switch( boundchg->boundchgtype )
729  	            {
730  	            case SCIP_BOUNDCHGTYPE_BRANCHING:
731  	               SCIPsetDebugMsg(set, " -> branching: new upper bound of <%s>[%g,%g]: %g\n",
732  	                  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
733  	               SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
734  	                     NULL, NULL, NULL, 0, SCIP_BOUNDTYPE_UPPER, SCIP_BOUNDCHGTYPE_BRANCHING) );
735  	               stat->lastbranchvar = var;
736  	               stat->lastbranchdir = SCIP_BRANCHDIR_DOWNWARDS;
737  	               stat->lastbranchvalue = boundchg->newbound;
738  	               break;
739  	
740  	            case SCIP_BOUNDCHGTYPE_CONSINFER:
741  	               assert(boundchg->data.inferencedata.reason.cons != NULL);
742  	               SCIPsetDebugMsg(set, " -> constraint <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
743  	                  SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
744  	                  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
745  	               SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
746  	                     boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
747  	                     boundchg->data.inferencedata.info,
748  	                     (SCIP_BOUNDTYPE)(boundchg->inferboundtype), SCIP_BOUNDCHGTYPE_CONSINFER) );
749  	               break;
750  	
751  	            case SCIP_BOUNDCHGTYPE_PROPINFER:
752  	               SCIPsetDebugMsg(set, " -> propagator <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
753  	                  boundchg->data.inferencedata.reason.prop != NULL
754  	                  ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
755  	                  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
756  	               SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
757  	                     boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
758  	                     boundchg->data.inferencedata.info,
759  	                     (SCIP_BOUNDTYPE)(boundchg->inferboundtype), SCIP_BOUNDCHGTYPE_PROPINFER) );
760  	               break;
761  	
762  	            default:
763  	               SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
764  	               return SCIP_INVALIDDATA;
765  	            }
766  	
767  	            /* change local bound of variable */
768  	            SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
769  	         }
770  	         else
771  	         {
772  	            SCIPsetDebugMsg(set, " -> cutoff: new upper bound of <%s>[%g,%g]: %g\n",
773  	               SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
774  	            *cutoff = TRUE;
775  	            boundchg->redundant = TRUE; /* bound change has not entered the ubchginfos array of the variable! */
776  	         }
777  	      }
778  	      else
779  	      {
780  	         /* mark bound change to be inactive */
781  	         SCIPsetDebugMsg(set, " -> inactive %s: new upper bound of <%s>[%g,%g]: %g\n",
782  	            (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
783  	            SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
784  	         boundchg->redundant = TRUE;
785  	      }
786  	      break;
787  	
788  	   default:
789  	      SCIPerrorMessage("unknown bound type\n");
790  	      return SCIP_INVALIDDATA;
791  	   }
792  	
793  	   /* update the branching and inference history */
794  	   if( !boundchg->applied && !boundchg->redundant )
795  	   {
796  	      assert(var == boundchg->var);
797  	
798  	      if( (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING )
799  	      {
800  	         SCIP_CALL( SCIPvarIncNBranchings(var, blkmem, set, stat,
801  	               (SCIP_BOUNDTYPE)boundchg->boundtype == SCIP_BOUNDTYPE_LOWER
802  	               ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS, boundchg->newbound, depth) );
803  	      }
804  	      else if( stat->lastbranchvar != NULL )
805  	      {
806  	         /**@todo if last branching variable is unknown, retrieve it from the nodes' boundchg arrays */
807  	         SCIP_CALL( SCIPvarIncInferenceSum(stat->lastbranchvar, blkmem, set, stat, stat->lastbranchdir, stat->lastbranchvalue, 1.0) );
808  	      }
809  	      boundchg->applied = TRUE;
810  	   }
811  	
812  	   return SCIP_OKAY;
813  	}
814  	
815  	/** undoes single bound change */
816  	SCIP_RETCODE SCIPboundchgUndo(
817  	   SCIP_BOUNDCHG*        boundchg,           /**< bound change to remove */
818  	   BMS_BLKMEM*           blkmem,             /**< block memory */
819  	   SCIP_SET*             set,                /**< global SCIP settings */
820  	   SCIP_STAT*            stat,               /**< problem statistics */
821  	   SCIP_LP*              lp,                 /**< current LP data */
822  	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
823  	   SCIP_EVENTQUEUE*      eventqueue          /**< event queue */
824  	   )
825  	{
826  	   SCIP_VAR* var;
827  	
828  	   assert(boundchg != NULL);
829  	   assert(stat != NULL);
830  	
831  	   /* ignore redundant bound changes */
832  	   if( boundchg->redundant )
833  	      return SCIP_OKAY;
834  	
835  	   var = boundchg->var;
836  	   assert(var != NULL);
837  	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
838  	
839  	   /* undo bound change: apply the previous bound change of variable */
840  	   switch( boundchg->boundtype )
841  	   {
842  	   case SCIP_BOUNDTYPE_LOWER:
843  	      var->nlbchginfos--;
844  	      assert(var->nlbchginfos >= 0);
845  	      assert(var->lbchginfos != NULL);
846  	      assert( SCIPsetIsFeasEQ(set, var->lbchginfos[var->nlbchginfos].newbound, var->locdom.lb) ); /*lint !e777*/
847  	      assert( SCIPsetIsFeasLE(set, boundchg->newbound, var->locdom.lb) ); /* current lb might be larger to intermediate global bound change */
848  	
849  	      SCIPsetDebugMsg(set, "removed lower bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
850  	         SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
851  	         var->lbchginfos[var->nlbchginfos].bdchgidx.depth, var->lbchginfos[var->nlbchginfos].bdchgidx.pos,
852  	         var->lbchginfos[var->nlbchginfos].oldbound, var->lbchginfos[var->nlbchginfos].newbound);
853  	
854  	      /* reinstall the previous local bound */
855  	      SCIP_CALL( SCIPvarChgLbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
856  	            var->lbchginfos[var->nlbchginfos].oldbound) );
857  	
858  	      /* in case all bound changes are removed the local bound should match the global bound */
859  	      assert(var->nlbchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.lb, var->glbdom.lb));
860  	
861  	      break;
862  	
863  	   case SCIP_BOUNDTYPE_UPPER:
864  	      var->nubchginfos--;
865  	      assert(var->nubchginfos >= 0);
866  	      assert(var->ubchginfos != NULL);
867  	      assert( SCIPsetIsFeasEQ(set, var->ubchginfos[var->nubchginfos].newbound, var->locdom.ub) ); /*lint !e777*/
868  	      assert( SCIPsetIsFeasGE(set, boundchg->newbound, var->locdom.ub) ); /* current ub might be smaller to intermediate global bound change */
869  	
870  	      SCIPsetDebugMsg(set, "removed upper bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
871  	         SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
872  	         var->ubchginfos[var->nubchginfos].bdchgidx.depth, var->ubchginfos[var->nubchginfos].bdchgidx.pos,
873  	         var->ubchginfos[var->nubchginfos].oldbound, var->ubchginfos[var->nubchginfos].newbound);
874  	
875  	      /* reinstall the previous local bound */
876  	      SCIP_CALL( SCIPvarChgUbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
877  	            var->ubchginfos[var->nubchginfos].oldbound) );
878  	
879  	      /* in case all bound changes are removed the local bound should match the global bound */
880  	      assert(var->nubchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.ub, var->glbdom.ub));
881  	
882  	      break;
883  	
884  	   default:
885  	      SCIPerrorMessage("unknown bound type\n");
886  	      return SCIP_INVALIDDATA;
887  	   }
888  	
889  	   /* update last branching variable */
890  	   if( (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING )
891  	   {
892  	      stat->lastbranchvar = NULL;
893  	      stat->lastbranchvalue = SCIP_UNKNOWN;
894  	   }
895  	
896  	   return SCIP_OKAY;
897  	}
898  	
899  	/** applies single bound change to the global problem by changing the global bound of the corresponding variable */
900  	static
901  	SCIP_RETCODE boundchgApplyGlobal(
902  	   SCIP_BOUNDCHG*        boundchg,           /**< bound change to apply */
903  	   BMS_BLKMEM*           blkmem,             /**< block memory */
904  	   SCIP_SET*             set,                /**< global SCIP settings */
905  	   SCIP_STAT*            stat,               /**< problem statistics */
906  	   SCIP_LP*              lp,                 /**< current LP data */
907  	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
908  	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
909  	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
910  	   SCIP_Bool*            cutoff              /**< pointer to store whether an infeasible bound change was detected */
911  	   )
912  	{
913  	   SCIP_VAR* var;
914  	   SCIP_Real newbound;
915  	   SCIP_BOUNDTYPE boundtype;
916  	
917  	   assert(boundchg != NULL);
918  	   assert(cutoff != NULL);
919  	
920  	   *cutoff = FALSE;
921  	
922  	   /* ignore redundant bound changes */
923  	   if( boundchg->redundant )
924  	      return SCIP_OKAY;
925  	
926  	   var = SCIPboundchgGetVar(boundchg);
927  	   newbound = SCIPboundchgGetNewbound(boundchg);
928  	   boundtype = SCIPboundchgGetBoundtype(boundchg);
929  	
930  	   /* check if the bound change is redundant which can happen due to a (better) global bound change which was performed
931  	    * after that bound change was applied
932  	    *
933  	    * @note a global bound change is not captured by the redundant member of the bound change data structure
934  	    */
935  	   if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasLE(set, newbound, SCIPvarGetLbGlobal(var)))
936  	      || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasGE(set, newbound, SCIPvarGetUbGlobal(var))) )
937  	   {
938  	      return SCIP_OKAY;
939  	   }
940  	
941  	   SCIPsetDebugMsg(set, "applying global bound change: <%s>[%g,%g] %s %g\n",
942  	      SCIPvarGetName(var), SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var),
943  	      boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", newbound);
944  	
945  	   /* check for cutoff */
946  	   if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, newbound, SCIPvarGetUbGlobal(var)))
947  	      || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, newbound, SCIPvarGetLbGlobal(var))) )
948  	   {
949  	      *cutoff = TRUE;
950  	      return SCIP_OKAY;
951  	   }
952  	
953  	   /* apply bound change */
954  	   SCIP_CALL( SCIPvarChgBdGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound, boundtype) );
955  	
956  	   return SCIP_OKAY;
957  	}
958  	
959  	/** captures branching and inference data of bound change */
960  	static
961  	SCIP_RETCODE boundchgCaptureData(
962  	   SCIP_BOUNDCHG*        boundchg            /**< bound change to remove */
963  	   )
964  	{
965  	   assert(boundchg != NULL);
966  	
967  	   /* capture variable associated with the bound change */
968  	   assert(boundchg->var != NULL);
969  	   SCIPvarCapture(boundchg->var);
970  	
971  	   switch( boundchg->boundchgtype )
972  	   {
973  	   case SCIP_BOUNDCHGTYPE_BRANCHING:
974  	   case SCIP_BOUNDCHGTYPE_PROPINFER:
975  	      break;
976  	
977  	   case SCIP_BOUNDCHGTYPE_CONSINFER:
978  	      assert(boundchg->data.inferencedata.var != NULL);
979  	      assert(boundchg->data.inferencedata.reason.cons != NULL);
980  	      SCIPconsCapture(boundchg->data.inferencedata.reason.cons);
981  	      break;
982  	
983  	   default:
984  	      SCIPerrorMessage("invalid bound change type\n");
985  	      return SCIP_INVALIDDATA;
986  	   }
987  	
988  	   return SCIP_OKAY;
989  	}
990  	
991  	/** releases branching and inference data of bound change */
992  	static
993  	SCIP_RETCODE boundchgReleaseData(
994  	   SCIP_BOUNDCHG*        boundchg,           /**< bound change to remove */
995  	   BMS_BLKMEM*           blkmem,             /**< block memory */
996  	   SCIP_SET*             set,                /**< global SCIP settings */
997  	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
998  	   SCIP_LP*              lp                  /**< current LP data */
999  	
1000 	   )
1001 	{
1002 	   assert(boundchg != NULL);
1003 	
1004 	   switch( boundchg->boundchgtype )
1005 	   {
1006 	   case SCIP_BOUNDCHGTYPE_BRANCHING:
1007 	   case SCIP_BOUNDCHGTYPE_PROPINFER:
1008 	      break;
1009 	
1010 	   case SCIP_BOUNDCHGTYPE_CONSINFER:
1011 	      assert(boundchg->data.inferencedata.var != NULL);
1012 	      assert(boundchg->data.inferencedata.reason.cons != NULL);
1013 	      SCIP_CALL( SCIPconsRelease(&boundchg->data.inferencedata.reason.cons, blkmem, set) );
1014 	      break;
1015 	
1016 	   default:
1017 	      SCIPerrorMessage("invalid bound change type\n");
1018 	      return SCIP_INVALIDDATA;
1019 	   }
1020 	
1021 	   /* release variable */
1022 	   assert(boundchg->var != NULL);
1023 	   SCIP_CALL( SCIPvarRelease(&boundchg->var, blkmem, set, eventqueue, lp) );
1024 	
1025 	   return SCIP_OKAY;
1026 	}
1027 	
1028 	/** creates empty domain change data with dynamic arrays */
1029 	static
1030 	SCIP_RETCODE domchgCreate(
1031 	   SCIP_DOMCHG**         domchg,             /**< pointer to domain change data */
1032 	   BMS_BLKMEM*           blkmem              /**< block memory */
1033 	   )
1034 	{
1035 	   assert(domchg != NULL);
1036 	   assert(blkmem != NULL);
1037 	
1038 	   SCIP_ALLOC( BMSallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN)) );
1039 	   (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1040 	   (*domchg)->domchgdyn.nboundchgs = 0;
1041 	   (*domchg)->domchgdyn.boundchgs = NULL;
1042 	   (*domchg)->domchgdyn.nholechgs = 0;
1043 	   (*domchg)->domchgdyn.holechgs = NULL;
1044 	   (*domchg)->domchgdyn.boundchgssize = 0;
1045 	   (*domchg)->domchgdyn.holechgssize = 0;
1046 	
1047 	   return SCIP_OKAY;
1048 	}
1049 	
1050 	/** frees domain change data */
1051 	SCIP_RETCODE SCIPdomchgFree(
1052 	   SCIP_DOMCHG**         domchg,             /**< pointer to domain change */
1053 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1054 	   SCIP_SET*             set,                /**< global SCIP settings */
1055 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
1056 	   SCIP_LP*              lp                  /**< current LP data */
1057 	   )
1058 	{
1059 	   assert(domchg != NULL);
1060 	   assert(blkmem != NULL);
1061 	
1062 	   if( *domchg != NULL )
1063 	   {
1064 	      int i;
1065 	
1066 	      /* release variables, branching and inference data associated with the bound changes */
1067 	      for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1068 	      {
1069 	         SCIP_CALL( boundchgReleaseData(&(*domchg)->domchgbound.boundchgs[i], blkmem, set, eventqueue, lp) );
1070 	      }
1071 	
1072 	      /* free memory for bound and hole changes */
1073 	      switch( (*domchg)->domchgdyn.domchgtype )
1074 	      {
1075 	      case SCIP_DOMCHGTYPE_BOUND:
1076 	         BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgbound.boundchgs, (*domchg)->domchgbound.nboundchgs);
1077 	         BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND));
1078 	         break;
1079 	      case SCIP_DOMCHGTYPE_BOTH:
1080 	         BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.boundchgs, (*domchg)->domchgboth.nboundchgs);
1081 	         BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.holechgs, (*domchg)->domchgboth.nholechgs);
1082 	         BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH));
1083 	         break;
1084 	      case SCIP_DOMCHGTYPE_DYNAMIC:
1085 	         BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.boundchgs, (*domchg)->domchgdyn.boundchgssize);
1086 	         BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1087 	         BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN));
1088 	         break;
1089 	      default:
1090 	         SCIPerrorMessage("invalid domain change type\n");
1091 	         return SCIP_INVALIDDATA;
1092 	      }
1093 	   }
1094 	
1095 	   return SCIP_OKAY;
1096 	}
1097 	
1098 	/** converts a static domain change data into a dynamic one */
1099 	static
1100 	SCIP_RETCODE domchgMakeDynamic(
1101 	   SCIP_DOMCHG**         domchg,             /**< pointer to domain change data */
1102 	   BMS_BLKMEM*           blkmem              /**< block memory */
1103 	   )
1104 	{
1105 	   assert(domchg != NULL);
1106 	   assert(blkmem != NULL);
1107 	
1108 	   SCIPdebugMessage("making domain change data %p pointing to %p dynamic\n", (void*)domchg, (void*)*domchg);
1109 	
1110 	   if( *domchg == NULL )
1111 	   {
1112 	      SCIP_CALL( domchgCreate(domchg, blkmem) );
1113 	   }
1114 	   else
1115 	   {
1116 	      switch( (*domchg)->domchgdyn.domchgtype )
1117 	      {
1118 	      case SCIP_DOMCHGTYPE_BOUND:
1119 	         SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND), sizeof(SCIP_DOMCHGDYN)) );
1120 	         (*domchg)->domchgdyn.nholechgs = 0;
1121 	         (*domchg)->domchgdyn.holechgs = NULL;
1122 	         (*domchg)->domchgdyn.boundchgssize = (int) (*domchg)->domchgdyn.nboundchgs;
1123 	         (*domchg)->domchgdyn.holechgssize = 0;
1124 	         (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1125 	         break;
1126 	      case SCIP_DOMCHGTYPE_BOTH:
1127 	         SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGDYN)) );
1128 	         (*domchg)->domchgdyn.boundchgssize = (int) (*domchg)->domchgdyn.nboundchgs;
1129 	         (*domchg)->domchgdyn.holechgssize = (*domchg)->domchgdyn.nholechgs;
1130 	         (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1131 	         break;
1132 	      case SCIP_DOMCHGTYPE_DYNAMIC:
1133 	         break;
1134 	      default:
1135 	         SCIPerrorMessage("invalid domain change type\n");
1136 	         return SCIP_INVALIDDATA;
1137 	      }
1138 	   }
1139 	#ifndef NDEBUG
1140 	   {
1141 	      int i;
1142 	      for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1143 	         assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1144 	            || EPSISINT((*domchg)->domchgbound.boundchgs[i].newbound, 1e-06));
1145 	   }
1146 	#endif
1147 	
1148 	   return SCIP_OKAY;
1149 	}
1150 	
1151 	/** converts a dynamic domain change data into a static one, using less memory than for a dynamic one */
1152 	SCIP_RETCODE SCIPdomchgMakeStatic(
1153 	   SCIP_DOMCHG**         domchg,             /**< pointer to domain change data */
1154 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1155 	   SCIP_SET*             set,                /**< global SCIP settings */
1156 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
1157 	   SCIP_LP*              lp                  /**< current LP data */
1158 	   )
1159 	{
1160 	   assert(domchg != NULL);
1161 	   assert(blkmem != NULL);
1162 	
1163 	   SCIPsetDebugMsg(set, "making domain change data %p pointing to %p static\n", (void*)domchg, (void*)*domchg);
1164 	
1165 	   if( *domchg != NULL )
1166 	   {
1167 	      switch( (*domchg)->domchgdyn.domchgtype )
1168 	      {
1169 	      case SCIP_DOMCHGTYPE_BOUND:
1170 	         if( (*domchg)->domchgbound.nboundchgs == 0 )
1171 	         {
1172 	            SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1173 	         }
1174 	         break;
1175 	      case SCIP_DOMCHGTYPE_BOTH:
1176 	         if( (*domchg)->domchgboth.nholechgs == 0 )
1177 	         {
1178 	            if( (*domchg)->domchgbound.nboundchgs == 0 )
1179 	            {
1180 	               SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1181 	            }
1182 	            else
1183 	            {
1184 	               SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGBOUND)) );
1185 	               (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1186 	            }
1187 	         }
1188 	         break;
1189 	      case SCIP_DOMCHGTYPE_DYNAMIC:
1190 	         if( (*domchg)->domchgboth.nholechgs == 0 )
1191 	         {
1192 	            if( (*domchg)->domchgbound.nboundchgs == 0 )
1193 	            {
1194 	               SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1195 	            }
1196 	            else
1197 	            {
1198 	               /* shrink dynamic size arrays to their minimal sizes */
1199 	               SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs, \
1200 	                     (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1201 	               BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1202 	
1203 	               /* convert into static domain change */
1204 	               SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOUND)) );
1205 	               (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1206 	            }
1207 	         }
1208 	         else
1209 	         {
1210 	            /* shrink dynamic size arrays to their minimal sizes */
1211 	            SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs, \
1212 	                  (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1213 	            SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.holechgs, \
1214 	                  (*domchg)->domchgdyn.holechgssize, (*domchg)->domchgdyn.nholechgs) );
1215 	
1216 	            /* convert into static domain change */
1217 	            SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOTH)) );
1218 	            (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOTH; /*lint !e641*/
1219 	         }
1220 	         break;
1221 	      default:
1222 	         SCIPerrorMessage("invalid domain change type\n");
1223 	         return SCIP_INVALIDDATA;
1224 	      }
1225 	#ifndef NDEBUG
1226 	      if( *domchg != NULL )
1227 	      {
1228 	         int i;
1229 	         for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1230 	            assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1231 	               || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1232 	      }
1233 	#endif
1234 	   }
1235 	
1236 	   return SCIP_OKAY;
1237 	}
1238 	
1239 	/** ensures, that boundchgs array can store at least num entries */
1240 	static
1241 	SCIP_RETCODE domchgEnsureBoundchgsSize(
1242 	   SCIP_DOMCHG*          domchg,             /**< domain change data structure */
1243 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1244 	   SCIP_SET*             set,                /**< global SCIP settings */
1245 	   int                   num                 /**< minimum number of entries to store */
1246 	   )
1247 	{
1248 	   assert(domchg != NULL);
1249 	   assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1250 	
1251 	   if( num > domchg->domchgdyn.boundchgssize )
1252 	   {
1253 	      int newsize;
1254 	
1255 	      newsize = SCIPsetCalcMemGrowSize(set, num);
1256 	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.boundchgs, domchg->domchgdyn.boundchgssize, newsize) );
1257 	      domchg->domchgdyn.boundchgssize = newsize;
1258 	   }
1259 	   assert(num <= domchg->domchgdyn.boundchgssize);
1260 	
1261 	   return SCIP_OKAY;
1262 	}
1263 	
1264 	/** ensures, that holechgs array can store at least num additional entries */
1265 	static
1266 	SCIP_RETCODE domchgEnsureHolechgsSize(
1267 	   SCIP_DOMCHG*          domchg,             /**< domain change data structure */
1268 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1269 	   SCIP_SET*             set,                /**< global SCIP settings */
1270 	   int                   num                 /**< minimum number of additional entries to store */
1271 	   )
1272 	{
1273 	   assert(domchg != NULL);
1274 	   assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1275 	
1276 	   if( num > domchg->domchgdyn.holechgssize )
1277 	   {
1278 	      int newsize;
1279 	
1280 	      newsize = SCIPsetCalcMemGrowSize(set, num);
1281 	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.holechgs, domchg->domchgdyn.holechgssize, newsize) );
1282 	      domchg->domchgdyn.holechgssize = newsize;
1283 	   }
1284 	   assert(num <= domchg->domchgdyn.holechgssize);
1285 	
1286 	   return SCIP_OKAY;
1287 	}
1288 	
1289 	/** applies domain change */
1290 	SCIP_RETCODE SCIPdomchgApply(
1291 	   SCIP_DOMCHG*          domchg,             /**< domain change to apply */
1292 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1293 	   SCIP_SET*             set,                /**< global SCIP settings */
1294 	   SCIP_STAT*            stat,               /**< problem statistics */
1295 	   SCIP_LP*              lp,                 /**< current LP data */
1296 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
1297 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
1298 	   int                   depth,              /**< depth in the tree, where the domain change takes place */
1299 	   SCIP_Bool*            cutoff              /**< pointer to store whether an infeasible domain change was detected */
1300 	   )
1301 	{
1302 	   int i;
1303 	
1304 	   assert(cutoff != NULL);
1305 	
1306 	   *cutoff = FALSE;
1307 	
1308 	   SCIPsetDebugMsg(set, "applying domain changes at %p in depth %d\n", (void*)domchg, depth);
1309 	
1310 	   if( domchg == NULL )
1311 	      return SCIP_OKAY;
1312 	
1313 	   /* apply bound changes */
1314 	   for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1315 	   {
1316 	      SCIP_CALL( SCIPboundchgApply(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1317 	            branchcand, eventqueue, depth, i, cutoff) );
1318 	      if( *cutoff )
1319 	         break;
1320 	   }
1321 	   SCIPsetDebugMsg(set, " -> %u bound changes (cutoff %u)\n", domchg->domchgbound.nboundchgs, *cutoff);
1322 	
1323 	   /* mark all bound changes after a cutoff redundant */
1324 	   for( ; i < (int)domchg->domchgbound.nboundchgs; ++i )
1325 	      domchg->domchgbound.boundchgs[i].redundant = TRUE;
1326 	
1327 	   /* apply holelist changes */
1328 	   if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1329 	   {
1330 	      for( i = 0; i < domchg->domchgboth.nholechgs; ++i )
1331 	         *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].newlist;
1332 	      SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1333 	   }
1334 	
1335 	   return SCIP_OKAY;
1336 	}
1337 	
1338 	/** undoes domain change */
1339 	SCIP_RETCODE SCIPdomchgUndo(
1340 	   SCIP_DOMCHG*          domchg,             /**< domain change to remove */
1341 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1342 	   SCIP_SET*             set,                /**< global SCIP settings */
1343 	   SCIP_STAT*            stat,               /**< problem statistics */
1344 	   SCIP_LP*              lp,                 /**< current LP data */
1345 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
1346 	   SCIP_EVENTQUEUE*      eventqueue          /**< event queue */
1347 	   )
1348 	{
1349 	   int i;
1350 	
1351 	   SCIPsetDebugMsg(set, "undoing domain changes at %p\n", (void*)domchg);
1352 	   if( domchg == NULL )
1353 	      return SCIP_OKAY;
1354 	
1355 	   /* undo holelist changes */
1356 	   if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1357 	   {
1358 	      for( i = domchg->domchgboth.nholechgs-1; i >= 0; --i )
1359 	         *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].oldlist;
1360 	      SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1361 	   }
1362 	
1363 	   /* undo bound changes */
1364 	   for( i = domchg->domchgbound.nboundchgs-1; i >= 0; --i )
1365 	   {
1366 	      SCIP_CALL( SCIPboundchgUndo(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp, branchcand, eventqueue) );
1367 	   }
1368 	   SCIPsetDebugMsg(set, " -> %u bound changes\n", domchg->domchgbound.nboundchgs);
1369 	
1370 	   return SCIP_OKAY;
1371 	}
1372 	
1373 	/** applies domain change to the global problem */
1374 	SCIP_RETCODE SCIPdomchgApplyGlobal(
1375 	   SCIP_DOMCHG*          domchg,             /**< domain change to apply */
1376 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1377 	   SCIP_SET*             set,                /**< global SCIP settings */
1378 	   SCIP_STAT*            stat,               /**< problem statistics */
1379 	   SCIP_LP*              lp,                 /**< current LP data */
1380 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
1381 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
1382 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
1383 	   SCIP_Bool*            cutoff              /**< pointer to store whether an infeasible domain change was detected */
1384 	   )
1385 	{
1386 	   int i;
1387 	
1388 	   assert(cutoff != NULL);
1389 	
1390 	   *cutoff = FALSE;
1391 	
1392 	   if( domchg == NULL )
1393 	      return SCIP_OKAY;
1394 	
1395 	   SCIPsetDebugMsg(set, "applying domain changes at %p to the global problem\n", (void*)domchg);
1396 	
1397 	   /* apply bound changes */
1398 	   for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1399 	   {
1400 	      SCIP_CALL( boundchgApplyGlobal(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1401 	            branchcand, eventqueue, cliquetable, cutoff) );
1402 	      if( *cutoff )
1403 	         break;
1404 	   }
1405 	   SCIPsetDebugMsg(set, " -> %u global bound changes\n", domchg->domchgbound.nboundchgs);
1406 	
1407 	   /**@todo globally apply holelist changes - how can this be done without confusing pointer updates? */
1408 	
1409 	   return SCIP_OKAY;
1410 	}
1411 	
1412 	/** adds bound change to domain changes */
1413 	SCIP_RETCODE SCIPdomchgAddBoundchg(
1414 	   SCIP_DOMCHG**         domchg,             /**< pointer to domain change data structure */
1415 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1416 	   SCIP_SET*             set,                /**< global SCIP settings */
1417 	   SCIP_VAR*             var,                /**< variable to change the bounds for */
1418 	   SCIP_Real             newbound,           /**< new value for bound */
1419 	   SCIP_BOUNDTYPE        boundtype,          /**< type of bound for var: lower or upper bound */
1420 	   SCIP_BOUNDCHGTYPE     boundchgtype,       /**< type of bound change: branching decision or inference */
1421 	   SCIP_Real             lpsolval,           /**< solval of variable in last LP on path to node, or SCIP_INVALID if unknown */
1422 	   SCIP_VAR*             infervar,           /**< variable that was changed (parent of var, or var itself), or NULL */
1423 	   SCIP_CONS*            infercons,          /**< constraint that deduced the bound change, or NULL */
1424 	   SCIP_PROP*            inferprop,          /**< propagator that deduced the bound change, or NULL */
1425 	   int                   inferinfo,          /**< user information for inference to help resolving the conflict */
1426 	   SCIP_BOUNDTYPE        inferboundtype      /**< type of bound for inference var: lower or upper bound */
1427 	   )
1428 	{
1429 	   SCIP_BOUNDCHG* boundchg;
1430 	
1431 	   assert(domchg != NULL);
1432 	   assert(var != NULL);
1433 	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
1434 	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
1435 	   assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, boundtype == SCIP_BOUNDTYPE_LOWER ? 1.0 : 0.0));
1436 	   assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
1437 	   assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
1438 	   assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
1439 	
1440 	   SCIPsetDebugMsg(set, "adding %s bound change <%s: %g> of variable <%s> to domain change at %p pointing to %p\n",
1441 	      boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
1442 	      newbound, var->name, (void*)domchg, (void*)*domchg);
1443 	
1444 	   /* if domain change data doesn't exist, create it;
1445 	    * if domain change is static, convert it into dynamic change
1446 	    */
1447 	   if( *domchg == NULL )
1448 	   {
1449 	      SCIP_CALL( domchgCreate(domchg, blkmem) );
1450 	   }
1451 	   else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1452 	   {
1453 	      SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1454 	   }
1455 	   assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1456 	
1457 	   /* get memory for additional bound change */
1458 	   SCIP_CALL( domchgEnsureBoundchgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nboundchgs+1) );
1459 	
1460 	   /* fill in the bound change data */
1461 	   boundchg = &(*domchg)->domchgdyn.boundchgs[(*domchg)->domchgdyn.nboundchgs];
1462 	   boundchg->var = var;
1463 	   switch( boundchgtype )
1464 	   {
1465 	   case SCIP_BOUNDCHGTYPE_BRANCHING:
1466 	      boundchg->data.branchingdata.lpsolval = lpsolval;
1467 	      break;
1468 	   case SCIP_BOUNDCHGTYPE_CONSINFER:
1469 	      assert(infercons != NULL);
1470 	      boundchg->data.inferencedata.var = infervar;
1471 	      boundchg->data.inferencedata.reason.cons = infercons;
1472 	      boundchg->data.inferencedata.info = inferinfo; 
1473 	      break;
1474 	   case SCIP_BOUNDCHGTYPE_PROPINFER:
1475 	      boundchg->data.inferencedata.var = infervar;
1476 	      boundchg->data.inferencedata.reason.prop = inferprop;
1477 	      boundchg->data.inferencedata.info = inferinfo; 
1478 	      break;
1479 	   default:
1480 	      SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
1481 	      return SCIP_INVALIDDATA;
1482 	   }
1483 	
1484 	   boundchg->newbound = newbound;
1485 	   boundchg->boundchgtype = boundchgtype; /*lint !e641*/
1486 	   boundchg->boundtype = boundtype; /*lint !e641*/
1487 	   boundchg->inferboundtype = inferboundtype; /*lint !e641*/
1488 	   boundchg->applied = FALSE;
1489 	   boundchg->redundant = FALSE;
1490 	   (*domchg)->domchgdyn.nboundchgs++;
1491 	
1492 	   /* capture branching and inference data associated with the bound changes */
1493 	   SCIP_CALL( boundchgCaptureData(boundchg) );
1494 	
1495 	#ifdef SCIP_DISABLED_CODE /* expensive debug check */
1496 	#ifdef SCIP_MORE_DEBUG
1497 	   {
1498 	      int i;
1499 	      for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1500 	         assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1501 	            || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1502 	   }
1503 	#endif
1504 	#endif
1505 	
1506 	   return SCIP_OKAY;
1507 	}
1508 	
1509 	/** adds hole change to domain changes */
1510 	SCIP_RETCODE SCIPdomchgAddHolechg(
1511 	   SCIP_DOMCHG**         domchg,             /**< pointer to domain change data structure */
1512 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1513 	   SCIP_SET*             set,                /**< global SCIP settings */
1514 	   SCIP_HOLELIST**       ptr,                /**< changed list pointer */
1515 	   SCIP_HOLELIST*        newlist,            /**< new value of list pointer */
1516 	   SCIP_HOLELIST*        oldlist             /**< old value of list pointer */
1517 	   )
1518 	{
1519 	   SCIP_HOLECHG* holechg;
1520 	
1521 	   assert(domchg != NULL);
1522 	   assert(ptr != NULL);
1523 	
1524 	   /* if domain change data doesn't exist, create it;
1525 	    * if domain change is static, convert it into dynamic change
1526 	    */
1527 	   if( *domchg == NULL )
1528 	   {
1529 	      SCIP_CALL( domchgCreate(domchg, blkmem) );
1530 	   }
1531 	   else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1532 	   {
1533 	      SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1534 	   }
1535 	   assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1536 	
1537 	   /* get memory for additional hole change */
1538 	   SCIP_CALL( domchgEnsureHolechgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nholechgs+1) );
1539 	
1540 	   /* fill in the hole change data */
1541 	   holechg = &(*domchg)->domchgdyn.holechgs[(*domchg)->domchgdyn.nholechgs];
1542 	   holechg->ptr = ptr;
1543 	   holechg->newlist = newlist;
1544 	   holechg->oldlist = oldlist;
1545 	   (*domchg)->domchgdyn.nholechgs++;
1546 	
1547 	   return SCIP_OKAY;
1548 	}
1549 	
1550 	
1551 	
1552 	
1553 	/*
1554 	 * methods for variables 
1555 	 */
1556 	
1557 	/** returns adjusted lower bound value, which is rounded for integral variable types */
1558 	static
1559 	SCIP_Real adjustedLb(
1560 	   SCIP_SET*             set,                /**< global SCIP settings */
1561 	   SCIP_VARTYPE          vartype,            /**< type of variable */
1562 	   SCIP_Real             lb                  /**< lower bound to adjust */
1563 	   )
1564 	{
1565 	   if( lb < 0.0 && SCIPsetIsInfinity(set, -lb) )
1566 	      return -SCIPsetInfinity(set);
1567 	   else if( lb > 0.0 && SCIPsetIsInfinity(set, lb) )
1568 	      return SCIPsetInfinity(set);
1569 	   else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1570 	      return SCIPsetFeasCeil(set, lb);
1571 	   else if( lb > 0.0 && lb < SCIPsetEpsilon(set) )
1572 	      return 0.0;
1573 	   else
1574 	      return lb;
1575 	}
1576 	
1577 	/** returns adjusted upper bound value, which is rounded for integral variable types */
1578 	static
1579 	SCIP_Real adjustedUb(
1580 	   SCIP_SET*             set,                /**< global SCIP settings */
1581 	   SCIP_VARTYPE          vartype,            /**< type of variable */
1582 	   SCIP_Real             ub                  /**< upper bound to adjust */
1583 	   )
1584 	{
1585 	   if( ub > 0.0 && SCIPsetIsInfinity(set, ub) )
1586 	      return SCIPsetInfinity(set);
1587 	   else if( ub < 0.0 && SCIPsetIsInfinity(set, -ub) )
1588 	      return -SCIPsetInfinity(set);
1589 	   else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1590 	      return SCIPsetFeasFloor(set, ub);
1591 	   else if( ub < 0.0 && ub > -SCIPsetEpsilon(set) )
1592 	      return 0.0;
1593 	   else
1594 	      return ub;
1595 	}
1596 	
1597 	/** removes (redundant) cliques, implications and variable bounds of variable from all other variables' implications and variable
1598 	 *  bounds arrays, and optionally removes them also from the variable itself
1599 	 */
1600 	SCIP_RETCODE SCIPvarRemoveCliquesImplicsVbs(
1601 	   SCIP_VAR*             var,                /**< problem variable */
1602 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1603 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
1604 	   SCIP_SET*             set,                /**< global SCIP settings */
1605 	   SCIP_Bool             irrelevantvar,      /**< has the variable become irrelevant? */
1606 	   SCIP_Bool             onlyredundant,      /**< should only the redundant implications and variable bounds be removed? */
1607 	   SCIP_Bool             removefromvar       /**< should the implications and variable bounds be removed from the var itself? */
1608 	   )
1609 	{
1610 	   SCIP_Real lb;
1611 	   SCIP_Real ub;
1612 	
1613 	   assert(var != NULL);
1614 	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
1615 	   assert(SCIPvarIsActive(var) || SCIPvarGetType(var) != SCIP_VARTYPE_BINARY);
1616 	
1617 	   lb = SCIPvarGetLbGlobal(var);
1618 	   ub = SCIPvarGetUbGlobal(var);
1619 	
1620 	   SCIPsetDebugMsg(set, "removing %s implications and vbounds of %s<%s>[%g,%g]\n",
1621 	      onlyredundant ? "redundant" : "all", irrelevantvar ? "irrelevant " : "", SCIPvarGetName(var), lb, ub);
1622 	
1623 	   /* remove implications of (fixed) binary variable */
1624 	   if( var->implics != NULL && (!onlyredundant || lb > 0.5 || ub < 0.5) )
1625 	   {
1626 	      SCIP_Bool varfixing;
1627 	
1628 	      assert(SCIPvarIsBinary(var));
1629 	
1630 	      varfixing = FALSE;
1631 	      do
1632 	      {
1633 	         SCIP_VAR** implvars;
1634 	         SCIP_BOUNDTYPE* impltypes;
1635 	         int nimpls;
1636 	         int i;
1637 	
1638 	         nimpls = SCIPimplicsGetNImpls(var->implics, varfixing);
1639 	         implvars = SCIPimplicsGetVars(var->implics, varfixing);
1640 	         impltypes = SCIPimplicsGetTypes(var->implics, varfixing);
1641 	
1642 	         for( i = 0; i < nimpls; i++ )
1643 	         {
1644 	            SCIP_VAR* implvar;
1645 	            SCIP_BOUNDTYPE impltype;
1646 	
1647 	            implvar = implvars[i];
1648 	            impltype = impltypes[i];
1649 	            assert(implvar != var);
1650 	
1651 	            /* remove for all implications z == 0 / 1  ==>  x <= p / x >= p (x not binary)
1652 	             * the following variable bound from x's variable bounds 
1653 	             *   x <= b*z+d (z in vubs of x)            , for z == 0 / 1  ==>  x <= p
1654 	             *   x >= b*z+d (z in vlbs of x)            , for z == 0 / 1  ==>  x >= p
1655 	             */
1656 	            if( impltype == SCIP_BOUNDTYPE_UPPER )
1657 	            {
1658 	               if( implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1659 	               {
1660 	                  SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u  ==>  <%s> <= %g\n",
1661 	                     SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
1662 	                     SCIPimplicsGetBounds(var->implics, varfixing)[i]);
1663 	                  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, varfixing) );
1664 	                  implvar->closestvblpcount = -1;
1665 	                  var->closestvblpcount = -1;
1666 	               }
1667 	            }
1668 	            else
1669 	            {
1670 	               if( implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1671 	               {
1672 	                  SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u  ==>  <%s> >= %g\n",
1673 	                     SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
1674 	                     SCIPimplicsGetBounds(var->implics, varfixing)[i]);
1675 	                  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, !varfixing) );
1676 	                  implvar->closestvblpcount = -1;
1677 	                  var->closestvblpcount = -1;
1678 	               }
1679 	            }
1680 	         }
1681 	         varfixing = !varfixing;
1682 	      }
1683 	      while( varfixing == TRUE );
1684 	
1685 	      if( removefromvar )
1686 	      {
1687 	         /* free the implications data structures */
1688 	         SCIPimplicsFree(&var->implics, blkmem);
1689 	      }
1690 	   }
1691 	
1692 	   /* remove the (redundant) variable lower bounds */
1693 	   if( var->vlbs != NULL )
1694 	   {
1695 	      SCIP_VAR** vars;
1696 	      SCIP_Real* coefs;
1697 	      SCIP_Real* constants;
1698 	      int nvbds;
1699 	      int newnvbds;
1700 	      int i;
1701 	
1702 	      nvbds = SCIPvboundsGetNVbds(var->vlbs);
1703 	      vars = SCIPvboundsGetVars(var->vlbs);
1704 	      coefs = SCIPvboundsGetCoefs(var->vlbs);
1705 	      constants = SCIPvboundsGetConstants(var->vlbs);
1706 	
1707 	      /* remove for all variable bounds x >= b*z+d the following implication from z's implications 
1708 	       *   z == ub  ==>  x >= b*ub + d           , if b > 0
1709 	       *   z == lb  ==>  x >= b*lb + d           , if b < 0
1710 	       */
1711 	      newnvbds = 0;
1712 	      for( i = 0; i < nvbds; i++ )
1713 	      {
1714 	         SCIP_VAR* implvar;
1715 	         SCIP_Real coef;
1716 	
1717 	         assert(newnvbds <= i);
1718 	
1719 	         implvar = vars[i];
1720 	         assert(implvar != NULL);
1721 	
1722 	         coef = coefs[i];
1723 	         assert(!SCIPsetIsZero(set, coef));
1724 	
1725 	         /* check, if we want to remove the variable bound */
1726 	         if( onlyredundant )
1727 	         {
1728 	            SCIP_Real vbound;
1729 	
1730 	            vbound = MAX(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i];  /*lint !e666*/
1731 	            if( SCIPsetIsFeasGT(set, vbound, lb) )
1732 	            {
1733 	               /* the variable bound is not redundant: keep it */
1734 	               if( removefromvar )
1735 	               {
1736 	                  if( newnvbds < i )
1737 	                  {
1738 	                     vars[newnvbds] = implvar;
1739 	                     coefs[newnvbds] = coef;
1740 	                     constants[newnvbds] = constants[i];
1741 	                  }
1742 	                  newnvbds++;
1743 	               }
1744 	               continue;
1745 	            }
1746 	         }
1747 	
1748 	         /* remove the corresponding implication */
1749 	         if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1750 	         {
1751 	            SCIPsetDebugMsg(set, "deleting implication: <%s> == %d  ==>  <%s> >= %g\n",
1752 	               SCIPvarGetName(implvar), (coef > 0.0), SCIPvarGetName(var), MAX(coef, 0.0) + constants[i]);
1753 	            SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef > 0.0), var, SCIP_BOUNDTYPE_LOWER) );
1754 	         }
1755 	         if( coef > 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1756 	         {
1757 	            SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
1758 	               SCIPvarGetName(implvar), SCIPvarGetName(var));
1759 	            SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, FALSE) );
1760 	            implvar->closestvblpcount = -1;
1761 	            var->closestvblpcount = -1;
1762 	         }
1763 	         else if( coef < 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1764 	         {
1765 	            SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
1766 	               SCIPvarGetName(implvar), SCIPvarGetName(var));
1767 	            SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, TRUE) );
1768 	            implvar->closestvblpcount = -1;
1769 	            var->closestvblpcount = -1;
1770 	         }
1771 	      }
1772 	
1773 	      if( removefromvar )
1774 	      {
1775 	         /* update the number of variable bounds */
1776 	         SCIPvboundsShrink(&var->vlbs, blkmem, newnvbds);
1777 	         var->closestvblpcount = -1;
1778 	      }
1779 	   }
1780 	
1781 	   /**@todo in general, variable bounds like x >= b*z + d corresponding to an implication like z = ub ==> x >= b*ub + d 
1782 	    *       might be missing because we only add variable bounds with reasonably small value of b. thus, we currently 
1783 	    *       cannot remove such variables x from z's implications.
1784 	    */
1785 	
1786 	   /* remove the (redundant) variable upper bounds */
1787 	   if( var->vubs != NULL )
1788 	   {
1789 	      SCIP_VAR** vars;
1790 	      SCIP_Real* coefs;
1791 	      SCIP_Real* constants;
1792 	      int nvbds;
1793 	      int newnvbds;
1794 	      int i;
1795 	
1796 	      nvbds = SCIPvboundsGetNVbds(var->vubs);
1797 	      vars = SCIPvboundsGetVars(var->vubs);
1798 	      coefs = SCIPvboundsGetCoefs(var->vubs);
1799 	      constants = SCIPvboundsGetConstants(var->vubs);
1800 	
1801 	      /* remove for all variable bounds x <= b*z+d the following implication from z's implications 
1802 	       *   z == lb  ==>  x <= b*lb + d           , if b > 0
1803 	       *   z == ub  ==>  x <= b*ub + d           , if b < 0
1804 	       */
1805 	      newnvbds = 0;
1806 	      for( i = 0; i < nvbds; i++ )
1807 	      {
1808 	         SCIP_VAR* implvar;
1809 	         SCIP_Real coef;
1810 	
1811 	         assert(newnvbds <= i);
1812 	
1813 	         implvar = vars[i];
1814 	         assert(implvar != NULL);
1815 	
1816 	         coef = coefs[i];
1817 	         assert(!SCIPsetIsZero(set, coef));
1818 	
1819 	         /* check, if we want to remove the variable bound */
1820 	         if( onlyredundant )
1821 	         {
1822 	            SCIP_Real vbound;
1823 	
1824 	            vbound = MIN(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i];  /*lint !e666*/
1825 	            if( SCIPsetIsFeasLT(set, vbound, ub) )
1826 	            {
1827 	               /* the variable bound is not redundant: keep it */
1828 	               if( removefromvar )
1829 	               {
1830 	                  if( newnvbds < i )
1831 	                  {
1832 	                     vars[newnvbds] = implvar;
1833 	                     coefs[newnvbds] = coefs[i];
1834 	                     constants[newnvbds] = constants[i];
1835 	                  }
1836 	                  newnvbds++;
1837 	               }
1838 	               continue;
1839 	            }
1840 	         }
1841 	
1842 	         /* remove the corresponding implication */
1843 	         if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1844 	         {
1845 	            SCIPsetDebugMsg(set, "deleting implication: <%s> == %d  ==>  <%s> <= %g\n",
1846 	               SCIPvarGetName(implvar), (coef < 0.0), SCIPvarGetName(var), MIN(coef, 0.0) + constants[i]);
1847 	            SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef < 0.0), var, SCIP_BOUNDTYPE_UPPER) );
1848 	         }
1849 	         if( coef < 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1850 	         {
1851 	            SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
1852 	               SCIPvarGetName(implvar), SCIPvarGetName(var));
1853 	            SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, TRUE) );
1854 	            implvar->closestvblpcount = -1;
1855 	            var->closestvblpcount = -1;
1856 	         }
1857 	         else if( coef > 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1858 	         {
1859 	            SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
1860 	               SCIPvarGetName(implvar), SCIPvarGetName(var));
1861 	            SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, FALSE) );
1862 	            implvar->closestvblpcount = -1;
1863 	            var->closestvblpcount = -1;
1864 	         }
1865 	      }
1866 	
1867 	      if( removefromvar )
1868 	      {
1869 	         /* update the number of variable bounds */
1870 	         SCIPvboundsShrink(&var->vubs, blkmem, newnvbds);
1871 	         var->closestvblpcount = -1;
1872 	      }
1873 	   }
1874 	
1875 	   /* remove the variable from all cliques */
1876 	   if( SCIPvarIsBinary(var) )
1877 	   {
1878 	      SCIPcliquelistRemoveFromCliques(var->cliquelist, cliquetable, var, irrelevantvar);
1879 	      SCIPcliquelistFree(&var->cliquelist, blkmem);
1880 	   }
1881 	
1882 	   /**@todo variable bounds like x <= b*z + d with z general integer are not removed from x's vbd arrays, because
1883 	    *       z has no link (like in the binary case) to x
1884 	    */
1885 	
1886 	   return SCIP_OKAY;
1887 	}
1888 	
1889 	/** sets the variable name */
1890 	static
1891 	SCIP_RETCODE varSetName(
1892 	   SCIP_VAR*             var,                /**< problem variable */
1893 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1894 	   SCIP_STAT*            stat,               /**< problem statistics, or NULL */
1895 	   const char*           name                /**< name of variable, or NULL for automatic name creation */
1896 	   )
1897 	{
1898 	   assert(blkmem != NULL);
1899 	   assert(var != NULL);
1900 	
1901 	   if( name == NULL )
1902 	   {
1903 	      char s[SCIP_MAXSTRLEN];
1904 	
1905 	      assert(stat != NULL);
1906 	
1907 	      (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "_var%d_", stat->nvaridx);
1908 	      SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, s, strlen(s)+1) );
1909 	   }
1910 	   else
1911 	   {
1912 	      SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, name, strlen(name)+1) );
1913 	   }
1914 	
1915 	   return SCIP_OKAY;
1916 	}
1917 	
1918 	
1919 	/** creates variable; if variable is of integral type, fractional bounds are automatically rounded; an integer variable
1920 	 *  with bounds zero and one is automatically converted into a binary variable
1921 	 */
1922 	static
1923 	SCIP_RETCODE varCreate(
1924 	   SCIP_VAR**            var,                /**< pointer to variable data */
1925 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1926 	   SCIP_SET*             set,                /**< global SCIP settings */
1927 	   SCIP_STAT*            stat,               /**< problem statistics */
1928 	   const char*           name,               /**< name of variable, or NULL for automatic name creation */
1929 	   SCIP_Real             lb,                 /**< lower bound of variable */
1930 	   SCIP_Real             ub,                 /**< upper bound of variable */
1931 	   SCIP_Real             obj,                /**< objective function value */
1932 	   SCIP_VARTYPE          vartype,            /**< type of variable */
1933 	   SCIP_Bool             initial,            /**< should var's column be present in the initial root LP? */
1934 	   SCIP_Bool             removable,          /**< is var's column removable from the LP (due to aging or cleanup)? */
1935 	   SCIP_DECL_VARCOPY     ((*varcopy)),       /**< copies variable data if wanted to subscip, or NULL */
1936 	   SCIP_DECL_VARDELORIG  ((*vardelorig)),    /**< frees user data of original variable, or NULL */
1937 	   SCIP_DECL_VARTRANS    ((*vartrans)),      /**< creates transformed user data by transforming original user data, or NULL */
1938 	   SCIP_DECL_VARDELTRANS ((*vardeltrans)),   /**< frees user data of transformed variable, or NULL */
1939 	   SCIP_VARDATA*         vardata             /**< user data for this specific variable */
1940 	   )
1941 	{
1942 	   int i;
1943 	
1944 	   assert(var != NULL);
1945 	   assert(blkmem != NULL);
1946 	   assert(stat != NULL);
1947 	
1948 	   /* adjust bounds of variable */
1949 	   lb = adjustedLb(set, vartype, lb);
1950 	   ub = adjustedUb(set, vartype, ub);
1951 	
1952 	   /* convert [0,1]-integers into binary variables and check that binary variables have correct bounds */
1953 	   if( (SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0))
1954 	      && (SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0)) )
1955 	   {
1956 	      if( vartype == SCIP_VARTYPE_INTEGER )
1957 	         vartype = SCIP_VARTYPE_BINARY;
1958 	   }
1959 	   else
1960 	   {
1961 	      if( vartype == SCIP_VARTYPE_BINARY )
1962 	      {
1963 	         SCIPerrorMessage("invalid bounds [%.2g,%.2g] for binary variable <%s>\n", lb, ub, name);
1964 	         return SCIP_INVALIDDATA;
1965 	      }
1966 	   }
1967 	
1968 	   assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0));
1969 	   assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0));
1970 	
1971 	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, var) );
1972 	
1973 	   /* set variable's name */
1974 	   SCIP_CALL( varSetName(*var, blkmem, stat, name) );
1975 	
1976 	#ifndef NDEBUG
1977 	   (*var)->scip = set->scip;
1978 	#endif
1979 	   (*var)->obj = obj;
1980 	   (*var)->unchangedobj = obj;
1981 	   (*var)->branchfactor = 1.0;
1982 	   (*var)->rootsol = 0.0;
1983 	   (*var)->bestrootsol = 0.0;
1984 	   (*var)->bestrootredcost = 0.0;
1985 	   (*var)->bestrootlpobjval = SCIP_INVALID;
1986 	   (*var)->relaxsol = 0.0;
1987 	   (*var)->nlpsol = 0.0;
1988 	   (*var)->primsolavg = 0.5 * (lb + ub);
1989 	   (*var)->conflictlb = SCIP_REAL_MIN;
1990 	   (*var)->conflictub = SCIP_REAL_MAX;
1991 	   (*var)->conflictrelaxedlb = (*var)->conflictlb;
1992 	   (*var)->conflictrelaxedub = (*var)->conflictub;
1993 	   (*var)->lazylb = -SCIPsetInfinity(set);
1994 	   (*var)->lazyub = SCIPsetInfinity(set);
1995 	   (*var)->glbdom.holelist = NULL;
1996 	   (*var)->glbdom.lb = lb;
1997 	   (*var)->glbdom.ub = ub;
1998 	   (*var)->locdom.holelist = NULL;
1999 	   (*var)->locdom.lb = lb;
2000 	   (*var)->locdom.ub = ub;
2001 	   (*var)->varcopy = varcopy;
2002 	   (*var)->vardelorig = vardelorig;
2003 	   (*var)->vartrans = vartrans;
2004 	   (*var)->vardeltrans = vardeltrans;
2005 	   (*var)->vardata = vardata;
2006 	   (*var)->parentvars = NULL;
2007 	   (*var)->negatedvar = NULL;
2008 	   (*var)->vlbs = NULL;
2009 	   (*var)->vubs = NULL;
2010 	   (*var)->implics = NULL;
2011 	   (*var)->cliquelist = NULL;
2012 	   (*var)->eventfilter = NULL;
2013 	   (*var)->lbchginfos = NULL;
2014 	   (*var)->ubchginfos = NULL;
2015 	   (*var)->index = stat->nvaridx;
2016 	   (*var)->probindex = -1;
2017 	   (*var)->pseudocandindex = -1;
2018 	   (*var)->eventqueueindexobj = -1;
2019 	   (*var)->eventqueueindexlb = -1;
2020 	   (*var)->eventqueueindexub = -1;
2021 	   (*var)->parentvarssize = 0;
2022 	   (*var)->nparentvars = 0;
2023 	   (*var)->nuses = 0;
2024 	   (*var)->branchpriority = 0;
2025 	   (*var)->branchdirection = SCIP_BRANCHDIR_AUTO; /*lint !e641*/
2026 	   (*var)->lbchginfossize = 0;
2027 	   (*var)->nlbchginfos = 0;
2028 	   (*var)->ubchginfossize = 0;
2029 	   (*var)->nubchginfos = 0;
2030 	   (*var)->conflictlbcount = 0;
2031 	   (*var)->conflictubcount = 0;
2032 	   (*var)->closestvlbidx = -1;
2033 	   (*var)->closestvubidx = -1;
2034 	   (*var)->closestvblpcount = -1;
2035 	   (*var)->initial = initial;
2036 	   (*var)->removable = removable;
2037 	   (*var)->deleted = FALSE;
2038 	   (*var)->donotaggr = FALSE;
2039 	   (*var)->donotmultaggr = FALSE;
2040 	   (*var)->vartype = vartype; /*lint !e641*/
2041 	   (*var)->pseudocostflag = FALSE;
2042 	   (*var)->eventqueueimpl = FALSE;
2043 	   (*var)->deletable = FALSE;
2044 	   (*var)->delglobalstructs = FALSE;
2045 	   (*var)->relaxationonly = FALSE;
2046 	
2047 	   for( i = 0; i < NLOCKTYPES; i++ )
2048 	   {
2049 	      (*var)->nlocksdown[i] = 0;
2050 	      (*var)->nlocksup[i] = 0;
2051 	   }
2052 	
2053 	   stat->nvaridx++;
2054 	
2055 	   /* create branching and inference history entries */
2056 	   SCIP_CALL( SCIPhistoryCreate(&(*var)->history, blkmem) );
2057 	   SCIP_CALL( SCIPhistoryCreate(&(*var)->historycrun, blkmem) );
2058 	
2059 	   /* the value based history is only created on demand */
2060 	   (*var)->valuehistory = NULL;
2061 	
2062 	   return SCIP_OKAY;
2063 	}
2064 	
2065 	/** creates and captures an original problem variable; an integer variable with bounds
2066 	 *  zero and one is automatically converted into a binary variable
2067 	 */
2068 	SCIP_RETCODE SCIPvarCreateOriginal(
2069 	   SCIP_VAR**            var,                /**< pointer to variable data */
2070 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2071 	   SCIP_SET*             set,                /**< global SCIP settings */
2072 	   SCIP_STAT*            stat,               /**< problem statistics */
2073 	   const char*           name,               /**< name of variable, or NULL for automatic name creation */
2074 	   SCIP_Real             lb,                 /**< lower bound of variable */
2075 	   SCIP_Real             ub,                 /**< upper bound of variable */
2076 	   SCIP_Real             obj,                /**< objective function value */
2077 	   SCIP_VARTYPE          vartype,            /**< type of variable */
2078 	   SCIP_Bool             initial,            /**< should var's column be present in the initial root LP? */
2079 	   SCIP_Bool             removable,          /**< is var's column removable from the LP (due to aging or cleanup)? */
2080 	   SCIP_DECL_VARDELORIG  ((*vardelorig)),    /**< frees user data of original variable, or NULL */
2081 	   SCIP_DECL_VARTRANS    ((*vartrans)),      /**< creates transformed user data by transforming original user data, or NULL */
2082 	   SCIP_DECL_VARDELTRANS ((*vardeltrans)),   /**< frees user data of transformed variable, or NULL */
2083 	   SCIP_DECL_VARCOPY     ((*varcopy)),       /**< copies variable data if wanted to subscip, or NULL */
2084 	   SCIP_VARDATA*         vardata             /**< user data for this specific variable */
2085 	   )
2086 	{
2087 	   assert(var != NULL);
2088 	   assert(blkmem != NULL);
2089 	   assert(stat != NULL);
2090 	
2091 	   /* create variable */
2092 	   SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2093 	         varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2094 	
2095 	   /* set variable status and data */
2096 	   (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2097 	   (*var)->data.original.origdom.holelist = NULL;
2098 	   (*var)->data.original.origdom.lb = lb;
2099 	   (*var)->data.original.origdom.ub = ub;
2100 	   (*var)->data.original.transvar = NULL;
2101 	
2102 	   /* capture variable */
2103 	   SCIPvarCapture(*var);
2104 	
2105 	   return SCIP_OKAY;
2106 	}
2107 	
2108 	/** creates and captures a loose variable belonging to the transformed problem; an integer variable with bounds
2109 	 *  zero and one is automatically converted into a binary variable
2110 	 */
2111 	SCIP_RETCODE SCIPvarCreateTransformed(
2112 	   SCIP_VAR**            var,                /**< pointer to variable data */
2113 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2114 	   SCIP_SET*             set,                /**< global SCIP settings */
2115 	   SCIP_STAT*            stat,               /**< problem statistics */
2116 	   const char*           name,               /**< name of variable, or NULL for automatic name creation */
2117 	   SCIP_Real             lb,                 /**< lower bound of variable */
2118 	   SCIP_Real             ub,                 /**< upper bound of variable */
2119 	   SCIP_Real             obj,                /**< objective function value */
2120 	   SCIP_VARTYPE          vartype,            /**< type of variable */
2121 	   SCIP_Bool             initial,            /**< should var's column be present in the initial root LP? */
2122 	   SCIP_Bool             removable,          /**< is var's column removable from the LP (due to aging or cleanup)? */
2123 	   SCIP_DECL_VARDELORIG  ((*vardelorig)),    /**< frees user data of original variable, or NULL */
2124 	   SCIP_DECL_VARTRANS    ((*vartrans)),      /**< creates transformed user data by transforming original user data, or NULL */
2125 	   SCIP_DECL_VARDELTRANS ((*vardeltrans)),   /**< frees user data of transformed variable, or NULL */
2126 	   SCIP_DECL_VARCOPY     ((*varcopy)),       /**< copies variable data if wanted to subscip, or NULL */
2127 	   SCIP_VARDATA*         vardata             /**< user data for this specific variable */
2128 	   )
2129 	{
2130 	   assert(var != NULL);
2131 	   assert(blkmem != NULL);
2132 	
2133 	   /* create variable */
2134 	   SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2135 	         varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2136 	
2137 	   /* create event filter for transformed variable */
2138 	   SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2139 	
2140 	   /* set variable status and data */
2141 	   (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2142 	
2143 	   /* capture variable */
2144 	   SCIPvarCapture(*var);
2145 	
2146 	   return SCIP_OKAY;   
2147 	}
2148 	
2149 	/** copies and captures a variable from source to target SCIP; an integer variable with bounds zero and one is
2150 	 *  automatically converted into a binary variable; in case the variable data cannot be copied the variable is not
2151 	 *  copied at all
2152 	 */
2153 	SCIP_RETCODE SCIPvarCopy(
2154 	   SCIP_VAR**            var,                /**< pointer to store the target variable */
2155 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2156 	   SCIP_SET*             set,                /**< global SCIP settings */
2157 	   SCIP_STAT*            stat,               /**< problem statistics */
2158 	   SCIP*                 sourcescip,         /**< source SCIP data structure */
2159 	   SCIP_VAR*             sourcevar,          /**< source variable */
2160 	   SCIP_HASHMAP*         varmap,             /**< a hashmap to store the mapping of source variables corresponding
2161 	                                              *   target variables */
2162 	   SCIP_HASHMAP*         consmap,            /**< a hashmap to store the mapping of source constraints to the corresponding
2163 	                                              *   target constraints */
2164 	   SCIP_Bool             global              /**< should global or local bounds be used? */
2165 	   )
2166 	{
2167 	   SCIP_VARDATA* targetdata;
2168 	   SCIP_RESULT result;
2169 	   SCIP_Real lb;
2170 	   SCIP_Real ub;
2171 	
2172 	   assert(set != NULL);
2173 	   assert(blkmem != NULL);
2174 	   assert(stat != NULL);
2175 	   assert(sourcescip != NULL);
2176 	   assert(sourcevar != NULL);
2177 	   assert(var != NULL);
2178 	   assert(set->stage == SCIP_STAGE_PROBLEM);
2179 	   assert(varmap != NULL);
2180 	   assert(consmap != NULL);
2181 	
2182 	   /** @todo copy hole lists */
2183 	   assert(global || SCIPvarGetHolelistLocal(sourcevar) == NULL);
2184 	   assert(!global || SCIPvarGetHolelistGlobal(sourcevar) == NULL);
2185 	
2186 	   result = SCIP_DIDNOTRUN;
2187 	   targetdata = NULL;
2188 	
2189 	   if( SCIPvarGetStatus(sourcevar) == SCIP_VARSTATUS_ORIGINAL )
2190 	   {
2191 	      lb = SCIPvarGetLbOriginal(sourcevar);
2192 	      ub = SCIPvarGetUbOriginal(sourcevar);
2193 	   }
2194 	   else
2195 	   {
2196 	      lb = global ? SCIPvarGetLbGlobal(sourcevar) : SCIPvarGetLbLocal(sourcevar);
2197 	      ub = global ? SCIPvarGetUbGlobal(sourcevar) : SCIPvarGetUbLocal(sourcevar);
2198 	   }
2199 	
2200 	   /* creates and captures the variable in the target SCIP and initialize callback methods and variable data to NULL */
2201 	   SCIP_CALL( SCIPvarCreateOriginal(var, blkmem, set, stat, SCIPvarGetName(sourcevar), 
2202 	         lb, ub, SCIPvarGetObj(sourcevar), SCIPvarGetType(sourcevar),
2203 	         SCIPvarIsInitial(sourcevar), SCIPvarIsRemovable(sourcevar), 
2204 	         NULL, NULL, NULL, NULL, NULL) );
2205 	   assert(*var != NULL);
2206 	
2207 	   /* directly copy donot(mult)aggr flag */
2208 	   (*var)->donotaggr = sourcevar->donotaggr;
2209 	   (*var)->donotmultaggr = sourcevar->donotmultaggr;
2210 	
2211 	   /* insert variable into mapping between source SCIP and the target SCIP */
2212 	   assert(!SCIPhashmapExists(varmap, sourcevar));
2213 	   SCIP_CALL( SCIPhashmapInsert(varmap, sourcevar, *var) );
2214 	
2215 	   /* in case there exists variable data and the variable data copy callback, try to copy variable data */
2216 	   if( sourcevar->vardata != NULL && sourcevar->varcopy != NULL )
2217 	   {
2218 	      SCIP_CALL( sourcevar->varcopy(set->scip, sourcescip, sourcevar, sourcevar->vardata, 
2219 	            varmap, consmap, (*var), &targetdata, &result) );
2220 	
2221 	      /* evaluate result */
2222 	      if( result != SCIP_DIDNOTRUN && result != SCIP_SUCCESS )
2223 	      {
2224 	         SCIPerrorMessage("variable data copying method returned invalid result <%d>\n", result);
2225 	         return SCIP_INVALIDRESULT;
2226 	      }
2227 	
2228 	      assert(targetdata == NULL || result == SCIP_SUCCESS);
2229 	
2230 	      /* if copying was successful, add the created variable data to the variable as well as all callback methods */
2231 	      if( result == SCIP_SUCCESS )
2232 	      {
2233 	         (*var)->varcopy = sourcevar->varcopy;
2234 	         (*var)->vardelorig = sourcevar->vardelorig;
2235 	         (*var)->vartrans = sourcevar->vartrans;
2236 	         (*var)->vardeltrans = sourcevar->vardeltrans;
2237 	         (*var)->vardata = targetdata;
2238 	      }
2239 	   }
2240 	
2241 	   /* we initialize histories of the variables by copying the source variable-information */
2242 	   if( set->history_allowtransfer )
2243 	   {
2244 	      SCIPvarMergeHistories((*var), sourcevar, stat);
2245 	   }
2246 	
2247 	   /* in case the copying was successfully, add the created variable data to the variable as well as all callback
2248 	    * methods 
2249 	    */
2250 	   if( result == SCIP_SUCCESS )
2251 	   {
2252 	      (*var)->varcopy = sourcevar->varcopy;
2253 	      (*var)->vardelorig = sourcevar->vardelorig;
2254 	      (*var)->vartrans = sourcevar->vartrans;
2255 	      (*var)->vardeltrans = sourcevar->vardeltrans;
2256 	      (*var)->vardata = targetdata;
2257 	   }
2258 	
2259 	   SCIPsetDebugMsg(set, "created copy <%s> of variable <%s>\n", SCIPvarGetName(*var), SCIPvarGetName(sourcevar));
2260 	
2261 	   return SCIP_OKAY;
2262 	}
2263 	
2264 	/** parse given string for a SCIP_Real bound */
2265 	static
2266 	SCIP_RETCODE parseValue(
2267 	   SCIP_SET*             set,                /**< global SCIP settings */
2268 	   const char*           str,                /**< string to parse */
2269 	   SCIP_Real*            value,              /**< pointer to store the parsed value */
2270 	   char**                endptr              /**< pointer to store the final string position if successfully parsed */
2271 	   )
2272 	{
2273 	   /* first check for infinity value */
2274 	   if( strncmp(str, "+inf", 4) == 0 )
2275 	   {
2276 	      *value = SCIPsetInfinity(set);
2277 	      (*endptr) = (char*)str + 4;
2278 	   }
2279 	   else if( strncmp(str, "-inf", 4) == 0 )
2280 	   {
2281 	      *value = -SCIPsetInfinity(set);
2282 	      (*endptr) = (char*)str + 4;
2283 	   }
2284 	   else
2285 	   {
2286 	      if( !SCIPstrToRealValue(str, value, endptr) )
2287 	      {
2288 	         SCIPerrorMessage("expected value: %s.\n", str);
2289 	         return SCIP_READERROR;
2290 	      }
2291 	   }
2292 	
2293 	   return SCIP_OKAY;
2294 	}
2295 	
2296 	/** parse the characters as bounds */
2297 	static
2298 	SCIP_RETCODE parseBounds(
2299 	   SCIP_SET*             set,                /**< global SCIP settings */
2300 	   const char*           str,                /**< string to parse */
2301 	   char*                 type,               /**< bound type (global, local, or lazy) */
2302 	   SCIP_Real*            lb,                 /**< pointer to store the lower bound */
2303 	   SCIP_Real*            ub,                 /**< pointer to store the upper bound */
2304 	   char**                endptr              /**< pointer to store the final string position if successfully parsed (or NULL if an error occured) */
2305 	   )
2306 	{
2307 	   char token[SCIP_MAXSTRLEN];
2308 	   char* tmpend;
2309 	
2310 	   SCIPsetDebugMsg(set, "parsing bounds: '%s'\n", str);
2311 	
2312 	   /* get bound type */
2313 	   SCIPstrCopySection(str, ' ', ' ', type, SCIP_MAXSTRLEN, endptr);
2314 	   if ( strncmp(type, "original", 8) != 0 && strncmp(type, "global", 6) != 0 && strncmp(type, "local", 5) != 0 && strncmp(type, "lazy", 4) != 0 )
2315 	   {
2316 	      SCIPsetDebugMsg(set, "unkown bound type <%s>\n", type);
2317 	      *endptr = NULL;
2318 	      return SCIP_OKAY;
2319 	   }
2320 	
2321 	   SCIPsetDebugMsg(set, "parsed bound type <%s>\n", type);
2322 	
2323 	   /* get lower bound */
2324 	   SCIPstrCopySection(str, '[', ',', token, SCIP_MAXSTRLEN, endptr);
2325 	   str = *endptr;
2326 	   SCIP_CALL( parseValue(set, token, lb, &tmpend) );
2327 	
2328 	   /* get upper bound */
2329 	   SCIP_CALL( parseValue(set, str, ub, endptr) );
2330 	
2331 	   SCIPsetDebugMsg(set, "parsed bounds: [%g,%g]\n", *lb, *ub);
2332 	
2333 	   /* skip end of bounds */
2334 	   while ( **endptr != '\0' && (**endptr == ']' || **endptr == ',') )
2335 	      ++(*endptr);
2336 	
2337 	   return SCIP_OKAY;
2338 	}
2339 	
2340 	/** parses a given string for a variable informations */
2341 	static
2342 	SCIP_RETCODE varParse(
2343 	   SCIP_SET*             set,                /**< global SCIP settings */
2344 	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
2345 	   const char*           str,                /**< string to parse */
2346 	   char*                 name,               /**< pointer to store the variable name */
2347 	   SCIP_Real*            lb,                 /**< pointer to store the lower bound */
2348 	   SCIP_Real*            ub,                 /**< pointer to store the upper bound */
2349 	   SCIP_Real*            obj,                /**< pointer to store the objective coefficient */
2350 	   SCIP_VARTYPE*         vartype,            /**< pointer to store the variable type */
2351 	   SCIP_Real*            lazylb,             /**< pointer to store if the lower bound is lazy */
2352 	   SCIP_Real*            lazyub,             /**< pointer to store if the upper bound is lazy */
2353 	   SCIP_Bool             local,              /**< should the local bound be applied */
2354 	   char**                endptr,             /**< pointer to store the final string position if successfully */
2355 	   SCIP_Bool*            success             /**< pointer store if the paring process was successful */
2356 	   )
2357 	{
2358 	   SCIP_Real parsedlb;
2359 	   SCIP_Real parsedub;
2360 	   char token[SCIP_MAXSTRLEN];
2361 	   char* strptr;
2362 	   int i;
2363 	
2364 	   assert(lb != NULL);
2365 	   assert(ub != NULL);
2366 	   assert(obj != NULL);
2367 	   assert(vartype != NULL);
2368 	   assert(lazylb != NULL);
2369 	   assert(lazyub != NULL);
2370 	   assert(success != NULL);
2371 	
2372 	   (*success) = TRUE;
2373 	
2374 	   /* copy variable type */
2375 	   SCIPstrCopySection(str, '[', ']', token, SCIP_MAXSTRLEN, endptr);
2376 	   assert(str != *endptr);
2377 	   SCIPsetDebugMsg(set, "parsed variable type <%s>\n", token);
2378 	
2379 	   /* get variable type */
2380 	   if( strncmp(token, "binary", 3) == 0 )
2381 	      (*vartype) = SCIP_VARTYPE_BINARY;
2382 	   else if( strncmp(token, "integer", 3) == 0 )
2383 	      (*vartype) = SCIP_VARTYPE_INTEGER;
2384 	   else if( strncmp(token, "implicit", 3) == 0 )
2385 	      (*vartype) = SCIP_VARTYPE_IMPLINT;
2386 	   else if( strncmp(token, "continuous", 3) == 0 )
2387 	      (*vartype) = SCIP_VARTYPE_CONTINUOUS;
2388 	   else
2389 	   {
2390 	      SCIPmessagePrintWarning(messagehdlr, "unknown variable type\n");
2391 	      (*success) = FALSE;
2392 	      return SCIP_OKAY;
2393 	   }
2394 	
2395 	   /* move string pointer behind variable type */
2396 	   str = *endptr;
2397 	
2398 	   /* get variable name */
2399 	   SCIPstrCopySection(str, '<', '>', name, SCIP_MAXSTRLEN, endptr);
2400 	   assert(endptr != NULL);
2401 	   SCIPsetDebugMsg(set, "parsed variable name <%s>\n", name);
2402 	
2403 	   /* move string pointer behind variable name */
2404 	   str = *endptr;
2405 	
2406 	   /* cut out objective coefficient */
2407 	   SCIPstrCopySection(str, '=', ',', token, SCIP_MAXSTRLEN, endptr);
2408 	
2409 	   /* move string pointer behind objective coefficient */
2410 	   str = *endptr;
2411 	
2412 	   /* get objective coefficient */
2413 	   if( !SCIPstrToRealValue(token, obj, endptr) )
2414 	   {
2415 	      *endptr = NULL;
2416 	      return SCIP_READERROR;
2417 	   }
2418 	
2419 	   SCIPsetDebugMsg(set, "parsed objective coefficient <%g>\n", *obj);
2420 	
2421 	   /* parse global/original bounds */
2422 	   SCIP_CALL( parseBounds(set, str, token, lb, ub, endptr) );
2423 	   if ( *endptr == NULL )
2424 	   {
2425 	      SCIPerrorMessage("Expected bound type: %s.\n", token);
2426 	      return SCIP_READERROR;
2427 	   }
2428 	   assert(strncmp(token, "global", 6) == 0 || strncmp(token, "original", 8) == 0);
2429 	
2430 	   /* initialize the lazy bound */
2431 	   *lazylb = -SCIPsetInfinity(set);
2432 	   *lazyub =  SCIPsetInfinity(set);
2433 	
2434 	   /* store pointer */
2435 	   strptr = *endptr;
2436 	
2437 	   /* possibly parse optional local and lazy bounds */
2438 	   for( i = 0; i < 2 && *endptr != NULL && **endptr != '\0'; ++i )
2439 	   {
2440 	      /* start after previous bounds */
2441 	      strptr = *endptr;
2442 	
2443 	      /* parse global bounds */
2444 	      SCIP_CALL( parseBounds(set, strptr, token, &parsedlb, &parsedub, endptr) );
2445 	
2446 	      /* stop if parsing of bounds failed */
2447 	      if( *endptr == NULL )
2448 	         break;
2449 	
2450 	      if( strncmp(token, "local", 5) == 0 && local )
2451 	      {
2452 	         *lb = parsedlb;
2453 	         *ub = parsedub;
2454 	      }
2455 	      else if( strncmp(token, "lazy", 4) == 0 )
2456 	      {
2457 	         *lazylb = parsedlb;
2458 	         *lazyub = parsedub;
2459 	      }
2460 	   }
2461 	
2462 	   /* restore pointer */
2463 	   if ( *endptr == NULL )
2464 	      *endptr = strptr;
2465 	
2466 	   /* check bounds for binary variables */
2467 	   if ( (*vartype) == SCIP_VARTYPE_BINARY )
2468 	   {
2469 	      if ( SCIPsetIsLT(set, *lb, 0.0) || SCIPsetIsGT(set, *ub, 1.0) )
2470 	      {
2471 	         SCIPerrorMessage("Parsed invalid bounds for binary variable <%s>: [%f, %f].\n", name, *lb, *ub);
2472 	         return SCIP_READERROR;
2473 	      }
2474 	      if ( !SCIPsetIsInfinity(set, -(*lazylb)) && !SCIPsetIsInfinity(set, *lazyub) && 
2475 	           ( SCIPsetIsLT(set, *lazylb, 0.0) || SCIPsetIsGT(set, *lazyub, 1.0) ) )
2476 	      {
2477 	         SCIPerrorMessage("Parsed invalid lazy bounds for binary variable <%s>: [%f, %f].\n", name, *lazylb, *lazyub);
2478 	         return SCIP_READERROR;
2479 	      }
2480 	   }
2481 	
2482 	   return SCIP_OKAY;
2483 	}
2484 	
2485 	/** parses variable information (in cip format) out of a string; if the parsing process was successful an original
2486 	 *  variable is created and captured; if variable is of integral type, fractional bounds are automatically rounded; an
2487 	 *  integer variable with bounds zero and one is automatically converted into a binary variable
2488 	 */
2489 	SCIP_RETCODE SCIPvarParseOriginal(
2490 	   SCIP_VAR**            var,                /**< pointer to variable data */
2491 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2492 	   SCIP_SET*             set,                /**< global SCIP settings */
2493 	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
2494 	   SCIP_STAT*            stat,               /**< problem statistics */
2495 	   const char*           str,                /**< string to parse */
2496 	   SCIP_Bool             initial,            /**< should var's column be present in the initial root LP? */
2497 	   SCIP_Bool             removable,          /**< is var's column removable from the LP (due to aging or cleanup)? */
2498 	   SCIP_DECL_VARCOPY     ((*varcopy)),       /**< copies variable data if wanted to subscip, or NULL */
2499 	   SCIP_DECL_VARDELORIG  ((*vardelorig)),    /**< frees user data of original variable */
2500 	   SCIP_DECL_VARTRANS    ((*vartrans)),      /**< creates transformed user data by transforming original user data */
2501 	   SCIP_DECL_VARDELTRANS ((*vardeltrans)),   /**< frees user data of transformed variable */
2502 	   SCIP_VARDATA*         vardata,            /**< user data for this specific variable */
2503 	   char**                endptr,             /**< pointer to store the final string position if successfully */
2504 	   SCIP_Bool*            success             /**< pointer store if the paring process was successful */
2505 	   )
2506 	{
2507 	   char name[SCIP_MAXSTRLEN];
2508 	   SCIP_Real lb;
2509 	   SCIP_Real ub;
2510 	   SCIP_Real obj;
2511 	   SCIP_VARTYPE vartype;
2512 	   SCIP_Real lazylb;
2513 	   SCIP_Real lazyub;
2514 	
2515 	   assert(var != NULL);
2516 	   assert(blkmem != NULL);
2517 	   assert(stat != NULL);
2518 	   assert(endptr != NULL);
2519 	   assert(success != NULL);
2520 	
2521 	   /* parse string in cip format for variable information */
2522 	   SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, FALSE, endptr, success) );
2523 	
2524 	   if( *success ) /*lint !e774*/
2525 	   {
2526 	      /* create variable */
2527 	      SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2528 	            varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2529 	
2530 	      /* set variable status and data */
2531 	      (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2532 	      (*var)->data.original.origdom.holelist = NULL;
2533 	      (*var)->data.original.origdom.lb = lb;
2534 	      (*var)->data.original.origdom.ub = ub;
2535 	      (*var)->data.original.transvar = NULL;
2536 	
2537 	      /* set lazy status of variable bounds */
2538 	      (*var)->lazylb = lazylb;
2539 	      (*var)->lazyub = lazyub;
2540 	
2541 	      /* capture variable */
2542 	      SCIPvarCapture(*var);
2543 	   }
2544 	
2545 	   return SCIP_OKAY;
2546 	}
2547 	
2548 	/** parses variable information (in cip format) out of a string; if the parsing process was successful a loose variable
2549 	 *  belonging to the transformed problem is created and captured; if variable is of integral type, fractional bounds are
2550 	 *  automatically rounded; an integer variable with bounds zero and one is automatically converted into a binary
2551 	 *  variable
2552 	 */
2553 	SCIP_RETCODE SCIPvarParseTransformed(
2554 	   SCIP_VAR**            var,                /**< pointer to variable data */
2555 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2556 	   SCIP_SET*             set,                /**< global SCIP settings */
2557 	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
2558 	   SCIP_STAT*            stat,               /**< problem statistics */
2559 	   const char*           str,                /**< string to parse */
2560 	   SCIP_Bool             initial,            /**< should var's column be present in the initial root LP? */
2561 	   SCIP_Bool             removable,          /**< is var's column removable from the LP (due to aging or cleanup)? */
2562 	   SCIP_DECL_VARCOPY     ((*varcopy)),       /**< copies variable data if wanted to subscip, or NULL */
2563 	   SCIP_DECL_VARDELORIG  ((*vardelorig)),    /**< frees user data of original variable */
2564 	   SCIP_DECL_VARTRANS    ((*vartrans)),      /**< creates transformed user data by transforming original user data */
2565 	   SCIP_DECL_VARDELTRANS ((*vardeltrans)),   /**< frees user data of transformed variable */
2566 	   SCIP_VARDATA*         vardata,            /**< user data for this specific variable */
2567 	   char**                endptr,             /**< pointer to store the final string position if successfully */
2568 	   SCIP_Bool*            success             /**< pointer store if the paring process was successful */
2569 	   )
2570 	{
2571 	   char name[SCIP_MAXSTRLEN];
2572 	   SCIP_Real lb;
2573 	   SCIP_Real ub;
2574 	   SCIP_Real obj;
2575 	   SCIP_VARTYPE vartype;
2576 	   SCIP_Real lazylb;
2577 	   SCIP_Real lazyub;
2578 	
2579 	   assert(var != NULL);
2580 	   assert(blkmem != NULL);
2581 	   assert(endptr != NULL);
2582 	   assert(success != NULL);
2583 	
2584 	   /* parse string in cip format for variable information */
2585 	   SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, TRUE, endptr, success) );
2586 	
2587 	   if( *success ) /*lint !e774*/
2588 	   {
2589 	      /* create variable */
2590 	      SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2591 	            varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2592 	
2593 	      /* create event filter for transformed variable */
2594 	      SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2595 	
2596 	      /* set variable status and data */
2597 	      (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2598 	
2599 	      /* set lazy status of variable bounds */
2600 	      (*var)->lazylb = lazylb;
2601 	      (*var)->lazyub = lazyub;
2602 	
2603 	      /* capture variable */
2604 	      SCIPvarCapture(*var);
2605 	   }
2606 	
2607 	   return SCIP_OKAY;   
2608 	}
2609 	
2610 	/** ensures, that parentvars array of var can store at least num entries */
2611 	static
2612 	SCIP_RETCODE varEnsureParentvarsSize(
2613 	   SCIP_VAR*             var,                /**< problem variable */
2614 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2615 	   SCIP_SET*             set,                /**< global SCIP settings */
2616 	   int                   num                 /**< minimum number of entries to store */
2617 	   )
2618 	{
2619 	   assert(var->nparentvars <= var->parentvarssize);
2620 	
2621 	   if( num > var->parentvarssize )
2622 	   {
2623 	      int newsize;
2624 	
2625 	      newsize = SCIPsetCalcMemGrowSize(set, num);
2626 	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->parentvars, var->parentvarssize, newsize) );
2627 	      var->parentvarssize = newsize;
2628 	   }
2629 	   assert(num <= var->parentvarssize);
2630 	
2631 	   return SCIP_OKAY;
2632 	}
2633 	
2634 	/** adds variable to parent list of a variable and captures parent variable */
2635 	static
2636 	SCIP_RETCODE varAddParent(
2637 	   SCIP_VAR*             var,                /**< variable to add parent to */
2638 	   BMS_BLKMEM*           blkmem,             /**< block memory of transformed problem */
2639 	   SCIP_SET*             set,                /**< global SCIP settings */
2640 	   SCIP_VAR*             parentvar           /**< parent variable to add */
2641 	   )
2642 	{
2643 	   assert(var != NULL);
2644 	   assert(parentvar != NULL);
2645 	
2646 	   /* the direct original counterpart must be stored as first parent */
2647 	   assert(var->nparentvars == 0 || SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL);
2648 	
2649 	   SCIPsetDebugMsg(set, "adding parent <%s>[%p] to variable <%s>[%p] in slot %d\n",
2650 	      parentvar->name, (void*)parentvar, var->name, (void*)var, var->nparentvars);
2651 	
2652 	   SCIP_CALL( varEnsureParentvarsSize(var, blkmem, set, var->nparentvars+1) );
2653 	
2654 	   var->parentvars[var->nparentvars] = parentvar;
2655 	   var->nparentvars++;
2656 	
2657 	   SCIPvarCapture(parentvar);
2658 	
2659 	   return SCIP_OKAY;
2660 	}
2661 	
2662 	/** deletes and releases all variables from the parent list of a variable, frees the memory of parents array */
2663 	static
2664 	SCIP_RETCODE varFreeParents(
2665 	   SCIP_VAR**            var,                /**< pointer to variable */
2666 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2667 	   SCIP_SET*             set,                /**< global SCIP settings */
2668 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue (or NULL, if it's an original variable) */
2669 	   SCIP_LP*              lp                  /**< current LP data (or NULL, if it's an original variable) */
2670 	   )
2671 	{
2672 	   SCIP_VAR* parentvar;
2673 	   int i;
2674 	
2675 	   SCIPsetDebugMsg(set, "free parents of <%s>\n", (*var)->name);
2676 	
2677 	   /* release the parent variables and remove the link from the parent variable to the child */
2678 	   for( i = 0; i < (*var)->nparentvars; ++i )
2679 	   {
2680 	      assert((*var)->parentvars != NULL);
2681 	      parentvar = (*var)->parentvars[i];
2682 	      assert(parentvar != NULL);
2683 	
2684 	      switch( SCIPvarGetStatus(parentvar) )
2685 	      {
2686 	      case SCIP_VARSTATUS_ORIGINAL:
2687 	         assert(parentvar->data.original.transvar == *var);
2688 	         assert(&parentvar->data.original.transvar != var);
2689 	         parentvar->data.original.transvar = NULL;
2690 	         break;
2691 	
2692 	      case SCIP_VARSTATUS_AGGREGATED:
2693 	         assert(parentvar->data.aggregate.var == *var);
2694 	         assert(&parentvar->data.aggregate.var != var);
2695 	         parentvar->data.aggregate.var = NULL;
2696 	         break;
2697 	
2698 	#if 0
2699 	      /* The following code is unclear: should the current variable be removed from its parents? */
2700 	      case SCIP_VARSTATUS_MULTAGGR:
2701 	         assert(parentvar->data.multaggr.vars != NULL);
2702 	         for( v = 0; v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] != *var; ++v )
2703 	         {}
2704 	         assert(v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] == *var);
2705 	         if( v < parentvar->data.multaggr.nvars-1 )
2706 	         {
2707 	            parentvar->data.multaggr.vars[v] = parentvar->data.multaggr.vars[parentvar->data.multaggr.nvars-1];
2708 	            parentvar->data.multaggr.scalars[v] = parentvar->data.multaggr.scalars[parentvar->data.multaggr.nvars-1];
2709 	         }
2710 	         parentvar->data.multaggr.nvars--;
2711 	         break;
2712 	#endif
2713 	
2714 	      case SCIP_VARSTATUS_NEGATED:
2715 	         assert(parentvar->negatedvar == *var);
2716 	         assert((*var)->negatedvar == parentvar);
2717 	         parentvar->negatedvar = NULL;
2718 	         (*var)->negatedvar = NULL;
2719 	         break;
2720 	
2721 	      default:
2722 	         SCIPerrorMessage("parent variable is neither ORIGINAL, AGGREGATED nor NEGATED\n");
2723 	         return SCIP_INVALIDDATA;
2724 	      }  /*lint !e788*/
2725 	
2726 	      SCIP_CALL( SCIPvarRelease(&(*var)->parentvars[i], blkmem, set, eventqueue, lp) );
2727 	   }
2728 	
2729 	   /* free parentvars array */
2730 	   BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->parentvars, (*var)->parentvarssize);
2731 	
2732 	   return SCIP_OKAY;
2733 	}
2734 	
2735 	/** frees a variable */
2736 	static
2737 	SCIP_RETCODE varFree(
2738 	   SCIP_VAR**            var,                /**< pointer to variable */
2739 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2740 	   SCIP_SET*             set,                /**< global SCIP settings */
2741 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue (may be NULL, if it's not a column variable) */
2742 	   SCIP_LP*              lp                  /**< current LP data (may be NULL, if it's not a column variable) */
2743 	   )
2744 	{
2745 	   assert(var != NULL);
2746 	   assert(*var != NULL);
2747 	   assert(SCIPvarGetStatus(*var) != SCIP_VARSTATUS_COLUMN || &(*var)->data.col->var != var);
2748 	   assert((*var)->nuses == 0);
2749 	   assert((*var)->probindex == -1);
2750 	   assert((*var)->nlocksup[SCIP_LOCKTYPE_MODEL] == 0);
2751 	   assert((*var)->nlocksdown[SCIP_LOCKTYPE_MODEL] == 0);
2752 	
2753 	   SCIPsetDebugMsg(set, "free variable <%s> with status=%d\n", (*var)->name, SCIPvarGetStatus(*var));
2754 	
2755 	   switch( SCIPvarGetStatus(*var) )
2756 	   {
2757 	   case SCIP_VARSTATUS_ORIGINAL:
2758 	      assert((*var)->data.original.transvar == NULL); /* cannot free variable, if transformed variable is still existing */
2759 	      holelistFree(&(*var)->data.original.origdom.holelist, blkmem);
2760 	      assert((*var)->data.original.origdom.holelist == NULL);
2761 	      break;
2762 	   case SCIP_VARSTATUS_LOOSE:
2763 	      break;
2764 	   case SCIP_VARSTATUS_COLUMN:
2765 	      SCIP_CALL( SCIPcolFree(&(*var)->data.col, blkmem, set, eventqueue, lp) );  /* free corresponding LP column */
2766 	      break;
2767 	   case SCIP_VARSTATUS_FIXED:
2768 	   case SCIP_VARSTATUS_AGGREGATED:
2769 	      break;
2770 	   case SCIP_VARSTATUS_MULTAGGR:
2771 	      BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.vars, (*var)->data.multaggr.varssize);
2772 	      BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.scalars, (*var)->data.multaggr.varssize);
2773 	      break;
2774 	   case SCIP_VARSTATUS_NEGATED:
2775 	      break;
2776 	   default:
2777 	      SCIPerrorMessage("unknown variable status\n");
2778 	      return SCIP_INVALIDDATA;
2779 	   }
2780 	
2781 	   /* release all parent variables and free the parentvars array */
2782 	   SCIP_CALL( varFreeParents(var, blkmem, set, eventqueue, lp) );
2783 	
2784 	   /* free user data */
2785 	   if( SCIPvarGetStatus(*var) == SCIP_VARSTATUS_ORIGINAL )
2786 	   {
2787 	      if( (*var)->vardelorig != NULL )
2788 	      {
2789 	         SCIP_CALL( (*var)->vardelorig(set->scip, *var, &(*var)->vardata) );
2790 	      }
2791 	   }
2792 	   else
2793 	   {
2794 	      if( (*var)->vardeltrans != NULL )
2795 	      {
2796 	         SCIP_CALL( (*var)->vardeltrans(set->scip, *var, &(*var)->vardata) );
2797 	      }
2798 	   }
2799 	
2800 	   /* free event filter */
2801 	   if( (*var)->eventfilter != NULL )
2802 	   {
2803 	      SCIP_CALL( SCIPeventfilterFree(&(*var)->eventfilter, blkmem, set) );
2804 	   }
2805 	   assert((*var)->eventfilter == NULL);
2806 	
2807 	   /* free hole lists */
2808 	   holelistFree(&(*var)->glbdom.holelist, blkmem);
2809 	   holelistFree(&(*var)->locdom.holelist, blkmem);
2810 	   assert((*var)->glbdom.holelist == NULL);
2811 	   assert((*var)->locdom.holelist == NULL);
2812 	
2813 	   /* free variable bounds data structures */
2814 	   SCIPvboundsFree(&(*var)->vlbs, blkmem);
2815 	   SCIPvboundsFree(&(*var)->vubs, blkmem);
2816 	
2817 	   /* free implications data structures */
2818 	   SCIPimplicsFree(&(*var)->implics, blkmem);
2819 	
2820 	   /* free clique list data structures */
2821 	   SCIPcliquelistFree(&(*var)->cliquelist, blkmem);
2822 	
2823 	   /* free bound change information arrays */
2824 	   BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->lbchginfos, (*var)->lbchginfossize);
2825 	   BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->ubchginfos, (*var)->ubchginfossize);
2826 	
2827 	   /* free branching and inference history entries */
2828 	   SCIPhistoryFree(&(*var)->history, blkmem);
2829 	   SCIPhistoryFree(&(*var)->historycrun, blkmem);
2830 	   SCIPvaluehistoryFree(&(*var)->valuehistory, blkmem);
2831 	
2832 	   /* free variable data structure */
2833 	   BMSfreeBlockMemoryArray(blkmem, &(*var)->name, strlen((*var)->name)+1);
2834 	   BMSfreeBlockMemory(blkmem, var);
2835 	
2836 	   return SCIP_OKAY;
2837 	}
2838 	
2839 	/** increases usage counter of variable */
2840 	void SCIPvarCapture(
2841 	   SCIP_VAR*             var                 /**< variable */
2842 	   )
2843 	{
2844 	   assert(var != NULL);
2845 	   assert(var->nuses >= 0);
2846 	
2847 	   SCIPdebugMessage("capture variable <%s> with nuses=%d\n", var->name, var->nuses);
2848 	   var->nuses++;
2849 	
2850 	#ifdef DEBUGUSES_VARNAME
2851 	   if( strcmp(var->name, DEBUGUSES_VARNAME) == 0
2852 	#ifdef DEBUGUSES_PROBNAME
2853 	      && ((var->scip->transprob != NULL && strcmp(SCIPprobGetName(var->scip->transprob), DEBUGUSES_PROBNAME) == 0) ||
2854 	          strcmp(SCIPprobGetName(var->scip->origprob), DEBUGUSES_PROBNAME) == 0)
2855 	#endif
2856 	   )
2857 	   {
2858 	      printf("Captured variable " DEBUGUSES_VARNAME " in SCIP %p, now %d uses; captured at\n", (void*)var->scip, var->nuses);
2859 	      print_backtrace();
2860 	   }
2861 	#endif
2862 	}
2863 	
2864 	/** decreases usage counter of variable, and frees memory if necessary */
2865 	SCIP_RETCODE SCIPvarRelease(
2866 	   SCIP_VAR**            var,                /**< pointer to variable */
2867 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2868 	   SCIP_SET*             set,                /**< global SCIP settings */
2869 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
2870 	   SCIP_LP*              lp                  /**< current LP data (or NULL, if it's an original variable) */
2871 	   )
2872 	{
2873 	   assert(var != NULL);
2874 	   assert(*var != NULL);
2875 	   assert((*var)->nuses >= 1);
2876 	   assert(blkmem != NULL);
2877 	   assert((*var)->scip == set->scip);
2878 	
2879 	   SCIPsetDebugMsg(set, "release variable <%s> with nuses=%d\n", (*var)->name, (*var)->nuses);
2880 	   (*var)->nuses--;
2881 	
2882 	#ifdef DEBUGUSES_VARNAME
2883 	   if( strcmp((*var)->name, DEBUGUSES_VARNAME) == 0
2884 	#ifdef DEBUGUSES_PROBNAME
2885 	      && (((*var)->scip->transprob != NULL && strcmp(SCIPprobGetName((*var)->scip->transprob), DEBUGUSES_PROBNAME) == 0) ||
2886 	          strcmp(SCIPprobGetName((*var)->scip->origprob), DEBUGUSES_PROBNAME) == 0)
2887 	#endif
2888 	   )
2889 	   {
2890 	      printf("Released variable " DEBUGUSES_VARNAME " in SCIP %p, now %d uses; released at\n", (void*)(*var)->scip, (*var)->nuses);
2891 	      print_backtrace();
2892 	   }
2893 	#endif
2894 	
2895 	   if( (*var)->nuses == 0 )
2896 	   {
2897 	      SCIP_CALL( varFree(var, blkmem, set, eventqueue, lp) );
2898 	   }
2899 	
2900 	   *var = NULL;
2901 	
2902 	   return SCIP_OKAY;
2903 	}
2904 	
2905 	/** change variable name */
2906 	SCIP_RETCODE SCIPvarChgName(
2907 	   SCIP_VAR*             var,                /**< problem variable */
2908 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2909 	   const char*           name                /**< name of variable */
2910 	   )
2911 	{
2912 	   assert(name != NULL);
2913 	
2914 	   /* remove old variable name */
2915 	   BMSfreeBlockMemoryArray(blkmem, &var->name, strlen(var->name)+1);
2916 	
2917 	   /* set new variable name */
2918 	   SCIP_CALL( varSetName(var, blkmem, NULL, name) );
2919 	
2920 	   return SCIP_OKAY;
2921 	}
2922 	
2923 	/** initializes variable data structure for solving */
2924 	void SCIPvarInitSolve(
2925 	   SCIP_VAR*             var                 /**< problem variable */
2926 	   )
2927 	{
2928 	   assert(var != NULL);
2929 	
2930 	   SCIPhistoryReset(var->historycrun);
2931 	   var->conflictlbcount = 0;
2932 	   var->conflictubcount = 0;
2933 	}
2934 	
2935 	/** outputs the given bounds into the file stream */
2936 	static
2937 	void printBounds(
2938 	   SCIP_SET*             set,                /**< global SCIP settings */
2939 	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
2940 	   FILE*                 file,               /**< output file (or NULL for standard output) */
2941 	   SCIP_Real             lb,                 /**< lower bound */
2942 	   SCIP_Real             ub,                 /**< upper bound */
2943 	   const char*           name                /**< bound type name */
2944 	   )
2945 	{
2946 	   assert(set != NULL);
2947 	
2948 	   SCIPmessageFPrintInfo(messagehdlr, file, ", %s=", name);
2949 	   if( SCIPsetIsInfinity(set, lb) )
2950 	      SCIPmessageFPrintInfo(messagehdlr, file, "[+inf,");
2951 	   else if( SCIPsetIsInfinity(set, -lb) )
2952 	      SCIPmessageFPrintInfo(messagehdlr, file, "[-inf,");
2953 	   else
2954 	      SCIPmessageFPrintInfo(messagehdlr, file, "[%.15g,", lb);
2955 	   if( SCIPsetIsInfinity(set, ub) )
2956 	      SCIPmessageFPrintInfo(messagehdlr, file, "+inf]");
2957 	   else if( SCIPsetIsInfinity(set, -ub) )
2958 	      SCIPmessageFPrintInfo(messagehdlr, file, "-inf]");
2959 	   else
2960 	      SCIPmessageFPrintInfo(messagehdlr, file, "%.15g]", ub);
2961 	}
2962 	
2963 	/** prints hole list to file stream */
2964 	static
2965 	void printHolelist(
2966 	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
2967 	   FILE*                 file,               /**< output file (or NULL for standard output) */
2968 	   SCIP_HOLELIST*        holelist,           /**< hole list pointer to hole of interest */
2969 	   const char*           name                /**< hole type name */
2970 	   )
2971 	{  /*lint --e{715}*/
2972 	   SCIP_Real left;
2973 	   SCIP_Real right;
2974 	
2975 	   if( holelist == NULL )
2976 	      return;
2977 	
2978 	   left = SCIPholelistGetLeft(holelist);
2979 	   right = SCIPholelistGetRight(holelist);
2980 	
2981 	   /* display first hole */
2982 	   SCIPmessageFPrintInfo(messagehdlr, file, ", %s=(%g,%g)", name, left, right);
2983 	   holelist = SCIPholelistGetNext(holelist);
2984 	
2985 	   while(holelist != NULL  )
2986 	   {
2987 	      left = SCIPholelistGetLeft(holelist);
2988 	      right = SCIPholelistGetRight(holelist);
2989 	
2990 	      /* display hole */
2991 	      SCIPmessageFPrintInfo(messagehdlr, file, "(%g,%g)", left, right);
2992 	
2993 	      /* get next hole */
2994 	      holelist = SCIPholelistGetNext(holelist);
2995 	   }
2996 	}
2997 	
2998 	/** outputs variable information into file stream */
2999 	SCIP_RETCODE SCIPvarPrint(
3000 	   SCIP_VAR*             var,                /**< problem variable */
3001 	   SCIP_SET*             set,                /**< global SCIP settings */
3002 	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
3003 	   FILE*                 file                /**< output file (or NULL for standard output) */
3004 	   )
3005 	{
3006 	   SCIP_HOLELIST* holelist;
3007 	   SCIP_Real lb;
3008 	   SCIP_Real ub;
3009 	   int i;
3010 	
3011 	   assert(var != NULL);
3012 	   assert(var->scip == set->scip);
3013 	
3014 	   /* type of variable */
3015 	   switch( SCIPvarGetType(var) )
3016 	   {
3017 	   case SCIP_VARTYPE_BINARY:
3018 	      SCIPmessageFPrintInfo(messagehdlr, file, "  [binary]");
3019 	      break;
3020 	   case SCIP_VARTYPE_INTEGER:
3021 	      SCIPmessageFPrintInfo(messagehdlr, file, "  [integer]");
3022 	      break;
3023 	   case SCIP_VARTYPE_IMPLINT:
3024 	      SCIPmessageFPrintInfo(messagehdlr, file, "  [implicit]");
3025 	      break;
3026 	   case SCIP_VARTYPE_CONTINUOUS:
3027 	      SCIPmessageFPrintInfo(messagehdlr, file, "  [continuous]");
3028 	      break;
3029 	   default:
3030 	      SCIPerrorMessage("unknown variable type\n");
3031 	      SCIPABORT();
3032 	      return SCIP_ERROR; /*lint !e527*/
3033 	   }
3034 	
3035 	   /* name */
3036 	   SCIPmessageFPrintInfo(messagehdlr, file, " <%s>:", var->name);
3037 	
3038 	   /* objective value */
3039 	   SCIPmessageFPrintInfo(messagehdlr, file, " obj=%.15g", var->obj);
3040 	
3041 	   /* bounds (global bounds for transformed variables, original bounds for original variables) */
3042 	   if( !SCIPvarIsTransformed(var) )
3043 	   {
3044 	      /* output original bound */
3045 	      lb = SCIPvarGetLbOriginal(var);
3046 	      ub = SCIPvarGetUbOriginal(var);
3047 	      printBounds(set, messagehdlr, file, lb, ub, "original bounds");
3048 	
3049 	      /* output lazy bound */
3050 	      lb = SCIPvarGetLbLazy(var);
3051 	      ub = SCIPvarGetUbLazy(var);
3052 	
3053 	      /* only display the lazy bounds if they are different from [-infinity,infinity] */
3054 	      if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
3055 	         printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
3056 	
3057 	      holelist = SCIPvarGetHolelistOriginal(var);
3058 	      printHolelist(messagehdlr, file, holelist, "original holes");
3059 	   }
3060 	   else
3061 	   {
3062 	      /* output global bound */
3063 	      lb = SCIPvarGetLbGlobal(var);
3064 	      ub = SCIPvarGetUbGlobal(var);
3065 	      printBounds(set, messagehdlr, file, lb, ub, "global bounds");
3066 	
3067 	      /* output local bound */
3068 	      lb = SCIPvarGetLbLocal(var);
3069 	      ub = SCIPvarGetUbLocal(var);
3070 	      printBounds(set, messagehdlr, file, lb, ub, "local bounds");
3071 	
3072 	      /* output lazy bound */
3073 	      lb = SCIPvarGetLbLazy(var);
3074 	      ub = SCIPvarGetUbLazy(var);
3075 	
3076 	      /* only display the lazy bounds if they are different from [-infinity,infinity] */
3077 	      if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
3078 	         printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
3079 	
3080 	      /* global hole list */
3081 	      holelist = SCIPvarGetHolelistGlobal(var);
3082 	      printHolelist(messagehdlr, file, holelist, "global holes");
3083 	
3084 	      /* local hole list */
3085 	      holelist = SCIPvarGetHolelistLocal(var);
3086 	      printHolelist(messagehdlr, file, holelist, "local holes");
3087 	   }
3088 	
3089 	   /* fixings and aggregations */
3090 	   switch( SCIPvarGetStatus(var) )
3091 	   {
3092 	   case SCIP_VARSTATUS_ORIGINAL:
3093 	   case SCIP_VARSTATUS_LOOSE:
3094 	   case SCIP_VARSTATUS_COLUMN:
3095 	      break;
3096 	
3097 	   case SCIP_VARSTATUS_FIXED:
3098 	      SCIPmessageFPrintInfo(messagehdlr, file, ", fixed:");
3099 	      if( SCIPsetIsInfinity(set, var->glbdom.lb) )
3100 	         SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
3101 	      else if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
3102 	         SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
3103 	      else
3104 	         SCIPmessageFPrintInfo(messagehdlr, file, "%.15g", var->glbdom.lb);
3105 	      break;
3106 	
3107 	   case SCIP_VARSTATUS_AGGREGATED:
3108 	      SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
3109 	      if( !SCIPsetIsZero(set, var->data.aggregate.constant) )
3110 	         SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.aggregate.constant);
3111 	      SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.aggregate.scalar, SCIPvarGetName(var->data.aggregate.var));
3112 	      break;
3113 	
3114 	   case SCIP_VARSTATUS_MULTAGGR:
3115 	      SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
3116 	      if( var->data.multaggr.nvars == 0 || !SCIPsetIsZero(set, var->data.multaggr.constant) )
3117 	         SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.multaggr.constant);
3118 	      for( i = 0; i < var->data.multaggr.nvars; ++i )
3119 	         SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.multaggr.scalars[i], SCIPvarGetName(var->data.multaggr.vars[i]));
3120 	      break;
3121 	
3122 	   case SCIP_VARSTATUS_NEGATED:
3123 	      SCIPmessageFPrintInfo(messagehdlr, file, ", negated: %.15g - <%s>", var->data.negate.constant, SCIPvarGetName(var->negatedvar));
3124 	      break;
3125 	
3126 	   default:
3127 	      SCIPerrorMessage("unknown variable status\n");
3128 	      SCIPABORT();
3129 	      return SCIP_ERROR; /*lint !e527*/
3130 	   }
3131 	
3132 	   SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3133 	
3134 	   return SCIP_OKAY;
3135 	}
3136 	
3137 	/** issues a VARUNLOCKED event on the given variable */
3138 	static
3139 	SCIP_RETCODE varEventVarUnlocked(
3140 	   SCIP_VAR*             var,                /**< problem variable to change */
3141 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3142 	   SCIP_SET*             set,                /**< global SCIP settings */
3143 	   SCIP_EVENTQUEUE*      eventqueue          /**< event queue */
3144 	   )
3145 	{
3146 	   SCIP_EVENT* event;
3147 	
3148 	   assert(var != NULL);
3149 	   assert(var->nlocksdown[SCIP_LOCKTYPE_MODEL] <= 1 && var->nlocksup[SCIP_LOCKTYPE_MODEL] <= 1);
3150 	   assert(var->scip == set->scip);
3151 	
3152 	   /* issue VARUNLOCKED event on variable */
3153 	   SCIP_CALL( SCIPeventCreateVarUnlocked(&event, blkmem, var) );
3154 	   SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3155 	
3156 	   return SCIP_OKAY;
3157 	}
3158 	
3159 	/** modifies lock numbers for rounding */
3160 	SCIP_RETCODE SCIPvarAddLocks(
3161 	   SCIP_VAR*             var,                /**< problem variable */
3162 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3163 	   SCIP_SET*             set,                /**< global SCIP settings */
3164 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
3165 	   SCIP_LOCKTYPE         locktype,           /**< type of the variable locks */
3166 	   int                   addnlocksdown,      /**< increase in number of rounding down locks */
3167 	   int                   addnlocksup         /**< increase in number of rounding up locks */
3168 	   )
3169 	{
3170 	   SCIP_VAR* lockvar;
3171 	
3172 	   assert(var != NULL);
3173 	   assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3174 	   assert(var->nlocksup[locktype] >= 0);
3175 	   assert(var->nlocksdown[locktype] >= 0);
3176 	   assert(var->scip == set->scip);
3177 	
3178 	   if( addnlocksdown == 0 && addnlocksup == 0 )
3179 	      return SCIP_OKAY;
3180 	
3181 	#ifdef SCIP_DEBUG
3182 	   SCIPsetDebugMsg(set, "add rounding locks %d/%d to variable <%s> (locks=%d/%d, type=%u)\n",
3183 	         addnlocksdown, addnlocksup, var->name, var->nlocksdown[locktype], var->nlocksup[locktype], locktype);
3184 	#endif
3185 	
3186 	   lockvar = var;
3187 	
3188 	   while( TRUE ) /*lint !e716 */
3189 	   {
3190 	      assert(lockvar != NULL);
3191 	
3192 	      switch( SCIPvarGetStatus(lockvar) )
3193 	      {
3194 	      case SCIP_VARSTATUS_ORIGINAL:
3195 	         if( lockvar->data.original.transvar != NULL )
3196 	         {
3197 	            lockvar = lockvar->data.original.transvar;
3198 	            break;
3199 	         }
3200 	         else
3201 	         {
3202 	            lockvar->nlocksdown[locktype] += addnlocksdown;
3203 	            lockvar->nlocksup[locktype] += addnlocksup;
3204 	
3205 	            assert(lockvar->nlocksdown[locktype] >= 0);
3206 	            assert(lockvar->nlocksup[locktype] >= 0);
3207 	
3208 	            return SCIP_OKAY;
3209 	         }
3210 	      case SCIP_VARSTATUS_LOOSE:
3211 	      case SCIP_VARSTATUS_COLUMN:
3212 	      case SCIP_VARSTATUS_FIXED:
3213 	         lockvar->nlocksdown[locktype] += addnlocksdown;
3214 	         lockvar->nlocksup[locktype] += addnlocksup;
3215 	
3216 	         assert(lockvar->nlocksdown[locktype] >= 0);
3217 	         assert(lockvar->nlocksup[locktype] >= 0);
3218 	
3219 	         if( locktype == SCIP_LOCKTYPE_MODEL && lockvar->nlocksdown[locktype] <= 1
3220 	            && lockvar->nlocksup[locktype] <= 1 )
3221 	         {
3222 	            SCIP_CALL( varEventVarUnlocked(lockvar, blkmem, set, eventqueue) );
3223 	         }
3224 	
3225 	         return SCIP_OKAY;
3226 	      case SCIP_VARSTATUS_AGGREGATED:
3227 	         assert(!lockvar->donotaggr);
3228 	
3229 	         if( lockvar->data.aggregate.scalar < 0.0 )
3230 	         {
3231 	            int tmp = addnlocksup;
3232 	
3233 	            addnlocksup = addnlocksdown;
3234 	            addnlocksdown = tmp;
3235 	         }
3236 	
3237 	         lockvar = lockvar->data.aggregate.var;
3238 	         break;
3239 	      case SCIP_VARSTATUS_MULTAGGR:
3240 	      {
3241 	         int v;
3242 	
3243 	         assert(!lockvar->donotmultaggr);
3244 	
3245 	         lockvar->nlocksdown[locktype] += addnlocksdown;
3246 	         lockvar->nlocksup[locktype] += addnlocksup;
3247 	
3248 	         assert(lockvar->nlocksdown[locktype] >= 0);
3249 	         assert(lockvar->nlocksup[locktype] >= 0);
3250 	
3251 	         for( v = lockvar->data.multaggr.nvars - 1; v >= 0; --v )
3252 	         {
3253 	            if( lockvar->data.multaggr.scalars[v] > 0.0 )
3254 	            {
3255 	               SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksdown,
3256 	                     addnlocksup) );
3257 	            }
3258 	            else
3259 	            {
3260 	               SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksup,
3261 	                     addnlocksdown) );
3262 	            }
3263 	         }
3264 	         return SCIP_OKAY;
3265 	      }
3266 	      case SCIP_VARSTATUS_NEGATED:
3267 	      {
3268 	         int tmp = addnlocksup;
3269 	
3270 	         assert(lockvar->negatedvar != NULL);
3271 	         assert(SCIPvarGetStatus(lockvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
3272 	         assert(lockvar->negatedvar->negatedvar == lockvar);
3273 	
3274 	         addnlocksup = addnlocksdown;
3275 	         addnlocksdown = tmp;
3276 	
3277 	         lockvar = lockvar->negatedvar;
3278 	         break;
3279 	      }
3280 	      default:
3281 	         SCIPerrorMessage("unknown variable status\n");
3282 	         return SCIP_INVALIDDATA;
3283 	      }
3284 	   }
3285 	}
3286 	
3287 	/** gets number of locks for rounding down of a special type */
3288 	int SCIPvarGetNLocksDownType(
3289 	   SCIP_VAR*             var,                /**< problem variable */
3290 	   SCIP_LOCKTYPE         locktype            /**< type of variable locks */
3291 	   )
3292 	{
3293 	   int nlocks;
3294 	   int i;
3295 	
3296 	   assert(var != NULL);
3297 	   assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3298 	   assert(var->nlocksdown[locktype] >= 0);
3299 	
3300 	   switch( SCIPvarGetStatus(var) )
3301 	   {
3302 	   case SCIP_VARSTATUS_ORIGINAL:
3303 	      if( var->data.original.transvar != NULL )
3304 	         return SCIPvarGetNLocksDownType(var->data.original.transvar, locktype);
3305 	      else
3306 	         return var->nlocksdown[locktype];
3307 	
3308 	   case SCIP_VARSTATUS_LOOSE:
3309 	   case SCIP_VARSTATUS_COLUMN:
3310 	   case SCIP_VARSTATUS_FIXED:
3311 	      return var->nlocksdown[locktype];
3312 	
3313 	   case SCIP_VARSTATUS_AGGREGATED:
3314 	      assert(!var->donotaggr);
3315 	      if( var->data.aggregate.scalar > 0.0 )
3316 	         return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
3317 	      else
3318 	         return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
3319 	
3320 	   case SCIP_VARSTATUS_MULTAGGR:
3321 	      assert(!var->donotmultaggr);
3322 	      nlocks = 0;
3323 	      for( i = 0; i < var->data.multaggr.nvars; ++i )
3324 	      {
3325 	         if( var->data.multaggr.scalars[i] > 0.0 )
3326 	            nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
3327 	         else
3328 	            nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
3329 	      }
3330 	      return nlocks;
3331 	
3332 	   case SCIP_VARSTATUS_NEGATED:
3333 	      assert(var->negatedvar != NULL);
3334 	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
3335 	      assert(var->negatedvar->negatedvar == var);
3336 	      return SCIPvarGetNLocksUpType(var->negatedvar, locktype);
3337 	
3338 	   default:
3339 	      SCIPerrorMessage("unknown variable status\n");
3340 	      SCIPABORT();
3341 	      return INT_MAX; /*lint !e527*/
3342 	   }
3343 	}
3344 	
3345 	/** gets number of locks for rounding up of a special type */
3346 	int SCIPvarGetNLocksUpType(
3347 	   SCIP_VAR*             var,                /**< problem variable */
3348 	   SCIP_LOCKTYPE         locktype            /**< type of variable locks */
3349 	   )
3350 	{
3351 	   int nlocks;
3352 	   int i;
3353 	
3354 	   assert(var != NULL);
3355 	   assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3356 	   assert(var->nlocksup[locktype] >= 0);
3357 	
3358 	   switch( SCIPvarGetStatus(var) )
3359 	   {
3360 	   case SCIP_VARSTATUS_ORIGINAL:
3361 	      if( var->data.original.transvar != NULL )
3362 	         return SCIPvarGetNLocksUpType(var->data.original.transvar, locktype);
3363 	      else
3364 	         return var->nlocksup[locktype];
3365 	
3366 	   case SCIP_VARSTATUS_LOOSE:
3367 	   case SCIP_VARSTATUS_COLUMN:
3368 	   case SCIP_VARSTATUS_FIXED:
3369 	      return var->nlocksup[locktype];
3370 	
3371 	   case SCIP_VARSTATUS_AGGREGATED:
3372 	      assert(!var->donotaggr);
3373 	      if( var->data.aggregate.scalar > 0.0 )
3374 	         return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
3375 	      else
3376 	         return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
3377 	
3378 	   case SCIP_VARSTATUS_MULTAGGR:
3379 	      assert(!var->donotmultaggr);
3380 	      nlocks = 0;
3381 	      for( i = 0; i < var->data.multaggr.nvars; ++i )
3382 	      {
3383 	         if( var->data.multaggr.scalars[i] > 0.0 )
3384 	            nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
3385 	         else
3386 	            nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
3387 	      }
3388 	      return nlocks;
3389 	
3390 	   case SCIP_VARSTATUS_NEGATED:
3391 	      assert(var->negatedvar != NULL);
3392 	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
3393 	      assert(var->negatedvar->negatedvar == var);
3394 	      return SCIPvarGetNLocksDownType(var->negatedvar, locktype);
3395 	
3396 	   default:
3397 	      SCIPerrorMessage("unknown variable status\n");
3398 	      SCIPABORT();
3399 	      return INT_MAX; /*lint !e527*/
3400 	   }
3401 	}
3402 	
3403 	/** gets number of locks for rounding down
3404 	 *
3405 	 *  @note This method will always return variable locks of type model
3406 	 *
3407 	 *  @note It is recommented to use SCIPvarGetNLocksDownType()
3408 	 */
3409 	int SCIPvarGetNLocksDown(
3410 	   SCIP_VAR*             var                 /**< problem variable */
3411 	   )
3412 	{
3413 	   return SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL);
3414 	}
3415 	
3416 	/** gets number of locks for rounding up
3417 	 *
3418 	 *  @note This method will always return variable locks of type model
3419 	 *
3420 	 *  @note It is recommented to use SCIPvarGetNLocksUpType()
3421 	 */
3422 	int SCIPvarGetNLocksUp(
3423 	   SCIP_VAR*             var                 /**< problem variable */
3424 	   )
3425 	{
3426 	   return SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL);
3427 	}
3428 	
3429 	/** is it possible, to round variable down and stay feasible?
3430 	 *
3431 	 *  @note This method will always check w.r.t variable locks of type model
3432 	 */
3433 	SCIP_Bool SCIPvarMayRoundDown(
3434 	   SCIP_VAR*             var                 /**< problem variable */
3435 	   )
3436 	{
3437 	   return (SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 0);
3438 	}
3439 	
3440 	/** is it possible, to round variable up and stay feasible?
3441 	 *
3442 	 *  @note This method will always check w.r.t. variable locks of type model
3443 	 */
3444 	SCIP_Bool SCIPvarMayRoundUp(
3445 	   SCIP_VAR*             var                 /**< problem variable */
3446 	   )
3447 	{
3448 	   return (SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 0);
3449 	}
3450 	
3451 	/** gets and captures transformed variable of a given variable; if the variable is not yet transformed,
3452 	 *  a new transformed variable for this variable is created
3453 	 */
3454 	SCIP_RETCODE SCIPvarTransform(
3455 	   SCIP_VAR*             origvar,            /**< original problem variable */
3456 	   BMS_BLKMEM*           blkmem,             /**< block memory of transformed problem */
3457 	   SCIP_SET*             set,                /**< global SCIP settings */
3458 	   SCIP_STAT*            stat,               /**< problem statistics */
3459 	   SCIP_OBJSENSE         objsense,           /**< objective sense of original problem; transformed is always MINIMIZE */
3460 	   SCIP_VAR**            transvar            /**< pointer to store the transformed variable */
3461 	   )
3462 	{
3463 	   char name[SCIP_MAXSTRLEN];
3464 	
3465 	   assert(origvar != NULL);
3466 	   assert(origvar->scip == set->scip);
3467 	   assert(SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_ORIGINAL);
3468 	   assert(SCIPsetIsEQ(set, origvar->glbdom.lb, origvar->locdom.lb));
3469 	   assert(SCIPsetIsEQ(set, origvar->glbdom.ub, origvar->locdom.ub));
3470 	   assert(origvar->vlbs == NULL);
3471 	   assert(origvar->vubs == NULL);
3472 	   assert(transvar != NULL);
3473 	
3474 	   /* check if variable is already transformed */
3475 	   if( origvar->data.original.transvar != NULL )
3476 	   {
3477 	      *transvar = origvar->data.original.transvar;
3478 	      SCIPvarCapture(*transvar);
3479 	   }
3480 	   else
3481 	   {
3482 	      int i;
3483 	
3484 	      /* create transformed variable */
3485 	      (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "t_%s", origvar->name);
3486 	      SCIP_CALL( SCIPvarCreateTransformed(transvar, blkmem, set, stat, name,
3487 	            origvar->glbdom.lb, origvar->glbdom.ub, (SCIP_Real)objsense * origvar->obj,
3488 	            SCIPvarGetType(origvar), origvar->initial, origvar->removable,
3489 	            origvar->vardelorig, origvar->vartrans, origvar->vardeltrans, origvar->varcopy, NULL) );
3490 	
3491 	      /* copy the branch factor and priority */
3492 	      (*transvar)->branchfactor = origvar->branchfactor;
3493 	      (*transvar)->branchpriority = origvar->branchpriority;
3494 	      (*transvar)->branchdirection = origvar->branchdirection; /*lint !e732*/
3495 	
3496 	      /* duplicate hole lists */
3497 	      SCIP_CALL( holelistDuplicate(&(*transvar)->glbdom.holelist, blkmem, set, origvar->glbdom.holelist) );
3498 	      SCIP_CALL( holelistDuplicate(&(*transvar)->locdom.holelist, blkmem, set, origvar->locdom.holelist) );
3499 	
3500 	      /* link original and transformed variable */
3501 	      origvar->data.original.transvar = *transvar;
3502 	      SCIP_CALL( varAddParent(*transvar, blkmem, set, origvar) );
3503 	
3504 	      /* copy rounding locks */
3505 	      for( i = 0; i < NLOCKTYPES; i++ )
3506 	      {
3507 	         (*transvar)->nlocksdown[i] = origvar->nlocksdown[i];
3508 	         (*transvar)->nlocksup[i] = origvar->nlocksup[i];
3509 	         assert((*transvar)->nlocksdown[i] >= 0);
3510 	         assert((*transvar)->nlocksup[i] >= 0);
3511 	      }
3512 	
3513 	      /* copy donot(mult)aggr status */
3514 	      (*transvar)->donotaggr = origvar->donotaggr;
3515 	      (*transvar)->donotmultaggr = origvar->donotmultaggr;
3516 	
3517 	      /* copy lazy bounds */
3518 	      (*transvar)->lazylb = origvar->lazylb;
3519 	      (*transvar)->lazyub = origvar->lazyub;
3520 	
3521 	      /* transfer eventual variable statistics; do not update global statistics, because this has been done
3522 	       * when original variable was created
3523 	       */
3524 	      SCIPhistoryUnite((*transvar)->history, origvar->history, FALSE);
3525 	
3526 	      /* transform user data */
3527 	      if( origvar->vartrans != NULL )
3528 	      {
3529 	         SCIP_CALL( origvar->vartrans(set->scip, origvar, origvar->vardata, *transvar, &(*transvar)->vardata) );
3530 	      }
3531 	      else
3532 	         (*transvar)->vardata = origvar->vardata;
3533 	   }
3534 	
3535 	   SCIPsetDebugMsg(set, "transformed variable: <%s>[%p] -> <%s>[%p]\n", origvar->name, (void*)origvar, (*transvar)->name, (void*)*transvar);
3536 	
3537 	   return SCIP_OKAY;
3538 	}
3539 	
3540 	/** gets corresponding transformed variable of an original or negated original variable */
3541 	SCIP_RETCODE SCIPvarGetTransformed(
3542 	   SCIP_VAR*             origvar,            /**< original problem variable */
3543 	   BMS_BLKMEM*           blkmem,             /**< block memory of transformed problem */
3544 	   SCIP_SET*             set,                /**< global SCIP settings */
3545 	   SCIP_STAT*            stat,               /**< problem statistics */
3546 	   SCIP_VAR**            transvar            /**< pointer to store the transformed variable, or NULL if not existing yet */
3547 	   )
3548 	{
3549 	   assert(origvar != NULL);
3550 	   assert(SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_ORIGINAL || SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_NEGATED);
3551 	   assert(origvar->scip == set->scip);
3552 	
3553 	   if( SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_NEGATED )
3554 	   {
3555 	      assert(origvar->negatedvar != NULL);
3556 	      assert(SCIPvarGetStatus(origvar->negatedvar) == SCIP_VARSTATUS_ORIGINAL);
3557 	
3558 	      if( origvar->negatedvar->data.original.transvar == NULL )
3559 	         *transvar = NULL;
3560 	      else
3561 	      {
3562 	         SCIP_CALL( SCIPvarNegate(origvar->negatedvar->data.original.transvar, blkmem, set, stat, transvar) );
3563 	      }
3564 	   }
3565 	   else 
3566 	      *transvar = origvar->data.original.transvar;
3567 	
3568 	   return SCIP_OKAY;
3569 	}
3570 	
3571 	/** converts loose transformed variable into column variable, creates LP column */
3572 	SCIP_RETCODE SCIPvarColumn(
3573 	   SCIP_VAR*             var,                /**< problem variable */
3574 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3575 	   SCIP_SET*             set,                /**< global SCIP settings */
3576 	   SCIP_STAT*            stat,               /**< problem statistics */
3577 	   SCIP_PROB*            prob,               /**< problem data */
3578 	   SCIP_LP*              lp                  /**< current LP data */
3579 	   )
3580 	{
3581 	   assert(var != NULL);
3582 	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
3583 	   assert(var->scip == set->scip);
3584 	
3585 	   SCIPsetDebugMsg(set, "creating column for variable <%s>\n", var->name);
3586 	
3587 	   /* switch variable status */
3588 	   var->varstatus = SCIP_VARSTATUS_COLUMN; /*lint !e641*/
3589 	
3590 	   /* create column of variable */
3591 	   SCIP_CALL( SCIPcolCreate(&var->data.col, blkmem, set, stat, var, 0, NULL, NULL, var->removable) );
3592 	
3593 	   if( var->probindex != -1 )
3594 	   {
3595 	      /* inform problem about the variable's status change */
3596 	      SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3597 	
3598 	      /* inform LP, that problem variable is now a column variable and no longer loose */
3599 	      SCIP_CALL( SCIPlpUpdateVarColumn(lp, set, var) );
3600 	   }
3601 	
3602 	   return SCIP_OKAY;
3603 	}
3604 	
3605 	/** converts column transformed variable back into loose variable, frees LP column */
3606 	SCIP_RETCODE SCIPvarLoose(
3607 	   SCIP_VAR*             var,                /**< problem variable */
3608 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3609 	   SCIP_SET*             set,                /**< global SCIP settings */
3610 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
3611 	   SCIP_PROB*            prob,               /**< problem data */
3612 	   SCIP_LP*              lp                  /**< current LP data */
3613 	   )
3614 	{
3615 	   assert(var != NULL);
3616 	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
3617 	   assert(var->scip == set->scip);
3618 	   assert(var->data.col != NULL);
3619 	   assert(var->data.col->lppos == -1);
3620 	   assert(var->data.col->lpipos == -1);
3621 	
3622 	   SCIPsetDebugMsg(set, "deleting column for variable <%s>\n", var->name);
3623 	
3624 	   /* free column of variable */
3625 	   SCIP_CALL( SCIPcolFree(&var->data.col, blkmem, set, eventqueue, lp) );
3626 	
3627 	   /* switch variable status */
3628 	   var->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
3629 	
3630 	   if( var->probindex != -1 )
3631 	   {
3632 	      /* inform problem about the variable's status change */
3633 	      SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3634 	
3635 	      /* inform LP, that problem variable is now a loose variable and no longer a column */
3636 	      SCIP_CALL( SCIPlpUpdateVarLoose(lp, set, var) );
3637 	   }
3638 	
3639 	   return SCIP_OKAY;
3640 	}
3641 	
3642 	/** issues a VARFIXED event on the given variable and all its parents (except ORIGINAL parents);
3643 	 *  the event issuing on the parents is necessary, because unlike with bound changes, the parent variables
3644 	 *  are not informed about a fixing of an active variable they are pointing to
3645 	 */
3646 	static
3647 	SCIP_RETCODE varEventVarFixed(
3648 	   SCIP_VAR*             var,                /**< problem variable to change */
3649 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3650 	   SCIP_SET*             set,                /**< global SCIP settings */
3651 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
3652 	   int                   fixeventtype        /**< is this event a fixation(0), an aggregation(1), or a
3653 						      *   multi-aggregation(2)
3654 						      */
3655 	   )
3656 	{
3657 	   SCIP_EVENT* event;
3658 	   SCIP_VARSTATUS varstatus;
3659 	   int i;
3660 	
3661 	   assert(var != NULL);
3662 	   assert(var->scip == set->scip);
3663 	   assert(0 <= fixeventtype && fixeventtype <= 2);
3664 	
3665 	   /* issue VARFIXED event on variable */
3666 	   SCIP_CALL( SCIPeventCreateVarFixed(&event, blkmem, var) );
3667 	   SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3668 	
3669 	#ifndef NDEBUG
3670 	   for( i = var->nparentvars -1; i >= 0; --i )
3671 	   {
3672 	      assert(SCIPvarGetStatus(var->parentvars[i]) != SCIP_VARSTATUS_MULTAGGR);
3673 	   }
3674 	#endif
3675 	
3676 	   switch( fixeventtype )
3677 	   {
3678 	   case 0:
3679 	      /* process all parents of a fixed variable */
3680 	      for( i = var->nparentvars - 1; i >= 0; --i )
3681 	      {
3682 		 varstatus = SCIPvarGetStatus(var->parentvars[i]);
3683 	
3684 		 assert(varstatus != SCIP_VARSTATUS_FIXED);
3685 	
3686 		 /* issue event on all not yet fixed parent variables, (that should already issued this event) except the original
3687 		  * one
3688 		  */
3689 		 if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3690 		 {
3691 		    SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3692 		 }
3693 	      }
3694 	      break;
3695 	   case 1:
3696 	      /* process all parents of a aggregated variable */
3697 	      for( i = var->nparentvars - 1; i >= 0; --i )
3698 	      {
3699 		 varstatus = SCIPvarGetStatus(var->parentvars[i]);
3700 	
3701 		 assert(varstatus != SCIP_VARSTATUS_FIXED);
3702 	
3703 		 /* issue event for not aggregated parent variable, because for these and its parents the var event was already
3704 	          * issued(, except the original one)
3705 	          *
3706 	          * @note that even before an aggregated parent variable, there might be variables, for which the vent was not
3707 	          *       yet issued
3708 		  */
3709 	         if( varstatus == SCIP_VARSTATUS_AGGREGATED )
3710 	            continue;
3711 	
3712 		 if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3713 		 {
3714 		    SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3715 		 }
3716 	      }
3717 	      break;
3718 	   case 2:
3719 	      /* process all parents of a aggregated variable */
3720 	      for( i = var->nparentvars - 1; i >= 0; --i )
3721 	      {
3722 		 varstatus = SCIPvarGetStatus(var->parentvars[i]);
3723 	
3724 		 assert(varstatus != SCIP_VARSTATUS_FIXED);
3725 	
3726 		 /* issue event on all parent variables except the original one */
3727 		 if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3728 		 {
3729 		    SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3730 		 }
3731 	      }
3732 	      break;
3733 	   default:
3734 	      SCIPerrorMessage("unknown variable fixation event origin\n");
3735 	      return SCIP_INVALIDDATA;
3736 	   }
3737 	
3738 	   return SCIP_OKAY;
3739 	}
3740 	
3741 	/** converts variable into fixed variable */
3742 	SCIP_RETCODE SCIPvarFix(
3743 	   SCIP_VAR*             var,                /**< problem variable */
3744 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3745 	   SCIP_SET*             set,                /**< global SCIP settings */
3746 	   SCIP_STAT*            stat,               /**< problem statistics */
3747 	   SCIP_PROB*            transprob,          /**< tranformed problem data */
3748 	   SCIP_PROB*            origprob,           /**< original problem data */
3749 	   SCIP_PRIMAL*          primal,             /**< primal data */
3750 	   SCIP_TREE*            tree,               /**< branch and bound tree */
3751 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
3752 	   SCIP_LP*              lp,                 /**< current LP data */
3753 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
3754 	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter for global (not variable dependent) events */
3755 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
3756 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
3757 	   SCIP_Real             fixedval,           /**< value to fix variable at */
3758 	   SCIP_Bool*            infeasible,         /**< pointer to store whether the fixing is infeasible */
3759 	   SCIP_Bool*            fixed               /**< pointer to store whether the fixing was performed (variable was unfixed) */
3760 	   )
3761 	{
3762 	   SCIP_Real obj;
3763 	   SCIP_Real childfixedval;
3764 	
3765 	   assert(var != NULL);
3766 	   assert(var->scip == set->scip);
3767 	   assert(SCIPsetIsEQ(set, var->glbdom.lb, var->locdom.lb));
3768 	   assert(SCIPsetIsEQ(set, var->glbdom.ub, var->locdom.ub));
3769 	   assert(infeasible != NULL);
3770 	   assert(fixed != NULL);
3771 	
3772 	   SCIPsetDebugMsg(set, "fix variable <%s>[%g,%g] to %g\n", var->name, var->glbdom.lb, var->glbdom.ub, fixedval);
3773 	
3774 	   *infeasible = FALSE;
3775 	   *fixed = FALSE;
3776 	
3777 	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED )
3778 	   {
3779 	      *infeasible = !SCIPsetIsFeasEQ(set, fixedval, var->locdom.lb);
3780 	      SCIPsetDebugMsg(set, " -> variable already fixed to %g (fixedval=%g): infeasible=%u\n", var->locdom.lb, fixedval, *infeasible);
3781 	      return SCIP_OKAY;
3782 	   }
3783 	   else if( (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPsetIsFeasIntegral(set, fixedval))
3784 	      || SCIPsetIsFeasLT(set, fixedval, var->locdom.lb)
3785 	      || SCIPsetIsFeasGT(set, fixedval, var->locdom.ub) )
3786 	   {
3787 	      SCIPsetDebugMsg(set, " -> fixing infeasible: locdom=[%g,%g], fixedval=%g\n", var->locdom.lb, var->locdom.ub, fixedval);
3788 	      *infeasible = TRUE;
3789 	      return SCIP_OKAY;
3790 	   }
3791 	
3792 	   switch( SCIPvarGetStatus(var) )
3793 	   {
3794 	   case SCIP_VARSTATUS_ORIGINAL:
3795 	      if( var->data.original.transvar == NULL )
3796 	      {
3797 	         SCIPerrorMessage("cannot fix an untransformed original variable\n");
3798 	         return SCIP_INVALIDDATA;
3799 	      }
3800 	      SCIP_CALL( SCIPvarFix(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
3801 	            lp, branchcand, eventfilter, eventqueue, cliquetable, fixedval, infeasible, fixed) );
3802 	      break;
3803 	
3804 	   case SCIP_VARSTATUS_LOOSE:
3805 	      assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
3806 	
3807 	      /* set the fixed variable's objective value to 0.0 */
3808 	      obj = var->obj;
3809 	      SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
3810 	
3811 	      /* since we change the variable type form loose to fixed, we have to adjust the number of loose
3812 	       * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
3813 	       * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
3814 	       * objective of this variable is set to zero
3815 	       */
3816 	      SCIPlpDecNLoosevars(lp);
3817 	
3818 	      /* change variable's bounds to fixed value (thereby removing redundant implications and variable bounds) */
3819 	      holelistFree(&var->glbdom.holelist, blkmem);
3820 	      holelistFree(&var->locdom.holelist, blkmem);
3821 	      SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3822 	      SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3823 	
3824 	      /* explicitly set variable's bounds, even if the fixed value is in epsilon range of the old bound */
3825 	      var->glbdom.lb = fixedval;
3826 	      var->glbdom.ub = fixedval;
3827 	      var->locdom.lb = fixedval;
3828 	      var->locdom.ub = fixedval;
3829 	
3830 	      /* delete implications and variable bounds information */
3831 	      SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
3832 	      assert(var->vlbs == NULL);
3833 	      assert(var->vubs == NULL);
3834 	      assert(var->implics == NULL);
3835 	      assert(var->cliquelist == NULL);
3836 	
3837 	      /* clear the history of the variable */
3838 	      SCIPhistoryReset(var->history);
3839 	      SCIPhistoryReset(var->historycrun);
3840 	
3841 	      /* convert variable into fixed variable */
3842 	      var->varstatus = SCIP_VARSTATUS_FIXED; /*lint !e641*/
3843 	
3844 	      /* inform problem about the variable's status change */
3845 	      if( var->probindex != -1 )
3846 	      {
3847 	         SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
3848 	      }
3849 	
3850 	      /* reset the objective value of the fixed variable, thus adjusting the problem's objective offset */
3851 	      SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
3852 	
3853 	      /* issue VARFIXED event */
3854 	      SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 0) );
3855 	
3856 	      *fixed = TRUE;
3857 	      break;
3858 	
3859 	   case SCIP_VARSTATUS_COLUMN:
3860 	      SCIPerrorMessage("cannot fix a column variable\n");
3861 	      return SCIP_INVALIDDATA;
3862 	
3863 	   case SCIP_VARSTATUS_FIXED:
3864 	      SCIPerrorMessage("cannot fix a fixed variable again\n");  /*lint !e527*/
3865 	      SCIPABORT(); /* case is already handled in earlier if condition */
3866 	      return SCIP_INVALIDDATA;  /*lint !e527*/
3867 	
3868 	   case SCIP_VARSTATUS_AGGREGATED:
3869 	      /* fix aggregation variable y in x = a*y + c, instead of fixing x directly */
3870 	      assert(SCIPsetIsZero(set, var->obj));
3871 	      assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
3872 	      if( SCIPsetIsInfinity(set, fixedval) || SCIPsetIsInfinity(set, -fixedval) )
3873 	         childfixedval = (var->data.aggregate.scalar < 0.0 ? -fixedval : fixedval);
3874 	      else
3875 	         childfixedval = (fixedval - var->data.aggregate.constant)/var->data.aggregate.scalar;
3876 	      SCIP_CALL( SCIPvarFix(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3877 	            branchcand, eventfilter, eventqueue, cliquetable, childfixedval, infeasible, fixed) );
3878 	      break;
3879 	
3880 	   case SCIP_VARSTATUS_MULTAGGR:
3881 	      SCIPerrorMessage("cannot fix a multiple aggregated variable\n");
3882 	      SCIPABORT();
3883 	      return SCIP_INVALIDDATA;  /*lint !e527*/
3884 	
3885 	   case SCIP_VARSTATUS_NEGATED:
3886 	      /* fix negation variable x in x' = offset - x, instead of fixing x' directly */
3887 	      assert(SCIPsetIsZero(set, var->obj));
3888 	      assert(var->negatedvar != NULL);
3889 	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
3890 	      assert(var->negatedvar->negatedvar == var);
3891 	      SCIP_CALL( SCIPvarFix(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3892 	            branchcand, eventfilter, eventqueue, cliquetable, var->data.negate.constant - fixedval, infeasible, fixed) );
3893 	      break;
3894 	
3895 	   default:
3896 	      SCIPerrorMessage("unknown variable status\n");
3897 	      return SCIP_INVALIDDATA;
3898 	   }
3899 	
3900 	   return SCIP_OKAY;
3901 	}
3902 	
3903 	/** transforms given variables, scalars and constant to the corresponding active variables, scalars and constant
3904 	 *
3905 	 * If the number of needed active variables is greater than the available slots in the variable array, nothing happens except
3906 	 * that the required size is stored in the corresponding variable; hence, if afterwards the required size is greater than the
3907 	 * available slots (varssize), nothing happens; otherwise, the active variable representation is stored in the arrays.
3908 	 *
3909 	 * The reason for this approach is that we cannot reallocate memory, since we do not know how the
3910 	 * memory has been allocated (e.g., by a C++ 'new' or SCIP functions).
3911 	 */
3912 	SCIP_RETCODE SCIPvarGetActiveRepresentatives(
3913 	   SCIP_SET*             set,                /**< global SCIP settings */
3914 	   SCIP_VAR**            vars,               /**< variable array to get active variables */
3915 	   SCIP_Real*            scalars,            /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
3916 	   int*                  nvars,              /**< pointer to number of variables and values in vars and scalars array */
3917 	   int                   varssize,           /**< available slots in vars and scalars array */
3918 	   SCIP_Real*            constant,           /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c  */
3919 	   int*                  requiredsize,       /**< pointer to store the required array size for the active variables */
3920 	   SCIP_Bool             mergemultiples      /**< should multiple occurrences of a var be replaced by a single coeff? */
3921 	   )
3922 	{
3923 	   SCIP_VAR** activevars;
3924 	   SCIP_Real* activescalars;
3925 	   int nactivevars;
3926 	   SCIP_Real activeconstant;
3927 	   SCIP_Bool activeconstantinf;
3928 	   int activevarssize;
3929 	
3930 	   SCIP_VAR* var;
3931 	   SCIP_Real scalar;
3932 	   int v;
3933 	   int k;
3934 	
3935 	   SCIP_VAR** tmpvars;
3936 	   SCIP_VAR** multvars;
3937 	   SCIP_Real* tmpscalars;
3938 	   SCIP_Real* multscalars;
3939 	   int tmpvarssize;
3940 	   int ntmpvars;
3941 	   int nmultvars;
3942 	
3943 	   SCIP_VAR* multvar;
3944 	   SCIP_Real multscalar;
3945 	   SCIP_Real multconstant;
3946 	   int pos;
3947 	
3948 	   int noldtmpvars;
3949 	
3950 	   SCIP_VAR** tmpvars2;
3951 	   SCIP_Real* tmpscalars2;
3952 	   int tmpvarssize2;
3953 	   int ntmpvars2;
3954 	
3955 	   SCIP_Bool sortagain = FALSE;
3956 	
3957 	   assert(set != NULL);
3958 	   assert(nvars != NULL);
3959 	   assert(scalars != NULL || *nvars == 0);
3960 	   assert(constant != NULL);
3961 	   assert(requiredsize != NULL);
3962 	   assert(*nvars <= varssize);
3963 	
3964 	   *requiredsize = 0;
3965 	
(1) Event cond_false: Condition "*nvars == 0", taking false branch.
3966 	   if( *nvars == 0 )
(2) Event if_end: End of if statement.
3967 	      return SCIP_OKAY;
3968 	
3969 	   assert(vars != NULL);
3970 	
3971 	   /* handle the "easy" case of just one variable and avoid memory allocation if the variable is already active */
(3) Event cond_true: Condition "*nvars == 1", taking true branch.
(4) Event deref_parm: Directly dereferencing parameter "vars".
3972 	   if( *nvars == 1 && (vars[0]->varstatus == ((int) SCIP_VARSTATUS_COLUMN) || vars[0]->varstatus == ((int) SCIP_VARSTATUS_LOOSE)) )
3973 	   {
3974 	      *requiredsize = 1;
3975 	
3976 	      return SCIP_OKAY;
3977 	   }
3978 	
3979 	   nactivevars = 0;
3980 	   activeconstant = 0.0;
3981 	   activeconstantinf = FALSE;
3982 	   activevarssize = (*nvars) * 2;
3983 	   ntmpvars = *nvars;
3984 	   tmpvarssize = *nvars;
3985 	
3986 	   tmpvarssize2 = 1;
3987 	
3988 	   /* allocate temporary memory */
3989 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpvars2, tmpvarssize2) );
3990 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpscalars2, tmpvarssize2) );
3991 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
3992 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &activescalars, activevarssize) );
3993 	   SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
3994 	   SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpscalars, scalars, ntmpvars) );
3995 	
3996 	   /* to avoid unnecessary expanding of variable arrays while disaggregating several variables multiple times combine same variables
3997 	    * first, first get all corresponding variables with status loose, column, multaggr or fixed
3998 	    */
3999 	   for( v = ntmpvars - 1; v >= 0; --v )
4000 	   {
4001 	      var = tmpvars[v];
4002 	      scalar = tmpscalars[v];
4003 	
4004 	      assert(var != NULL);
4005 	      /* transforms given variable, scalar and constant to the corresponding active, fixed, or
4006 	       * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed
4007 	       * variable, "scalar" will be 0.0 and the value of the sum will be stored in "constant".
4008 	       */
4009 	      SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &activeconstant) );
4010 	      assert(var != NULL);
4011 	
4012 	      assert(SCIPsetIsInfinity(set, activeconstant) == (activeconstant == SCIPsetInfinity(set))); /*lint !e777*/
4013 	      assert(SCIPsetIsInfinity(set, -activeconstant) == (activeconstant == -SCIPsetInfinity(set))); /*lint !e777*/
4014 	
4015 	      activeconstantinf = SCIPsetIsInfinity(set, activeconstant) || SCIPsetIsInfinity(set, -activeconstant);
4016 	
4017 	      assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
4018 	         || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
4019 	         || SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR
4020 	         || SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED);
4021 	
4022 	      tmpvars[v] = var;
4023 	      tmpscalars[v] = scalar;
4024 	   }
4025 	   noldtmpvars = ntmpvars;
4026 	
4027 	   /* sort all variables to combine equal variables easily */
4028 	   SCIPsortPtrReal((void**)tmpvars, tmpscalars, SCIPvarComp, noldtmpvars);
4029 	   ntmpvars = 0;
4030 	   for( v = 1; v < noldtmpvars; ++v )
4031 	   {
4032 	      /* combine same variables */
4033 	      if( SCIPvarCompare(tmpvars[v], tmpvars[ntmpvars]) == 0 )
4034 	      {
4035 	         tmpscalars[ntmpvars] += tmpscalars[v];
4036 	      }
4037 	      else
4038 	      {
4039 	         ++ntmpvars;
4040 	         if( v > ntmpvars )
4041 	         {
4042 	            tmpscalars[ntmpvars] = tmpscalars[v];
4043 	            tmpvars[ntmpvars] = tmpvars[v];
4044 	         }
4045 	      }
4046 	   }
4047 	   ++ntmpvars;
4048 	
4049 	#ifdef SCIP_MORE_DEBUG
4050 	   for( v = 1; v < ntmpvars; ++v )
4051 	      assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4052 	#endif
4053 	
4054 	   /* collect for each variable the representation in active variables */
4055 	   while( ntmpvars >= 1 )
4056 	   {
4057 	      --ntmpvars;
4058 	      ntmpvars2 = 0;
4059 	      var = tmpvars[ntmpvars];
4060 	      scalar = tmpscalars[ntmpvars];
4061 	
4062 	      assert(var != NULL);
4063 	
4064 	      /* TODO: maybe we should test here on SCIPsetIsZero() instead of 0.0 */
4065 	      if( scalar == 0.0 )
4066 	         continue;
4067 	
4068 	      assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
4069 	         || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
4070 	         || SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR
4071 	         || SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED);
4072 	
4073 	      switch( SCIPvarGetStatus(var) )
4074 	      {
4075 	      case SCIP_VARSTATUS_LOOSE:
4076 	      case SCIP_VARSTATUS_COLUMN:
4077 	         /* x = a*y + c */
4078 	         if( nactivevars >= activevarssize )
4079 	         {
4080 	            activevarssize *= 2;
4081 	            SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
4082 	            SCIP_CALL( SCIPsetReallocBufferArray(set, &activescalars, activevarssize) );
4083 	            assert(nactivevars < activevarssize);
4084 	         }
4085 	         activevars[nactivevars] = var;
4086 	         activescalars[nactivevars] = scalar;
4087 	         nactivevars++;
4088 	         break;
4089 	
4090 	      case SCIP_VARSTATUS_MULTAGGR:
4091 	         /* x = a_1*y_1 + ... + a_n*y_n + c */
4092 	         nmultvars = var->data.multaggr.nvars;
4093 	         multvars = var->data.multaggr.vars;
4094 	         multscalars = var->data.multaggr.scalars;
4095 	         sortagain = TRUE;
4096 	
4097 	         if( nmultvars + ntmpvars > tmpvarssize )
4098 	         {
4099 	            while( nmultvars + ntmpvars > tmpvarssize )
4100 	               tmpvarssize *= 2;
4101 	            SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
4102 	            SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars, tmpvarssize) );
4103 	            assert(nmultvars + ntmpvars <= tmpvarssize);
4104 	         }
4105 	
4106 	         if( nmultvars > tmpvarssize2 )
4107 	         {
4108 	            while( nmultvars > tmpvarssize2 )
4109 	               tmpvarssize2 *= 2;
4110 	            SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars2, tmpvarssize2) );
4111 	            SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars2, tmpvarssize2) );
4112 	            assert(nmultvars <= tmpvarssize2);
4113 	         }
4114 	
4115 	         --nmultvars;
4116 	
4117 	         for( ; nmultvars >= 0; --nmultvars )
4118 	         {
4119 	            multvar = multvars[nmultvars];
4120 	            multscalar = multscalars[nmultvars];
4121 	            multconstant = 0;
4122 	
4123 	            assert(multvar != NULL);
4124 	            SCIP_CALL( SCIPvarGetProbvarSum(&multvar, set, &multscalar, &multconstant) );
4125 	            assert(multvar != NULL);
4126 	
4127 	            assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
4128 	               || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
4129 	               || SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR
4130 	               || SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED);
4131 	
4132 	            if( !activeconstantinf )
4133 	            {
4134 	               assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4135 	
4136 	               if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4137 	               {
4138 	                  assert(scalar != 0.0);
4139 	                  if( scalar * multconstant > 0.0 )
4140 	                  {
4141 	                     activeconstant = SCIPsetInfinity(set);
4142 	                     activeconstantinf = TRUE;
4143 	                  }
4144 	                  else
4145 	                  {
4146 	                     activeconstant = -SCIPsetInfinity(set);
4147 	                     activeconstantinf = TRUE;
4148 	                  }
4149 	               }
4150 	               else
4151 	                  activeconstant += scalar * multconstant;
4152 	            }
4153 	#ifndef NDEBUG
4154 	            else
4155 	            {
4156 	               assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4157 	                     (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4158 	               assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4159 	                     (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4160 	            }
4161 	#endif
4162 	
4163 	            if( SCIPsortedvecFindPtr((void**)tmpvars, SCIPvarComp, multvar, ntmpvars, &pos) )
4164 	            {
4165 	               assert(SCIPvarCompare(tmpvars[pos], multvar) == 0);
4166 	               tmpscalars[pos] += scalar * multscalar;
4167 	            }
4168 	            else
4169 	            {
4170 	               tmpvars2[ntmpvars2] = multvar;
4171 	               tmpscalars2[ntmpvars2] = scalar * multscalar;
4172 	               ++(ntmpvars2);
4173 	               assert(ntmpvars2 <= tmpvarssize2);
4174 	            }
4175 	         }
4176 	
4177 	         if( ntmpvars2 > 0 )
4178 	         {
4179 	            /* sort all variables to combine equal variables easily */
4180 	            SCIPsortPtrReal((void**)tmpvars2, tmpscalars2, SCIPvarComp, ntmpvars2);
4181 	            pos = 0;
4182 	            for( v = 1; v < ntmpvars2; ++v )
4183 	            {
4184 	               /* combine same variables */
4185 	               if( SCIPvarCompare(tmpvars2[v], tmpvars2[pos]) == 0 )
4186 	               {
4187 	                  tmpscalars2[pos] += tmpscalars2[v];
4188 	               }
4189 	               else
4190 	               {
4191 	                  ++pos;
4192 	                  if( v > pos )
4193 	                  {
4194 	                     tmpscalars2[pos] = tmpscalars2[v];
4195 	                     tmpvars2[pos] = tmpvars2[v];
4196 	                  }
4197 	               }
4198 	            }
4199 	            ntmpvars2 = pos + 1;
4200 	#ifdef SCIP_MORE_DEBUG
4201 	            for( v = 1; v < ntmpvars2; ++v )
4202 	            {
4203 	               assert(SCIPvarCompare(tmpvars2[v], tmpvars2[v-1]) > 0);
4204 	            }
4205 	            for( v = 1; v < ntmpvars; ++v )
4206 	            {
4207 	               assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4208 	            }
4209 	#endif
4210 	            v = ntmpvars - 1;
4211 	            k = ntmpvars2 - 1;
4212 	            pos = ntmpvars + ntmpvars2 - 1;
4213 	            ntmpvars += ntmpvars2;
4214 	
4215 	            while( v >= 0 && k >= 0 )
4216 	            {
4217 	               assert(pos >= 0);
4218 	               assert(SCIPvarCompare(tmpvars[v], tmpvars2[k]) != 0);
4219 	               if( SCIPvarCompare(tmpvars[v], tmpvars2[k]) >= 0 )
4220 	               {
4221 	                  tmpvars[pos] = tmpvars[v];
4222 	                  tmpscalars[pos] = tmpscalars[v];
4223 	                  --v;
4224 	               }
4225 	               else
4226 	               {
4227 	                  tmpvars[pos] = tmpvars2[k];
4228 	                  tmpscalars[pos] = tmpscalars2[k];
4229 	                  --k;
4230 	               }
4231 	               --pos;
4232 	               assert(pos >= 0);
4233 	            }
4234 	            while( v >= 0 )
4235 	            {
4236 	               assert(pos >= 0);
4237 	               tmpvars[pos] = tmpvars[v];
4238 	               tmpscalars[pos] = tmpscalars[v];
4239 	               --v;
4240 	               --pos;
4241 	            }
4242 	            while( k >= 0 )
4243 	            {
4244 	               assert(pos >= 0);
4245 	               tmpvars[pos] = tmpvars2[k];
4246 	               tmpscalars[pos] = tmpscalars2[k];
4247 	               --k;
4248 	               --pos;
4249 	            }
4250 	         }
4251 	#ifdef SCIP_MORE_DEBUG
4252 	         for( v = 1; v < ntmpvars; ++v )
4253 	         {
4254 	            assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4255 	         }
4256 	#endif
4257 	
4258 	         if( !activeconstantinf )
4259 	         {
4260 	            assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4261 	
4262 	            multconstant = SCIPvarGetMultaggrConstant(var);
4263 	
4264 	            if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4265 	            {
4266 	               assert(scalar != 0.0);
4267 	               if( scalar * multconstant > 0.0 )
4268 	               {
4269 	                  activeconstant = SCIPsetInfinity(set);
4270 	                  activeconstantinf = TRUE;
4271 	               }
4272 	               else
4273 	               {
4274 	                  activeconstant = -SCIPsetInfinity(set);
4275 	                  activeconstantinf = TRUE;
4276 	               }
4277 	            }
4278 	            else
4279 	               activeconstant += scalar * multconstant;
4280 	         }
4281 	#ifndef NDEBUG
4282 	         else
4283 	         {
4284 	            multconstant = SCIPvarGetMultaggrConstant(var);
4285 	            assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4286 	                  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4287 	            assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4288 	                  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4289 	         }
4290 	#endif
4291 	         break;
4292 	
4293 	      case SCIP_VARSTATUS_FIXED:
4294 	      case SCIP_VARSTATUS_ORIGINAL:
4295 	      case SCIP_VARSTATUS_AGGREGATED:
4296 	      case SCIP_VARSTATUS_NEGATED:
4297 	      default:
4298 	         /* case x = c, but actually we should not be here, since SCIPvarGetProbvarSum() returns a scalar of 0.0 for
4299 	          * fixed variables and is handled already
4300 	          */
4301 	         assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED);
4302 	         assert(SCIPsetIsZero(set, var->glbdom.lb) && SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub));
4303 	      }
4304 	   }
4305 	
4306 	   if( mergemultiples )
4307 	   {
4308 	      if( sortagain )
4309 	      {
4310 	         /* sort variable and scalar array by variable index */
4311 	         SCIPsortPtrReal((void**)activevars, activescalars, SCIPvarComp, nactivevars);
4312 	
4313 	         /* eliminate duplicates and count required size */
4314 	         v = nactivevars - 1;
4315 	         while( v > 0 )
4316 	         {
4317 	            /* combine both variable since they are the same */
4318 	            if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
4319 	            {
4320 	               if( activescalars[v - 1] + activescalars[v] != 0.0 )
4321 	               {
4322 	                  activescalars[v - 1] += activescalars[v];
4323 	                  --nactivevars;
4324 	                  activevars[v] = activevars[nactivevars];
4325 	                  activescalars[v] = activescalars[nactivevars];
4326 	               }
4327 	               else
4328 	               {
4329 	                  --nactivevars;
4330 	                  activevars[v] = activevars[nactivevars];
4331 	                  activescalars[v] = activescalars[nactivevars];
4332 	                  --nactivevars;
4333 	                  --v;
4334 	                  activevars[v] = activevars[nactivevars];
4335 	                  activescalars[v] = activescalars[nactivevars];
4336 	               }
4337 	            }
4338 	            --v;
4339 	         }
4340 	      }
4341 	      /* the variables were added in reverse order, we revert the order now;
4342 	       * this should not be necessary, but not doing this changes the behavior sometimes
4343 	       */
4344 	      else
4345 	      {
4346 	         SCIP_VAR* tmpvar;
4347 	         SCIP_Real tmpscalar;
4348 	
4349 	         for( v = 0; v < nactivevars / 2; ++v )
4350 	         {
4351 	            tmpvar = activevars[v];
4352 	            tmpscalar = activescalars[v];
4353 	            activevars[v] = activevars[nactivevars - 1 - v];
4354 	            activescalars[v] = activescalars[nactivevars - 1 - v];
4355 	            activevars[nactivevars - 1 - v] = tmpvar;
4356 	            activescalars[nactivevars - 1 - v] = tmpscalar;
4357 	         }
4358 	      }
4359 	   }
4360 	   *requiredsize = nactivevars;
4361 	
4362 	   if( varssize >= *requiredsize )
4363 	   {
4364 	      assert(vars != NULL);
4365 	
4366 	      *nvars = *requiredsize;
4367 	
4368 	      if( !SCIPsetIsInfinity(set, *constant) && !SCIPsetIsInfinity(set, -(*constant)) )
4369 	      {
4370 	         /* if the activeconstant is infinite, the constant pointer gets the same value, otherwise add the value */
4371 	         if( activeconstantinf )
4372 	            (*constant) = activeconstant;
4373 	         else
4374 	            (*constant) += activeconstant;
4375 	      }
4376 	#ifndef NDEBUG
4377 	      else
4378 	      {
4379 	         assert(!SCIPsetIsInfinity(set, (*constant)) || !SCIPsetIsInfinity(set, -activeconstant));
4380 	         assert(!SCIPsetIsInfinity(set, -(*constant)) || !SCIPsetIsInfinity(set, activeconstant));
4381 	      }
4382 	#endif
4383 	
4384 	      /* copy active variable and scalar array to the given arrays */
4385 	      for( v = 0; v < *nvars; ++v )
4386 	      {
4387 	         vars[v] = activevars[v];
4388 	         scalars[v] = activescalars[v]; /*lint !e613*/
4389 	      }
4390 	   }
4391 	
4392 	   assert(SCIPsetIsInfinity(set, *constant) == ((*constant) == SCIPsetInfinity(set))); /*lint !e777*/
4393 	   assert(SCIPsetIsInfinity(set, -(*constant)) == ((*constant) == -SCIPsetInfinity(set))); /*lint !e777*/
4394 	
4395 	   SCIPsetFreeBufferArray(set, &tmpscalars);
4396 	   SCIPsetFreeBufferArray(set, &tmpvars);
4397 	   SCIPsetFreeBufferArray(set, &activescalars);
4398 	   SCIPsetFreeBufferArray(set, &activevars);
4399 	   SCIPsetFreeBufferArray(set, &tmpscalars2);
4400 	   SCIPsetFreeBufferArray(set, &tmpvars2);
4401 	
4402 	   return SCIP_OKAY;
4403 	}
4404 	
4405 	
4406 	/** flattens aggregation graph of multi-aggregated variable in order to avoid exponential recursion later on */
4407 	SCIP_RETCODE SCIPvarFlattenAggregationGraph(
4408 	   SCIP_VAR*             var,                /**< problem variable */
4409 	   BMS_BLKMEM*           blkmem,             /**< block memory */
4410 	   SCIP_SET*             set,                /**< global SCIP settings */
4411 	   SCIP_EVENTQUEUE*      eventqueue          /**< event queue */
4412 	   )
4413 	{
4414 	   int nlocksup[NLOCKTYPES];
4415 	   int nlocksdown[NLOCKTYPES];
4416 	   SCIP_Real multconstant;
4417 	   int multvarssize;
4418 	   int nmultvars;
4419 	   int multrequiredsize;
4420 	   int i;
4421 	
4422 	   assert( var != NULL );
4423 	   assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR );
4424 	   assert(var->scip == set->scip);
4425 	
4426 	   /* in order to update the locks on the active representation of the multi-aggregated variable, we remove all locks
4427 	    * on the current representation now and re-add the locks once the variable graph has been flattened, which
4428 	    * may lead to duplicate occurences of the same variable being merged
4429 	    *
4430 	    * Here is an example. Assume we have the multi-aggregation z = x + y.
4431 	    * z occures with positive coefficient in a <= constraint c1, so it has an uplock from there.
4432 	    * When the multi-aggregation is performed, all locks are added to the active representation,
4433 	    * so x and y both get an uplock from c1. However, z was not yet replaced by x + y in c1.
4434 	    * Next, a negation y = 1 - x is identified. Again, locks are moved, so that the uplock of y originating
4435 	    * from c1 is added to x as a downlock. Thus, x has both an up- and downlock from c1.
4436 	    * The multi-aggregation changes to z = x + 1 - x, which corresponds to the locks.
4437 	    * However, before z is replaced by that sum, SCIPvarFlattenAggregationGraph() is called
4438 	    * which changes z = x + y = x + 1 - x = 1, since it merges multiple occurences of the same variable.
4439 	    * The up- and downlock of x, however, is not removed when replacing z in c1 by its active representation,
4440 	    * because it is just 1 now. Therefore, we need to update locks when flattening the aggregation graph.
4441 	    * For this, the multi-aggregated variable knows its locks in addition to adding them to the active
4442 	    * representation, which corresponds to the locks from constraints where the variable was not replaced yet.
4443 	    * By removing the locks here, based on the old representation and adding them again after flattening,
4444 	    * we ensure that the locks are correct afterwards if coefficients were merged.
4445 	    */
4446 	   for( i = 0; i < NLOCKTYPES; ++i )
4447 	   {
4448 	      nlocksup[i] = var->nlocksup[i];
4449 	      nlocksdown[i] = var->nlocksdown[i];
4450 	
4451 	      SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, -nlocksdown[i], -nlocksup[i]) );
4452 	   }
4453 	
4454 	   multconstant = var->data.multaggr.constant;
4455 	   nmultvars = var->data.multaggr.nvars;
4456 	   multvarssize = var->data.multaggr.varssize;
4457 	
4458 	   SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4459 	
4460 	   if( multrequiredsize > multvarssize )
4461 	   {
4462 	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.vars), multvarssize, multrequiredsize) );
4463 	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.scalars), multvarssize, multrequiredsize) );
4464 	      multvarssize = multrequiredsize;
4465 	      SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4466 	      assert( multrequiredsize <= multvarssize );
4467 	   }
4468 	   /**@note After the flattening the multi aggregation might resolve to be in fact an aggregation (or even a fixing?).
4469 	    * This issue is not resolved right now, since var->data.multaggr.nvars < 2 should not cause troubles. However, one
4470 	    * may loose performance hereby, since aggregated variables are easier to handle.
4471 	    *
4472 	    * Note, that there are two cases where SCIPvarFlattenAggregationGraph() is called: The easier one is that it is
4473 	    * called while installing the multi-aggregation. in principle, the described issue could be handled straightforward
4474 	    * in this case by aggregating or fixing the variable instead.  The more complicated case is the one, when the
4475 	    * multi-aggregation is used, e.g., in linear presolving (and the variable is already declared to be multi-aggregated).
4476 	    *
4477 	    * By now, it is not allowed to fix or aggregate multi-aggregated variables which would be necessary in this case.
4478 	    *
4479 	    * The same issue appears in the SCIPvarGetProbvar...() methods.
4480 	    */
4481 	
4482 	   var->data.multaggr.constant = multconstant;
4483 	   var->data.multaggr.nvars = nmultvars;
4484 	   var->data.multaggr.varssize = multvarssize;
4485 	
4486 	   for( i = 0; i < NLOCKTYPES; ++i )
4487 	   {
4488 	      SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
4489 	   }
4490 	
4491 	   return SCIP_OKAY;
4492 	}
4493 	
4494 	/** merge two variable histories together; a typical use case is that \p othervar is an image of the target variable
4495 	 *  in a SCIP copy. Method should be applied with care, especially because no internal checks are performed whether
4496 	 *  the history merge is reasonable
4497 	 *
4498 	 *  @note Do not use this method if the two variables originate from two SCIP's with different objective functions, since
4499 	 *        this corrupts the variable pseudo costs
4500 	 *  @note Apply with care; no internal checks are performed if the two variables should be merged
4501 	 */
4502 	void SCIPvarMergeHistories(
4503 	   SCIP_VAR*             targetvar,          /**< the variable that should contain both histories afterwards */
4504 	   SCIP_VAR*             othervar,           /**< the variable whose history is to be merged with that of the target variable */
4505 	   SCIP_STAT*            stat                /**< problem statistics */
4506 	   )
4507 	{
4508 	   /* merge only the history of the current run into the target history */
4509 	   SCIPhistoryUnite(targetvar->history, othervar->historycrun, FALSE);
4510 	
4511 	   /* apply the changes also to the global history */
4512 	   SCIPhistoryUnite(stat->glbhistory, othervar->historycrun, FALSE);
4513 	}
4514 	
4515 	/** sets the history of a variable; this method is typically used within reoptimization to keep and update the variable
4516 	 *  history over several iterations
4517 	 */
4518 	void SCIPvarSetHistory(
4519 	   SCIP_VAR*             var,                /**< variable */
4520 	   SCIP_HISTORY*         history,            /**< the history which is to set */
4521 	   SCIP_STAT*            stat                /**< problem statistics */
4522 	   )
4523 	{
4524 	   /* merge only the history of the current run into the target history */
4525 	   SCIPhistoryUnite(var->history, history, FALSE);
4526 	
4527 	   /* apply the changes also to the global history */
4528 	   SCIPhistoryUnite(stat->glbhistory, history, FALSE);
4529 	}
4530 	
4531 	/** tightens the bounds of both variables in aggregation x = a*y + c */
4532 	static
4533 	SCIP_RETCODE varUpdateAggregationBounds(
4534 	   SCIP_VAR*             var,                /**< problem variable */
4535 	   BMS_BLKMEM*           blkmem,             /**< block memory */
4536 	   SCIP_SET*             set,                /**< global SCIP settings */
4537 	   SCIP_STAT*            stat,               /**< problem statistics */
4538 	   SCIP_PROB*            transprob,          /**< tranformed problem data */
4539 	   SCIP_PROB*            origprob,           /**< original problem data */
4540 	   SCIP_PRIMAL*          primal,             /**< primal data */
4541 	   SCIP_TREE*            tree,               /**< branch and bound tree */
4542 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
4543 	   SCIP_LP*              lp,                 /**< current LP data */
4544 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
4545 	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter for global (not variable dependent) events */
4546 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
4547 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
4548 	   SCIP_VAR*             aggvar,             /**< variable y in aggregation x = a*y + c */
4549 	   SCIP_Real             scalar,             /**< multiplier a in aggregation x = a*y + c */
4550 	   SCIP_Real             constant,           /**< constant shift c in aggregation x = a*y + c */
4551 	   SCIP_Bool*            infeasible,         /**< pointer to store whether the aggregation is infeasible */
4552 	   SCIP_Bool*            fixed               /**< pointer to store whether the variables were fixed */
4553 	   )
4554 	{
4555 	   SCIP_Real varlb;
4556 	   SCIP_Real varub;
4557 	   SCIP_Real aggvarlb;
4558 	   SCIP_Real aggvarub;
4559 	   SCIP_Bool aggvarbdschanged;
4560 	
4561 	   assert(var != NULL);
4562 	   assert(var->scip == set->scip);
4563 	   assert(aggvar != NULL);
4564 	   assert(!SCIPsetIsZero(set, scalar));
4565 	   assert(infeasible != NULL);
4566 	   assert(fixed != NULL);
4567 	
4568 	   *infeasible = FALSE;
4569 	   *fixed = FALSE;
4570 	
4571 	   SCIPsetDebugMsg(set, "updating bounds of variables in aggregation <%s> == %g*<%s> %+g\n", var->name, scalar, aggvar->name, constant);
4572 	   SCIPsetDebugMsg(set, "  old bounds: <%s> [%g,%g]   <%s> [%g,%g]\n",
4573 	      var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4574 	
4575 	   /* loop as long additional changes may be found */
4576 	   do
4577 	   {
4578 	      aggvarbdschanged = FALSE;
4579 	
4580 	      /* update the bounds of the aggregated variable x in x = a*y + c */
4581 	      if( scalar > 0.0 )
4582 	      {
4583 	         if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4584 	            varlb = -SCIPsetInfinity(set);
4585 	         else
4586 	            varlb = aggvar->glbdom.lb * scalar + constant;
4587 	         if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4588 	            varub = SCIPsetInfinity(set);
4589 	         else
4590 	            varub = aggvar->glbdom.ub * scalar + constant;
4591 	      }
4592 	      else
4593 	      {
4594 	         if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4595 	            varub = SCIPsetInfinity(set);
4596 	         else
4597 	            varub = aggvar->glbdom.lb * scalar + constant;
4598 	         if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4599 	            varlb = -SCIPsetInfinity(set);
4600 	         else
4601 	            varlb = aggvar->glbdom.ub * scalar + constant;
4602 	      }
4603 	      varlb = MAX(varlb, var->glbdom.lb);
4604 	      varub = MIN(varub, var->glbdom.ub);
4605 	      SCIPvarAdjustLb(var, set, &varlb);
4606 	      SCIPvarAdjustUb(var, set, &varub);
4607 	
4608 	      /* check the new bounds */
4609 	      if( SCIPsetIsGT(set, varlb, varub) )
4610 	      {
4611 	         /* the aggregation is infeasible */
4612 	         *infeasible = TRUE;
4613 	         return SCIP_OKAY;
4614 	      }
4615 	      else if( SCIPsetIsEQ(set, varlb, varub) )
4616 	      {
4617 	         /* the aggregated variable is fixed -> fix both variables */
4618 	         SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4619 	               eventfilter, eventqueue, cliquetable, varlb, infeasible, fixed) );
4620 	         if( !(*infeasible) )
4621 	         {
4622 	            SCIP_Bool aggfixed;
4623 	
4624 	            SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4625 	                  eventfilter, eventqueue, cliquetable, (varlb-constant)/scalar, infeasible, &aggfixed) );
4626 	            assert(*fixed == aggfixed);
4627 	         }
4628 	         return SCIP_OKAY;
4629 	      }
4630 	      else
4631 	      {
4632 	         if( SCIPsetIsGT(set, varlb, var->glbdom.lb) )
4633 	         {
4634 	            SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varlb) );
4635 	         }
4636 	         if( SCIPsetIsLT(set, varub, var->glbdom.ub) )
4637 	         {
4638 	            SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varub) );
4639 	         }
4640 	
4641 	         /* update the hole list of the aggregation variable */
4642 	         /**@todo update hole list of aggregation variable */
4643 	      }
4644 	
4645 	      /* update the bounds of the aggregation variable y in x = a*y + c  ->  y = (x-c)/a */
4646 	      if( scalar > 0.0 )
4647 	      {
4648 	         if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4649 	            aggvarlb = -SCIPsetInfinity(set);
4650 	         else
4651 	            aggvarlb = (var->glbdom.lb - constant) / scalar;
4652 	         if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4653 	            aggvarub = SCIPsetInfinity(set);
4654 	         else
4655 	            aggvarub = (var->glbdom.ub - constant) / scalar;
4656 	      }
4657 	      else
4658 	      {
4659 	         if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4660 	            aggvarub = SCIPsetInfinity(set);
4661 	         else
4662 	            aggvarub = (var->glbdom.lb - constant) / scalar;
4663 	         if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4664 	            aggvarlb = -SCIPsetInfinity(set);
4665 	         else
4666 	            aggvarlb = (var->glbdom.ub - constant) / scalar;
4667 	      }
4668 	      aggvarlb = MAX(aggvarlb, aggvar->glbdom.lb);
4669 	      aggvarub = MIN(aggvarub, aggvar->glbdom.ub);
4670 	      SCIPvarAdjustLb(aggvar, set, &aggvarlb);
4671 	      SCIPvarAdjustUb(aggvar, set, &aggvarub);
4672 	
4673 	      /* check the new bounds */
4674 	      if( SCIPsetIsGT(set, aggvarlb, aggvarub) )
4675 	      {
4676 	         /* the aggregation is infeasible */
4677 	         *infeasible = TRUE;
4678 	         return SCIP_OKAY;
4679 	      }
4680 	      else if( SCIPsetIsEQ(set, aggvarlb, aggvarub) )
4681 	      {
4682 	         /* the aggregation variable is fixed -> fix both variables */
4683 	         SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4684 	               eventfilter, eventqueue, cliquetable, aggvarlb, infeasible, fixed) );
4685 	         if( !(*infeasible) )
4686 	         {
4687 	            SCIP_Bool varfixed;
4688 	
4689 	            SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4690 	                  eventfilter, eventqueue, cliquetable, aggvarlb * scalar + constant, infeasible, &varfixed) );
4691 	            assert(*fixed == varfixed);
4692 	         }
4693 	         return SCIP_OKAY;
4694 	      }
4695 	      else
4696 	      {
4697 	         SCIP_Real oldbd;
4698 	         if( SCIPsetIsGT(set, aggvarlb, aggvar->glbdom.lb) )
4699 	         {
4700 	            oldbd = aggvar->glbdom.lb;
4701 	            SCIP_CALL( SCIPvarChgLbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarlb) );
4702 	            aggvarbdschanged = !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.lb);
4703 	         }
4704 	         if( SCIPsetIsLT(set, aggvarub, aggvar->glbdom.ub) )
4705 	         {
4706 	            oldbd = aggvar->glbdom.ub;
4707 	            SCIP_CALL( SCIPvarChgUbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarub) );
4708 	            aggvarbdschanged = aggvarbdschanged || !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.ub);
4709 	         }
4710 	
4711 	         /* update the hole list of the aggregation variable */
4712 	         /**@todo update hole list of aggregation variable */
4713 	      }
4714 	   }
4715 	   while( aggvarbdschanged );
4716 	
4717 	   SCIPsetDebugMsg(set, "  new bounds: <%s> [%g,%g]   <%s> [%g,%g]\n",
4718 	      var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4719 	
4720 	   return SCIP_OKAY;
4721 	}
4722 	
4723 	/** converts loose variable into aggregated variable */
4724 	SCIP_RETCODE SCIPvarAggregate(
4725 	   SCIP_VAR*             var,                /**< loose problem variable */
4726 	   BMS_BLKMEM*           blkmem,             /**< block memory */
4727 	   SCIP_SET*             set,                /**< global SCIP settings */
4728 	   SCIP_STAT*            stat,               /**< problem statistics */
4729 	   SCIP_PROB*            transprob,          /**< tranformed problem data */
4730 	   SCIP_PROB*            origprob,           /**< original problem data */
4731 	   SCIP_PRIMAL*          primal,             /**< primal data */
4732 	   SCIP_TREE*            tree,               /**< branch and bound tree */
4733 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
4734 	   SCIP_LP*              lp,                 /**< current LP data */
4735 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
4736 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
4737 	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter for global (not variable dependent) events */
4738 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
4739 	   SCIP_VAR*             aggvar,             /**< loose variable y in aggregation x = a*y + c */
4740 	   SCIP_Real             scalar,             /**< multiplier a in aggregation x = a*y + c */
4741 	   SCIP_Real             constant,           /**< constant shift c in aggregation x = a*y + c */
4742 	   SCIP_Bool*            infeasible,         /**< pointer to store whether the aggregation is infeasible */
4743 	   SCIP_Bool*            aggregated          /**< pointer to store whether the aggregation was successful */
4744 	   )
4745 	{
4746 	   SCIP_VAR** vars;
4747 	   SCIP_Real* coefs;
4748 	   SCIP_Real* constants;
4749 	   SCIP_Real obj;
4750 	   SCIP_Real branchfactor;
4751 	   SCIP_Bool fixed;
4752 	   int branchpriority;
4753 	   int nlocksdown[NLOCKTYPES];
4754 	   int nlocksup[NLOCKTYPES];
4755 	   int nvbds;
4756 	   int i;
4757 	   int j;
4758 	
4759 	   assert(var != NULL);
4760 	   assert(aggvar != NULL);
4761 	   assert(var->scip == set->scip);
4762 	   assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
4763 	   assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
4764 	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
4765 	   assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
4766 	   assert(infeasible != NULL);
4767 	   assert(aggregated != NULL);
4768 	
4769 	   /* check aggregation on debugging solution */
4770 	   SCIP_CALL( SCIPdebugCheckAggregation(set, var, &aggvar, &scalar, constant, 1) ); /*lint !e506 !e774*/
4771 	
4772 	   *infeasible = FALSE;
4773 	   *aggregated = FALSE;
4774 	
4775 	   /* get active problem variable of aggregation variable */
4776 	   SCIP_CALL( SCIPvarGetProbvarSum(&aggvar, set, &scalar, &constant) );
4777 	
4778 	   /* aggregation is a fixing, if the scalar is zero */
4779 	   if( SCIPsetIsZero(set, scalar) )
4780 	   {
4781 	      SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventfilter,
4782 	            eventqueue, cliquetable, constant, infeasible, aggregated) );
4783 	      return SCIP_OKAY;
4784 	   }
4785 	
4786 	   /* don't perform the aggregation if the aggregation variable is multi-aggregated itself */
4787 	   if( SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_MULTAGGR )
4788 	      return SCIP_OKAY;
4789 	
4790 	   /**@todo currently we don't perform the aggregation if the aggregation variable has a non-empty hole list; this
4791 	    *  should be changed in the future
4792 	    */
4793 	   if( SCIPvarGetHolelistGlobal(var) != NULL )
4794 	      return SCIP_OKAY;
4795 	
4796 	   /* if the variable is not allowed to be aggregated */
4797 	   if( SCIPvarDoNotAggr(var) )
4798 	   {
4799 	      SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
4800 	      return SCIP_OKAY;
4801 	   }
4802 	
4803 	   assert(aggvar->glbdom.lb == aggvar->locdom.lb); /*lint !e777*/
4804 	   assert(aggvar->glbdom.ub == aggvar->locdom.ub); /*lint !e777*/
4805 	   assert(SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_LOOSE);
4806 	
4807 	   SCIPsetDebugMsg(set, "aggregate variable <%s>[%g,%g] == %g*<%s>[%g,%g] %+g\n", var->name, var->glbdom.lb, var->glbdom.ub,
4808 	      scalar, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub, constant);
4809 	
4810 	   /* if variable and aggregation variable are equal, the variable can be fixed: x == a*x + c  =>  x == c/(1-a) */
4811 	   if( var == aggvar )
4812 	   {
4813 	      if( SCIPsetIsEQ(set, scalar, 1.0) )
4814 	         *infeasible = !SCIPsetIsZero(set, constant);
4815 	      else
4816 	      {
4817 	         SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4818 	               eventfilter, eventqueue, cliquetable, constant/(1.0-scalar), infeasible, aggregated) );
4819 	      }
4820 	      return SCIP_OKAY;
4821 	   }
4822 	
4823 	   /* tighten the bounds of aggregated and aggregation variable */
4824 	   SCIP_CALL( varUpdateAggregationBounds(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
4825 	         branchcand, eventfilter, eventqueue, cliquetable, aggvar, scalar, constant, infeasible, &fixed) );
4826 	   if( *infeasible || fixed )
4827 	   {
4828 	      *aggregated = fixed;
4829 	      return SCIP_OKAY;
4830 	   }
4831 	
4832 	   /* delete implications and variable bounds of the aggregated variable from other variables, but keep them in the
4833 	    * aggregated variable
4834 	    */
4835 	   SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, FALSE) );
4836 	   assert(var->cliquelist == NULL);
4837 	
4838 	   /* set the aggregated variable's objective value to 0.0 */
4839 	   obj = var->obj;
4840 	   SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
4841 	
4842 	   /* unlock all locks */
4843 	   for( i = 0; i < NLOCKTYPES; i++ )
4844 	   {
4845 	      nlocksdown[i] = var->nlocksdown[i];
4846 	      nlocksup[i] = var->nlocksup[i];
4847 	
4848 	      var->nlocksdown[i] = 0;
4849 	      var->nlocksup[i] = 0;
4850 	   }
4851 	
4852 	   /* check, if variable should be used as NEGATED variable of the aggregation variable */
4853 	   if( SCIPvarIsBinary(var) && SCIPvarIsBinary(aggvar)
4854 	      && var->negatedvar == NULL && aggvar->negatedvar == NULL
4855 	      && SCIPsetIsEQ(set, scalar, -1.0) && SCIPsetIsEQ(set, constant, 1.0) )
4856 	   {
4857 	      /* link both variables as negation pair */
4858 	      var->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
4859 	      var->data.negate.constant = 1.0;
4860 	      var->negatedvar = aggvar;
4861 	      aggvar->negatedvar = var;
4862 	
4863 	      /* copy donot(mult)aggr status */
4864 	      aggvar->donotaggr |= var->donotaggr;
4865 	      aggvar->donotmultaggr |= var->donotmultaggr;
4866 	
4867 	      /* mark both variables to be non-deletable */
4868 	      SCIPvarMarkNotDeletable(var);
4869 	      SCIPvarMarkNotDeletable(aggvar);
4870 	   }
4871 	   else
4872 	   {
4873 	      /* convert variable into aggregated variable */
4874 	      var->varstatus = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
4875 	      var->data.aggregate.var = aggvar;
4876 	      var->data.aggregate.scalar = scalar;
4877 	      var->data.aggregate.constant = constant;
4878 	
4879 	      /* copy donot(mult)aggr status */
4880 	      aggvar->donotaggr |= var->donotaggr;
4881 	      aggvar->donotmultaggr |= var->donotmultaggr;
4882 	
4883 	      /* mark both variables to be non-deletable */
4884 	      SCIPvarMarkNotDeletable(var);
4885 	      SCIPvarMarkNotDeletable(aggvar);
4886 	   }
4887 	
4888 	   /* make aggregated variable a parent of the aggregation variable */
4889 	   SCIP_CALL( varAddParent(aggvar, blkmem, set, var) );
4890 	
4891 	   /* relock the variable, thus increasing the locks of the aggregation variable */
4892 	   for( i = 0; i < NLOCKTYPES; i++ )
4893 	   {
4894 	      SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
4895 	   }
4896 	
4897 	   /* move the variable bounds to the aggregation variable:
4898 	    *  - add all variable bounds again to the variable, thus adding it to the aggregation variable
4899 	    *  - free the variable bounds data structures
4900 	    */
4901 	   if( var->vlbs != NULL )
4902 	   {
4903 	      nvbds = SCIPvboundsGetNVbds(var->vlbs);
4904 	      vars = SCIPvboundsGetVars(var->vlbs);
4905 	      coefs = SCIPvboundsGetCoefs(var->vlbs);
4906 	      constants = SCIPvboundsGetConstants(var->vlbs);
4907 	      for( i = 0; i < nvbds && !(*infeasible); ++i )
4908 	      {
4909 	         SCIP_CALL( SCIPvarAddVlb(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4910 	               eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4911 	      }
4912 	   }
4913 	   if( var->vubs != NULL )
4914 	   {
4915 	      nvbds = SCIPvboundsGetNVbds(var->vubs);
4916 	      vars = SCIPvboundsGetVars(var->vubs);
4917 	      coefs = SCIPvboundsGetCoefs(var->vubs);
4918 	      constants = SCIPvboundsGetConstants(var->vubs);
4919 	      for( i = 0; i < nvbds && !(*infeasible); ++i )
4920 	      {
4921 	         SCIP_CALL( SCIPvarAddVub(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4922 	               eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4923 	      }
4924 	   }
4925 	   SCIPvboundsFree(&var->vlbs, blkmem);
4926 	   SCIPvboundsFree(&var->vubs, blkmem);
4927 	
4928 	   /* move the implications to the aggregation variable:
4929 	    *  - add all implications again to the variable, thus adding it to the aggregation variable
4930 	    *  - free the implications data structures
4931 	    */
4932 	   if( var->implics != NULL && SCIPvarGetType(aggvar) == SCIP_VARTYPE_BINARY )
4933 	   {
4934 	      assert(SCIPvarIsBinary(var));
4935 	      for( i = 0; i < 2; ++i )
4936 	      {
4937 	         SCIP_VAR** implvars;
4938 	         SCIP_BOUNDTYPE* impltypes;
4939 	         SCIP_Real* implbounds;
4940 	         int nimpls;
4941 	
4942 	         nimpls = SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i);
4943 	         implvars = SCIPimplicsGetVars(var->implics, (SCIP_Bool)i);
4944 	         impltypes = SCIPimplicsGetTypes(var->implics, (SCIP_Bool)i);
4945 	         implbounds = SCIPimplicsGetBounds(var->implics, (SCIP_Bool)i);
4946 	
4947 	         for( j = 0; j < nimpls && !(*infeasible); ++j )
4948 	         {
4949 	            /* @todo can't we omit transitive closure, because it should already have been done when adding the
4950 	             *       implication to the aggregated variable?
4951 	             */
4952 	            SCIP_CALL( SCIPvarAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
4953 	                  branchcand, eventqueue, (SCIP_Bool)i, implvars[j], impltypes[j], implbounds[j], FALSE, infeasible,
4954 	                  NULL) );
4955 	            assert(nimpls == SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i));
4956 	         }
4957 	      }
4958 	   }
4959 	   SCIPimplicsFree(&var->implics, blkmem);
4960 	
4961 	   /* add the history entries to the aggregation variable and clear the history of the aggregated variable */
4962 	   SCIPhistoryUnite(aggvar->history, var->history, scalar < 0.0);
4963 	   SCIPhistoryUnite(aggvar->historycrun, var->historycrun, scalar < 0.0);
4964 	   SCIPhistoryReset(var->history);
4965 	   SCIPhistoryReset(var->historycrun);
4966 	
4967 	   /* update flags of aggregation variable */
4968 	   aggvar->removable &= var->removable;
4969 	
4970 	   /* update branching factors and priorities of both variables to be the maximum of both variables */
4971 	   branchfactor = MAX(aggvar->branchfactor, var->branchfactor);
4972 	   branchpriority = MAX(aggvar->branchpriority, var->branchpriority);
4973 	   SCIP_CALL( SCIPvarChgBranchFactor(aggvar, set, branchfactor) );
4974 	   SCIP_CALL( SCIPvarChgBranchPriority(aggvar, branchpriority) );
4975 	   SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
4976 	   SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
4977 	
4978 	   /* update branching direction of both variables to agree to a single direction */
4979 	   if( scalar >= 0.0 )
4980 	   {
4981 	      if( (SCIP_BRANCHDIR)var->branchdirection == SCIP_BRANCHDIR_AUTO )
4982 	      {
4983 	         SCIP_CALL( SCIPvarChgBranchDirection(var, (SCIP_BRANCHDIR)aggvar->branchdirection) );
4984 	      }
4985 	      else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
4986 	      {
4987 	         SCIP_CALL( SCIPvarChgBranchDirection(aggvar, (SCIP_BRANCHDIR)var->branchdirection) );
4988 	      }
4989 	      else if( var->branchdirection != aggvar->branchdirection )
4990 	      {
4991 	         SCIP_CALL( SCIPvarChgBranchDirection(var, SCIP_BRANCHDIR_AUTO) );
4992 	      }
4993 	   }
4994 	   else
4995 	   {
4996 	      if( (SCIP_BRANCHDIR)var->branchdirection == SCIP_BRANCHDIR_AUTO )
4997 	      {
4998 	         SCIP_CALL( SCIPvarChgBranchDirection(var, SCIPbranchdirOpposite((SCIP_BRANCHDIR)aggvar->branchdirection)) );
4999 	      }
5000 	      else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
5001 	      {
5002 	         SCIP_CALL( SCIPvarChgBranchDirection(aggvar, SCIPbranchdirOpposite((SCIP_BRANCHDIR)var->branchdirection)) );
5003 	      }
5004 	      else if( var->branchdirection != aggvar->branchdirection )
5005 	      {
5006 	         SCIP_CALL( SCIPvarChgBranchDirection(var, SCIP_BRANCHDIR_AUTO) );
5007 	      }
5008 	   }
5009 	
5010 	   if( var->probindex != -1 )
5011 	   {
5012 	      /* inform problem about the variable's status change */
5013 	      SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5014 	   }
5015 	
5016 	   /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5017 	    * variable and the problem's objective offset
5018 	    */
5019 	   SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
5020 	
5021 	   /* issue VARFIXED event */
5022 	   SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 1) );
5023 	
5024 	   *aggregated = TRUE;
5025 	
5026 	   return SCIP_OKAY;
5027 	}
5028 	
5029 	/** Tries to aggregate an equality a*x + b*y == c consisting of two (implicit) integral active problem variables x and
5030 	 *  y. An integer aggregation (i.e. integral coefficients a' and b', such that a'*x + b'*y == c') is searched.
5031 	 *
5032 	 *  This can lead to the detection of infeasibility (e.g. if c' is fractional), or to a rejection of the aggregation
5033 	 *  (denoted by aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
5034 	 */
5035 	static
5036 	SCIP_RETCODE tryAggregateIntVars(
5037 	   SCIP_SET*             set,                /**< global SCIP settings */
5038 	   BMS_BLKMEM*           blkmem,             /**< block memory */
5039 	   SCIP_STAT*            stat,               /**< problem statistics */
5040 	   SCIP_PROB*            transprob,          /**< tranformed problem data */
5041 	   SCIP_PROB*            origprob,           /**< original problem data */
5042 	   SCIP_PRIMAL*          primal,             /**< primal data */
5043 	   SCIP_TREE*            tree,               /**< branch and bound tree */
5044 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
5045 	   SCIP_LP*              lp,                 /**< current LP data */
5046 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
5047 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
5048 	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter for global (not variable dependent) events */
5049 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
5050 	   SCIP_VAR*             varx,               /**< integral variable x in equality a*x + b*y == c */
5051 	   SCIP_VAR*             vary,               /**< integral variable y in equality a*x + b*y == c */
5052 	   SCIP_Real             scalarx,            /**< multiplier a in equality a*x + b*y == c */
5053 	   SCIP_Real             scalary,            /**< multiplier b in equality a*x + b*y == c */
5054 	   SCIP_Real             rhs,                /**< right hand side c in equality a*x + b*y == c */
5055 	   SCIP_Bool*            infeasible,         /**< pointer to store whether the aggregation is infeasible */
5056 	   SCIP_Bool*            aggregated          /**< pointer to store whether the aggregation was successful */
5057 	   )
5058 	{
5059 	   SCIP_VAR* aggvar;
5060 	   char aggvarname[SCIP_MAXSTRLEN];
5061 	   SCIP_Longint scalarxn = 0;
5062 	   SCIP_Longint scalarxd = 0;
5063 	   SCIP_Longint scalaryn = 0;
5064 	   SCIP_Longint scalaryd = 0;
5065 	   SCIP_Longint a;
5066 	   SCIP_Longint b;
5067 	   SCIP_Longint c;
5068 	   SCIP_Longint scm;
5069 	   SCIP_Longint gcd;
5070 	   SCIP_Longint currentclass;
5071 	   SCIP_Longint classstep;
5072 	   SCIP_Longint xsol;
5073 	   SCIP_Longint ysol;
5074 	   SCIP_Bool success;
5075 	   SCIP_VARTYPE vartype;
5076 	
5077 	#define MAXDNOM 1000000LL
5078 	
5079 	   assert(set != NULL);
5080 	   assert(blkmem != NULL);
5081 	   assert(stat != NULL);
5082 	   assert(transprob != NULL);
5083 	   assert(origprob != NULL);
5084 	   assert(tree != NULL);
5085 	   assert(lp != NULL);
5086 	   assert(cliquetable != NULL);
5087 	   assert(branchcand != NULL);
5088 	   assert(eventqueue != NULL);
5089 	   assert(varx != NULL);
5090 	   assert(vary != NULL);
5091 	   assert(varx != vary);
5092 	   assert(infeasible != NULL);
5093 	   assert(aggregated != NULL);
5094 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
5095 	   assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
5096 	   assert(SCIPvarGetType(varx) == SCIP_VARTYPE_INTEGER || SCIPvarGetType(varx) == SCIP_VARTYPE_IMPLINT);
5097 	   assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
5098 	   assert(SCIPvarGetType(vary) == SCIP_VARTYPE_INTEGER || SCIPvarGetType(vary) == SCIP_VARTYPE_IMPLINT);
5099 	   assert(!SCIPsetIsZero(set, scalarx));
5100 	   assert(!SCIPsetIsZero(set, scalary));
5101 	
5102 	   *infeasible = FALSE;
5103 	   *aggregated = FALSE;
5104 	
5105 	   /* if the variable is not allowed to be aggregated */
5106 	   if( SCIPvarDoNotAggr(varx) )
5107 	   {
5108 	      SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
5109 	      return SCIP_OKAY;
5110 	   }
5111 	
5112 	   /* get rational representation of coefficients */
5113 	   success = SCIPrealToRational(scalarx, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalarxn, &scalarxd);
5114 	   if( success )
5115 	      success = SCIPrealToRational(scalary, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalaryn, &scalaryd);
5116 	   if( !success )
5117 	      return SCIP_OKAY;
5118 	   assert(scalarxd >= 1);
5119 	   assert(scalaryd >= 1);
5120 	
5121 	   /* multiply equality with smallest common denominator */
5122 	   scm = SCIPcalcSmaComMul(scalarxd, scalaryd);
5123 	   a = (scm/scalarxd)*scalarxn;
5124 	   b = (scm/scalaryd)*scalaryn;
5125 	   rhs *= scm;
5126 	
5127 	   /* divide equality by the greatest common divisor of a and b */
5128 	   gcd = SCIPcalcGreComDiv(ABS(a), ABS(b));
5129 	   a /= gcd;
5130 	   b /= gcd;
5131 	   rhs /= gcd;
5132 	   assert(a != 0);
5133 	   assert(b != 0);
5134 	
5135 	   /* check, if right hand side is integral */
5136 	   if( !SCIPsetIsFeasIntegral(set, rhs) )
5137 	   {
5138 	      *infeasible = TRUE;
5139 	      return SCIP_OKAY;
5140 	   }
5141 	   c = (SCIP_Longint)(SCIPsetFeasFloor(set, rhs));
5142 	
5143 	   /* check that the scalar and constant in the aggregation are not too large to avoid numerical problems */
5144 	   if( REALABS((SCIP_Real)(c/a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
5145 	      || REALABS((SCIP_Real)(b)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
5146 	      || REALABS((SCIP_Real)(a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
5147 	   {
5148 	      return SCIP_OKAY;
5149 	   }
5150 	
5151 	   /* check, if we are in an easy case with either |a| = 1 or |b| = 1 */
5152 	   if( (a == 1 || a == -1) && SCIPvarGetType(vary) == SCIP_VARTYPE_INTEGER )
5153 	   {
5154 	      /* aggregate x = - b/a*y + c/a */
5155 	      /*lint --e{653}*/
5156 	      SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5157 	            branchcand, eventfilter, eventqueue, vary, (SCIP_Real)(-b/a), (SCIP_Real)(c/a), infeasible, aggregated) );
5158 	      assert(*aggregated);
5159 	      return SCIP_OKAY;
5160 	   }
5161 	   if( (b == 1 || b == -1) && SCIPvarGetType(varx) == SCIP_VARTYPE_INTEGER )
5162 	   {
5163 	      /* aggregate y = - a/b*x + c/b */
5164 	      /*lint --e{653}*/
5165 	      SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5166 	            branchcand, eventfilter, eventqueue, varx, (SCIP_Real)(-a/b), (SCIP_Real)(c/b), infeasible, aggregated) );
5167 	      assert(*aggregated);
5168 	      return SCIP_OKAY;
5169 	   }
5170 	
5171 	   /* Both variables are integers, their coefficients are not multiples of each other, and they don't have any
5172 	    * common divisor. Let (x',y') be a solution of the equality
5173 	    *   a*x + b*y == c    ->   a*x == c - b*y
5174 	    * Then x = -b*z + x', y = a*z + y' with z integral gives all solutions to the equality.
5175 	    */
5176 	
5177 	   /* find initial solution (x',y'):
5178 	    *  - find y' such that c - b*y' is a multiple of a
5179 	    *    - start in equivalence class c%a
5180 	    *    - step through classes, where each step increases class number by (-b)%a, until class 0 is visited
5181 	    *    - if equivalence class 0 is visited, we are done: y' equals the number of steps taken
5182 	    *    - because a and b don't have a common divisor, each class is visited at most once, and at most a-1 steps are needed
5183 	    *  - calculate x' with x' = (c - b*y')/a (which must be integral)
5184 	    *
5185 	    * Algorithm works for a > 0 only.
5186 	    */
5187 	   if( a < 0 )
5188 	   {
5189 	      a = -a;
5190 	      b = -b;
5191 	      c = -c;
5192 	   }
5193 	   assert(a > 0);
5194 	
5195 	   /* search upwards from ysol = 0 */
5196 	   ysol = 0;
5197 	   currentclass = c % a;
5198 	   if( currentclass < 0 )
5199 	      currentclass += a;
5200 	   assert(0 <= currentclass && currentclass < a);
5201 	
5202 	   classstep = (-b) % a;
5203 	
5204 	   if( classstep < 0 )
5205 	      classstep += a;
5206 	   assert(0 <= classstep && classstep < a);
5207 	
5208 	   while( currentclass != 0 )
5209 	   {
5210 	      assert(0 <= currentclass && currentclass < a);
5211 	      currentclass += classstep;
5212 	      if( currentclass >= a )
5213 	         currentclass -= a;
5214 	      ysol++;
5215 	   }
5216 	   assert(ysol < a);
5217 	   assert(((c - b*ysol) % a) == 0);
5218 	
5219 	   xsol = (c - b*ysol)/a;
5220 	
5221 	   /* determine variable type for new artificial variable:
5222 	    *
5223 	    * if both variables are implicit integer the new variable can be implicit too, because the integer implication on
5224 	    * these both variables should be enforced by some other variables, otherwise the new variable needs to be of
5225 	    * integral type
5226 	    */
5227 	   vartype = ((SCIPvarGetType(varx) == SCIP_VARTYPE_INTEGER || SCIPvarGetType(vary) == SCIP_VARTYPE_INTEGER)
5228 	      ? SCIP_VARTYPE_INTEGER : SCIP_VARTYPE_IMPLINT);
5229 	
5230 	   /* feasible solutions are (x,y) = (x',y') + z*(-b,a)
5231 	    * - create new integer variable z with infinite bounds
5232 	    * - aggregate variable x = -b*z + x'
5233 	    * - aggregate variable y =  a*z + y'
5234 	    * - the bounds of z are calculated automatically during aggregation
5235 	    */
5236 	   (void) SCIPsnprintf(aggvarname, SCIP_MAXSTRLEN, "agg%d", stat->nvaridx);
5237 	   SCIP_CALL( SCIPvarCreateTransformed(&aggvar, blkmem, set, stat,
5238 	         aggvarname, -SCIPsetInfinity(set), SCIPsetInfinity(set), 0.0, vartype,
5239 	         SCIPvarIsInitial(varx) || SCIPvarIsInitial(vary), SCIPvarIsRemovable(varx) && SCIPvarIsRemovable(vary),
5240 	         NULL, NULL, NULL, NULL, NULL) );
5241 	
5242 	   SCIP_CALL( SCIPprobAddVar(transprob, blkmem, set, lp, branchcand, eventfilter, eventqueue, aggvar) );
5243 	
5244 	   SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5245 	         branchcand, eventfilter, eventqueue, aggvar, (SCIP_Real)(-b), (SCIP_Real)xsol, infeasible, aggregated) );
5246 	   assert(*aggregated || *infeasible);
5247 	
5248 	   if( !(*infeasible) )
5249 	   {
5250 	      SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5251 	            branchcand, eventfilter, eventqueue, aggvar, (SCIP_Real)a, (SCIP_Real)ysol, infeasible, aggregated) );
5252 	      assert(*aggregated || *infeasible);
5253 	   }
5254 	
5255 	   /* release z */
5256 	   SCIP_CALL( SCIPvarRelease(&aggvar, blkmem, set, eventqueue, lp) );
5257 	
5258 	   return SCIP_OKAY;  /*lint !e438*/
5259 	}
5260 	
5261 	/** performs second step of SCIPaggregateVars():
5262 	 *  the variable to be aggregated is chosen among active problem variables x' and y', preferring a less strict variable
5263 	 *  type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
5264 	 *  or integers over binaries). If none of the variables is continuous, it is tried to find an integer
5265 	 *  aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
5266 	 *  the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
5267 	 *  aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
5268 	 *
5269 	 *  @todo check for fixings, infeasibility, bound changes, or domain holes:
5270 	 *     a) if there is no easy aggregation and we have one binary variable and another integer/implicit/binary variable
5271 	 *     b) for implicit integer variables with fractional aggregation scalar (we cannot (for technical reasons) and do
5272 	 *        not want to aggregate implicit integer variables, since we loose the corresponding divisibility property)
5273 	 */
5274 	SCIP_RETCODE SCIPvarTryAggregateVars(
5275 	   SCIP_SET*             set,                /**< global SCIP settings */
5276 	   BMS_BLKMEM*           blkmem,             /**< block memory */
5277 	   SCIP_STAT*            stat,               /**< problem statistics */
5278 	   SCIP_PROB*            transprob,          /**< tranformed problem data */
5279 	   SCIP_PROB*            origprob,           /**< original problem data */
5280 	   SCIP_PRIMAL*          primal,             /**< primal data */
5281 	   SCIP_TREE*            tree,               /**< branch and bound tree */
5282 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
5283 	   SCIP_LP*              lp,                 /**< current LP data */
5284 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
5285 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
5286 	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter for global (not variable dependent) events */
5287 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
5288 	   SCIP_VAR*             varx,               /**< variable x in equality a*x + b*y == c */
5289 	   SCIP_VAR*             vary,               /**< variable y in equality a*x + b*y == c */
5290 	   SCIP_Real             scalarx,            /**< multiplier a in equality a*x + b*y == c */
5291 	   SCIP_Real             scalary,            /**< multiplier b in equality a*x + b*y == c */
5292 	   SCIP_Real             rhs,                /**< right hand side c in equality a*x + b*y == c */
5293 	   SCIP_Bool*            infeasible,         /**< pointer to store whether the aggregation is infeasible */
5294 	   SCIP_Bool*            aggregated          /**< pointer to store whether the aggregation was successful */
5295 	   )
5296 	{
5297 	   SCIP_Bool easyaggr;
5298 	   SCIP_Real maxscalar;
5299 	   SCIP_Real absquot;
5300 	
5301 	   assert(set != NULL);
5302 	   assert(blkmem != NULL);
5303 	   assert(stat != NULL);
5304 	   assert(transprob != NULL);
5305 	   assert(origprob != NULL);
5306 	   assert(tree != NULL);
5307 	   assert(lp != NULL);
5308 	   assert(cliquetable != NULL);
5309 	   assert(branchcand != NULL);
5310 	   assert(eventqueue != NULL);
5311 	   assert(varx != NULL);
5312 	   assert(vary != NULL);
5313 	   assert(varx != vary);
5314 	   assert(infeasible != NULL);
5315 	   assert(aggregated != NULL);
5316 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
5317 	   assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
5318 	   assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
5319 	   assert(!SCIPsetIsZero(set, scalarx));
5320 	   assert(!SCIPsetIsZero(set, scalary));
5321 	
5322 	   *infeasible = FALSE;
5323 	   *aggregated = FALSE;
5324 	
5325 	   absquot = REALABS(scalarx / scalary);
5326 	   maxscalar = SCIPsetFeastol(set) / SCIPsetEpsilon(set);
5327 	   maxscalar = MAX(maxscalar, 1.0);
5328 	
5329 	   if( absquot > maxscalar || absquot < 1 / maxscalar )
5330 	      return SCIP_OKAY;
5331 	
5332 	   /* prefer aggregating the variable of more general type (preferred aggregation variable is varx) */
5333 	   if( SCIPvarGetType(vary) > SCIPvarGetType(varx) ||
5334 	         (SCIPvarGetType(vary) == SCIPvarGetType(varx) && !SCIPvarIsBinary(vary) && SCIPvarIsBinary(varx))  )
5335 	   {
5336 	      SCIP_VAR* var;
5337 	      SCIP_Real scalar;
5338 	
5339 	      /* switch the variables, such that varx is the variable of more general type (cont > implint > int > bin) */
5340 	      var = vary;
5341 	      vary = varx;
5342 	      varx = var;
5343 	      scalar = scalary;
5344 	      scalary = scalarx;
5345 	      scalarx = scalar;
5346 	   }
5347 	
5348 	   /* don't aggregate if the aggregation would lead to a binary variable aggregated to a non-binary variable */
5349 	   if( SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary) )
5350 	      return SCIP_OKAY;
5351 	
5352 	   assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5353 	
5354 	   /* figure out, which variable should be aggregated */
5355 	   easyaggr = FALSE;
5356 	
5357 	   /* check if it is an easy aggregation that means:
5358 	    *
5359 	    *   a*x + b*y == c -> x == -b/a * y + c/a iff |b/a| > feastol and |a/b| > feastol
5360 	    */
5361 	   if( !SCIPsetIsFeasZero(set, scalary/scalarx) && !SCIPsetIsFeasZero(set, scalarx/scalary) )
5362 	   {
5363 	      if( SCIPvarGetType(varx) == SCIP_VARTYPE_CONTINUOUS && SCIPvarGetType(vary) < SCIP_VARTYPE_CONTINUOUS )
5364 	      {
5365 	         easyaggr = TRUE;
5366 	      }
5367 	      else if( SCIPsetIsFeasIntegral(set, scalary/scalarx) )
5368 	      {
5369 	         easyaggr = TRUE;
5370 	      }
5371 	      else if( SCIPsetIsFeasIntegral(set, scalarx/scalary) && SCIPvarGetType(vary) == SCIPvarGetType(varx) )
5372 	      {
5373 	         /* we have an easy aggregation if we flip the variables x and y */
5374 	         SCIP_VAR* var;
5375 	         SCIP_Real scalar;
5376 	
5377 	         /* switch the variables, such that varx is the aggregated variable */
5378 	         var = vary;
5379 	         vary = varx;
5380 	         varx = var;
5381 	         scalar = scalary;
5382 	         scalary = scalarx;
5383 	         scalarx = scalar;
5384 	         easyaggr = TRUE;
5385 	      }
5386 	      else if( SCIPvarGetType(varx) == SCIP_VARTYPE_CONTINUOUS )
5387 	      {
5388 	         /* the aggregation is still easy if both variables are continuous */
5389 	         assert(SCIPvarGetType(vary) == SCIP_VARTYPE_CONTINUOUS); /* otherwise we are in the first case */
5390 	         easyaggr = TRUE;
5391 	      }
5392 	   }
5393 	
5394 	   /* did we find an "easy" aggregation? */
5395 	   if( easyaggr )
5396 	   {
5397 	      SCIP_Real scalar;
5398 	      SCIP_Real constant;
5399 	
5400 	      assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5401 	
5402 	      /* calculate aggregation scalar and constant: a*x + b*y == c  =>  x == -b/a * y + c/a */
5403 	      scalar = -scalary/scalarx;
5404 	      constant = rhs/scalarx;
5405 	
5406 	      if( REALABS(constant) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
5407 	         return SCIP_OKAY;
5408 	
5409 	      /* check aggregation for integer feasibility */
5410 	      if( SCIPvarGetType(varx) != SCIP_VARTYPE_CONTINUOUS
5411 	         && SCIPvarGetType(vary) != SCIP_VARTYPE_CONTINUOUS
5412 	         && SCIPsetIsFeasIntegral(set, scalar) && !SCIPsetIsFeasIntegral(set, constant) )
5413 	      {
5414 	         *infeasible = TRUE;
5415 	         return SCIP_OKAY;
5416 	      }
5417 	
5418 	      /* if the aggregation scalar is fractional, we cannot (for technical reasons) and do not want to aggregate implicit integer variables,
5419 	       * since then we would loose the corresponding divisibility property
5420 	       */
5421 	      assert(SCIPvarGetType(varx) != SCIP_VARTYPE_IMPLINT || SCIPsetIsFeasIntegral(set, scalar));
5422 	
5423 	      /* aggregate the variable */
5424 	      SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5425 	            branchcand, eventfilter, eventqueue, vary, scalar, constant, infeasible, aggregated) );
5426 	      assert(*aggregated || *infeasible);
5427 	   }
5428 	   else if( (SCIPvarGetType(varx) == SCIP_VARTYPE_INTEGER || SCIPvarGetType(varx) == SCIP_VARTYPE_IMPLINT)
5429 	      && (SCIPvarGetType(vary) == SCIP_VARTYPE_INTEGER || SCIPvarGetType(vary) == SCIP_VARTYPE_IMPLINT) )
5430 	   {
5431 	      /* the variables are both integral: we have to try to find an integer aggregation */
5432 	      SCIP_CALL( tryAggregateIntVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5433 	            branchcand, eventfilter, eventqueue, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
5434 	   }
5435 	
5436 	   return SCIP_OKAY;
5437 	}
5438 	
5439 	/** converts variable into multi-aggregated variable */
5440 	SCIP_RETCODE SCIPvarMultiaggregate(
5441 	   SCIP_VAR*             var,                /**< problem variable */
5442 	   BMS_BLKMEM*           blkmem,             /**< block memory */
5443 	   SCIP_SET*             set,                /**< global SCIP settings */
5444 	   SCIP_STAT*            stat,               /**< problem statistics */
5445 	   SCIP_PROB*            transprob,          /**< tranformed problem data */
5446 	   SCIP_PROB*            origprob,           /**< original problem data */
5447 	   SCIP_PRIMAL*          primal,             /**< primal data */
5448 	   SCIP_TREE*            tree,               /**< branch and bound tree */
5449 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
5450 	   SCIP_LP*              lp,                 /**< current LP data */
5451 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
5452 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
5453 	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter for global (not variable dependent) events */
5454 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
5455 	   int                   naggvars,           /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5456 	   SCIP_VAR**            aggvars,            /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5457 	   SCIP_Real*            scalars,            /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5458 	   SCIP_Real             constant,           /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5459 	   SCIP_Bool*            infeasible,         /**< pointer to store whether the aggregation is infeasible */
5460 	   SCIP_Bool*            aggregated          /**< pointer to store whether the aggregation was successful */
5461 	   )
5462 	{
5463 	   SCIP_VAR** tmpvars;
5464 	   SCIP_Real* tmpscalars;
5465 	   SCIP_Real obj;
5466 	   SCIP_Real branchfactor;
5467 	   int branchpriority;
5468 	   SCIP_BRANCHDIR branchdirection;
5469 	   int nlocksdown[NLOCKTYPES];
5470 	   int nlocksup[NLOCKTYPES];
5471 	   int v;
5472 	   SCIP_Real tmpconstant;
5473 	   SCIP_Real tmpscalar;
5474 	   int ntmpvars;
5475 	   int tmpvarssize;
5476 	   int tmprequiredsize;
5477 	   int i;
5478 	
5479 	   assert(var != NULL);
5480 	   assert(var->scip == set->scip);
5481 	   assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
5482 	   assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
5483 	   assert(naggvars == 0 || aggvars != NULL);
5484 	   assert(naggvars == 0 || scalars != NULL);
5485 	   assert(infeasible != NULL);
5486 	   assert(aggregated != NULL);
5487 	
5488 	   SCIPsetDebugMsg(set, "trying multi-aggregating variable <%s> == ...%d vars... %+g\n", var->name, naggvars, constant);
5489 	
5490 	   /* check multi-aggregation on debugging solution */
5491 	   SCIP_CALL( SCIPdebugCheckAggregation(set, var, aggvars, scalars, constant, naggvars) ); /*lint !e506 !e774*/
5492 	
5493 	   *infeasible = FALSE;
5494 	   *aggregated = FALSE;
5495 	
5496 	   switch( SCIPvarGetStatus(var) )
5497 	   {
5498 	   case SCIP_VARSTATUS_ORIGINAL:
5499 	      if( var->data.original.transvar == NULL )
5500 	      {
5501 	         SCIPerrorMessage("cannot multi-aggregate an untransformed original variable\n");
5502 	         return SCIP_INVALIDDATA;
5503 	      }
5504 	      SCIP_CALL( SCIPvarMultiaggregate(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
5505 	            reopt, lp, cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
5506 	      break;
5507 	
5508 	   case SCIP_VARSTATUS_LOOSE:
5509 	      assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
5510 	
5511 	      /* check if we would create a self-reference */
5512 	      ntmpvars = naggvars;
5513 	      tmpvarssize = naggvars;
5514 	      tmpconstant = constant;
5515 	      SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpvars, aggvars, ntmpvars) );
5516 	      SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpscalars, scalars, ntmpvars) );
5517 	
5518 	      /* get all active variables for multi-aggregation */
5519 	      SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5520 	      if( tmprequiredsize > tmpvarssize )
5521 	      {
5522 	         SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpvars, tmpvarssize, tmprequiredsize) );
5523 	         SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize, tmprequiredsize) );
5524 	         tmpvarssize = tmprequiredsize;
5525 	         SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5526 	         assert( tmprequiredsize <= tmpvarssize );
5527 	      }
5528 	
5529 	      tmpscalar = 0.0;
5530 	
5531 	      /* iterate over all active variables of the multi-aggregation and filter all variables which are equal to the
5532 	       * possible multi-aggregated variable
5533 	       */
5534 	      for( v = ntmpvars - 1; v >= 0; --v )
5535 	      {
5536 	         assert(tmpvars[v] != NULL);
5537 	         assert(SCIPvarGetStatus(tmpvars[v]) == SCIP_VARSTATUS_LOOSE);
5538 	
5539 	         if( tmpvars[v]->index == var->index )
5540 	         {
5541 	            tmpscalar += tmpscalars[v];
5542 	            tmpvars[v] = tmpvars[ntmpvars - 1];
5543 	            tmpscalars[v] = tmpscalars[ntmpvars - 1];
5544 	            --ntmpvars;
5545 	         }
5546 	      }
5547 	
5548 	      /* this means that x = x + a_1*y_1 + ... + a_n*y_n + c */
5549 	      if( SCIPsetIsEQ(set, tmpscalar, 1.0) )
5550 	      {
5551 	         if( ntmpvars == 0 )
5552 	         {
5553 	            if( SCIPsetIsZero(set, tmpconstant) ) /* x = x */
5554 	            {
5555 	               SCIPsetDebugMsg(set, "Possible multi-aggregation was completely resolved and detected to be redundant.\n");
5556 	               goto TERMINATE;
5557 	            }
5558 	            else /* 0 = c and c != 0 */
5559 	            {
5560 	               SCIPsetDebugMsg(set, "Multi-aggregation was completely resolved and led to infeasibility.\n");
5561 	               *infeasible = TRUE;
5562 	               goto TERMINATE;
5563 	            }
5564 	         }
5565 	         else if( ntmpvars == 1 ) /* 0 = a*y + c => y = -c/a */
5566 	         {
5567 	            assert(tmpscalars[0] != 0.0);
5568 	            assert(tmpvars[0] != NULL);
5569 	
5570 	            SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(tmpvars[0]), -constant/tmpscalars[0]);
5571 	            SCIP_CALL( SCIPvarFix(tmpvars[0], blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5572 	                  branchcand, eventfilter, eventqueue, cliquetable, -constant/tmpscalars[0], infeasible, aggregated) );
5573 	            goto TERMINATE;
5574 	         }
5575 	         else if( ntmpvars == 2 ) /* 0 = a_1*y_1 + a_2*y_2 + c => y_1 = -a_2/a_1 * y_2 - c/a_1 */
5576 	         {
5577 	            /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
5578 	            SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5579 	                  SCIPvarGetName(tmpvars[0]), SCIPvarGetName(tmpvars[1]), tmpscalars[0], tmpscalars[1], -tmpconstant);
5580 	
5581 	            SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5582 	                  cliquetable, branchcand, eventfilter, eventqueue, tmpvars[0], tmpvars[1], tmpscalars[0],
5583 	                  tmpscalars[1], -tmpconstant, infeasible, aggregated) );
5584 	
5585 	            goto TERMINATE;
5586 	         }
5587 	         else
5588 	            /* @todo: it is possible to multi-aggregate another variable, does it make sense?,
5589 	             *        rest looks like 0 = a_1*y_1 + ... + a_n*y_n + c and has at least three variables
5590 	             */
5591 	            goto TERMINATE;
5592 	      }
5593 	      /* this means that x = b*x + a_1*y_1 + ... + a_n*y_n + c */
5594 	      else if( !SCIPsetIsZero(set, tmpscalar) )
5595 	      {
5596 	         tmpscalar = 1 - tmpscalar;
5597 	         tmpconstant /= tmpscalar;
5598 	         for( v = ntmpvars - 1; v >= 0; --v )
5599 	            tmpscalars[v] /= tmpscalar;
5600 	      }
5601 	
5602 	      /* check, if we are in one of the simple cases */
5603 	      if( ntmpvars == 0 )
5604 	      {
5605 	         SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(var), tmpconstant);
5606 	         SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
5607 	               eventfilter, eventqueue, cliquetable, tmpconstant, infeasible, aggregated) );
5608 	         goto TERMINATE;
5609 	      }
5610 	
5611 	      /* if only one aggregation variable is left, we perform a normal aggregation instead of a multi-aggregation */
5612 	      if( ntmpvars == 1 )
5613 	      {
5614 	         SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5615 	            SCIPvarGetName(var), SCIPvarGetName(tmpvars[0]), 1.0, -tmpscalars[0], tmpconstant);
5616 	
5617 	         SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5618 	               cliquetable, branchcand, eventfilter, eventqueue, var, tmpvars[0], 1.0, -tmpscalars[0], tmpconstant,
5619 	               infeasible, aggregated) );
5620 	
5621 	         goto TERMINATE;
5622 	      }
5623 	
5624 	      /**@todo currently we don't perform the multi aggregation if the multi aggregation variable has a non
5625 	       *  empty hole list; this should be changed in the future  */
5626 	      if( SCIPvarGetHolelistGlobal(var) != NULL )
5627 	         goto TERMINATE;
5628 	
5629 	      /* if the variable is not allowed to be multi-aggregated */
5630 	      if( SCIPvarDoNotMultaggr(var) )
5631 	      {
5632 	         SCIPsetDebugMsg(set, "variable is not allowed to be multi-aggregated.\n");
5633 	         goto TERMINATE;
5634 	      }
5635 	
5636 	      /* if the variable to be multi-aggregated has implications or variable bounds (i.e. is the implied variable or
5637 	       * variable bound variable of another variable), we have to remove it from the other variables implications or
5638 	       * variable bounds
5639 	       */
5640 	      SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5641 	      assert(var->vlbs == NULL);
5642 	      assert(var->vubs == NULL);
5643 	      assert(var->implics == NULL);
5644 	      assert(var->cliquelist == NULL);
5645 	
5646 	      /* set the aggregated variable's objective value to 0.0 */
5647 	      obj = var->obj;
5648 	      SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
5649 	
5650 	      /* since we change the variable type form loose to multi aggregated, we have to adjust the number of loose
5651 	       * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
5652 	       * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
5653 	       * objective of this variable is set to zero
5654 	       */
5655 	      SCIPlpDecNLoosevars(lp);
5656 	
5657 	      /* unlock all rounding locks */
5658 	      for( i = 0; i < NLOCKTYPES; i++ )
5659 	      {
5660 	         nlocksdown[i] = var->nlocksdown[i];
5661 	         nlocksup[i] = var->nlocksup[i];
5662 	
5663 	         var->nlocksdown[i] = 0;
5664 	         var->nlocksup[i] = 0;
5665 	      }
5666 	
5667 	      /* convert variable into multi-aggregated variable */
5668 	      var->varstatus = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
5669 	      SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.vars, tmpvars, ntmpvars) );
5670 	      SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.scalars, tmpscalars, ntmpvars) );
5671 	      var->data.multaggr.constant = tmpconstant;
5672 	      var->data.multaggr.nvars = ntmpvars;
5673 	      var->data.multaggr.varssize = ntmpvars;
5674 	
5675 	      /* mark variable to be non-deletable */
5676 	      SCIPvarMarkNotDeletable(var);
5677 	
5678 	      /* relock the variable, thus increasing the locks of the aggregation variables */
5679 	      for( i = 0; i < NLOCKTYPES; i++ )
5680 	      {
5681 	         SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
5682 	      }
5683 	
5684 	      /* update flags and branching factors and priorities of aggregation variables;
5685 	       * update preferred branching direction of all aggregation variables that don't have a preferred direction yet
5686 	       */
5687 	      branchfactor = var->branchfactor;
5688 	      branchpriority = var->branchpriority;
5689 	      branchdirection = (SCIP_BRANCHDIR)var->branchdirection;
5690 	
5691 	      for( v = 0; v < ntmpvars; ++v )
5692 	      {
5693 	         assert(tmpvars[v] != NULL);
5694 	         tmpvars[v]->removable &= var->removable;
5695 	         branchfactor = MAX(tmpvars[v]->branchfactor, branchfactor);
5696 	         branchpriority = MAX(tmpvars[v]->branchpriority, branchpriority);
5697 	
5698 	         /* mark variable to be non-deletable */
5699 	         SCIPvarMarkNotDeletable(tmpvars[v]);
5700 	      }
5701 	      for( v = 0; v < ntmpvars; ++v )
5702 	      {
5703 	         SCIP_CALL( SCIPvarChgBranchFactor(tmpvars[v], set, branchfactor) );
5704 	         SCIP_CALL( SCIPvarChgBranchPriority(tmpvars[v], branchpriority) );
5705 	         if( (SCIP_BRANCHDIR)tmpvars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
5706 	         {
5707 	            if( tmpscalars[v] >= 0.0 )
5708 	            {
5709 	               SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], branchdirection) );
5710 	            }
5711 	            else
5712 	            {
5713 	               SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], SCIPbranchdirOpposite(branchdirection)) );
5714 	            }
5715 	         }
5716 	      }
5717 	      SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
5718 	      SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
5719 	
5720 	      if( var->probindex != -1 )
5721 	      {
5722 	         /* inform problem about the variable's status change */
5723 	         SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5724 	      }
5725 	
5726 	      /* issue VARFIXED event */
5727 	      SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 2) );
5728 	
5729 	      /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5730 	       * variables and the problem's objective offset
5731 	       */
5732 	      SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
5733 	
5734 	      *aggregated = TRUE;
5735 	
5736 	   TERMINATE:
5737 	      BMSfreeBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize);
5738 	      BMSfreeBlockMemoryArray(blkmem, &tmpvars, tmpvarssize);
5739 	
5740 	      break;
5741 	
5742 	   case SCIP_VARSTATUS_COLUMN:
5743 	      SCIPerrorMessage("cannot multi-aggregate a column variable\n");
5744 	      return SCIP_INVALIDDATA;
5745 	
5746 	   case SCIP_VARSTATUS_FIXED:
5747 	      SCIPerrorMessage("cannot multi-aggregate a fixed variable\n");
5748 	      return SCIP_INVALIDDATA;
5749 	
5750 	   case SCIP_VARSTATUS_AGGREGATED:
5751 	      SCIPerrorMessage("cannot multi-aggregate an aggregated variable\n");
5752 	      return SCIP_INVALIDDATA;
5753 	
5754 	   case SCIP_VARSTATUS_MULTAGGR:
5755 	      SCIPerrorMessage("cannot multi-aggregate a multiple aggregated variable again\n");
5756 	      return SCIP_INVALIDDATA;
5757 	
5758 	   case SCIP_VARSTATUS_NEGATED:
5759 	      /* aggregate negation variable x in x' = offset - x, instead of aggregating x' directly:
5760 	       *   x' = a_1*y_1 + ... + a_n*y_n + c  ->  x = offset - x' = offset - a_1*y_1 - ... - a_n*y_n - c
5761 	       */
5762 	      assert(SCIPsetIsZero(set, var->obj));
5763 	      assert(var->negatedvar != NULL);
5764 	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
5765 	      assert(var->negatedvar->negatedvar == var);
5766 	
5767 	      /* switch the signs of the aggregation scalars */
5768 	      for( v = 0; v < naggvars; ++v )
5769 	         scalars[v] *= -1.0;
5770 	
5771 	      /* perform the multi aggregation on the negation variable */
5772 	      SCIP_CALL( SCIPvarMultiaggregate(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5773 	            cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars,
5774 	            var->data.negate.constant - constant, infeasible, aggregated) );
5775 	
5776 	      /* switch the signs of the aggregation scalars again, to reset them to their original values */
5777 	      for( v = 0; v < naggvars; ++v )
5778 	         scalars[v] *= -1.0;
5779 	      break;
5780 	
5781 	   default:
5782 	      SCIPerrorMessage("unknown variable status\n");
5783 	      return SCIP_INVALIDDATA;
5784 	   }
5785 	
5786 	   return SCIP_OKAY;
5787 	}
5788 	
5789 	/** transformed variables are resolved to their active, fixed, or multi-aggregated problem variable of a variable,
5790 	 * or for original variables the same variable is returned
5791 	 */
5792 	static
5793 	SCIP_VAR* varGetActiveVar(
5794 	   SCIP_VAR*             var                 /**< problem variable */
5795 	   )
5796 	{
5797 	   SCIP_VAR* retvar;
5798 	
5799 	   assert(var != NULL);
5800 	
5801 	   retvar = var;
5802 	
5803 	   SCIPdebugMessage("get active variable of <%s>\n", var->name);
5804 	
5805 	   while( TRUE ) /*lint !e716 */
5806 	   {
5807 	      assert(retvar != NULL);
5808 	
5809 	      switch( SCIPvarGetStatus(retvar) )
5810 	      {
5811 	      case SCIP_VARSTATUS_ORIGINAL:
5812 	      case SCIP_VARSTATUS_LOOSE:
5813 	      case SCIP_VARSTATUS_COLUMN:
5814 	      case SCIP_VARSTATUS_FIXED:
5815 		 return retvar;
5816 	
5817 	      case SCIP_VARSTATUS_MULTAGGR:
5818 		 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
5819 		 if ( retvar->data.multaggr.nvars == 1 )
5820 		    retvar = retvar->data.multaggr.vars[0];
5821 		 else
5822 		    return retvar;
5823 		 break;
5824 	
5825 	      case SCIP_VARSTATUS_AGGREGATED:
5826 		 retvar = retvar->data.aggregate.var;
5827 		 break;
5828 	
5829 	      case SCIP_VARSTATUS_NEGATED:
5830 		 retvar = retvar->negatedvar;
5831 		 break;
5832 	
5833 	      default:
5834 		 SCIPerrorMessage("unknown variable status\n");
5835 		 SCIPABORT();
5836 		 return NULL; /*lint !e527*/
5837 	      }
5838 	   }
5839 	}
5840 	
5841 	/** returns whether variable is not allowed to be aggregated */
5842 	SCIP_Bool SCIPvarDoNotAggr(
5843 	   SCIP_VAR*             var                 /**< problem variable */
5844 	   )
5845 	{
5846 	   SCIP_VAR* retvar;
5847 	
5848 	   assert(var != NULL);
5849 	
5850 	   retvar = varGetActiveVar(var);
5851 	   assert(retvar != NULL);
5852 	
5853 	   switch( SCIPvarGetStatus(retvar) )
5854 	   {
5855 	   case SCIP_VARSTATUS_ORIGINAL:
5856 	   case SCIP_VARSTATUS_LOOSE:
5857 	   case SCIP_VARSTATUS_COLUMN:
5858 	   case SCIP_VARSTATUS_FIXED:
5859 	      return retvar->donotaggr;
5860 	
5861 	   case SCIP_VARSTATUS_MULTAGGR:
5862 	      return FALSE;
5863 	
5864 	   case SCIP_VARSTATUS_AGGREGATED:
5865 	   case SCIP_VARSTATUS_NEGATED:
5866 	   default:
5867 	      /* aggregated and negated variables should be resolved by varGetActiveVar() */
5868 	      SCIPerrorMessage("wrong variable status\n");
5869 	      SCIPABORT();
5870 	      return FALSE; /*lint !e527 */
5871 	   }
5872 	}
5873 	
5874 	/** returns whether variable is not allowed to be multi-aggregated */
5875 	SCIP_Bool SCIPvarDoNotMultaggr(
5876 	   SCIP_VAR*             var                 /**< problem variable */
5877 	   )
5878 	{
5879 	   SCIP_VAR* retvar;
5880 	
5881 	   assert(var != NULL);
5882 	
5883 	   retvar = varGetActiveVar(var);
5884 	   assert(retvar != NULL);
5885 	
5886 	   switch( SCIPvarGetStatus(retvar) )
5887 	   {
5888 	   case SCIP_VARSTATUS_ORIGINAL:
5889 	   case SCIP_VARSTATUS_LOOSE:
5890 	   case SCIP_VARSTATUS_COLUMN:
5891 	   case SCIP_VARSTATUS_FIXED:
5892 	      return retvar->donotmultaggr;
5893 	
5894 	   case SCIP_VARSTATUS_MULTAGGR:
5895 	      return FALSE;
5896 	
5897 	   case SCIP_VARSTATUS_AGGREGATED:
5898 	   case SCIP_VARSTATUS_NEGATED:
5899 	   default:
5900 	      /* aggregated and negated variables should be resolved by varGetActiveVar() */
5901 	      SCIPerrorMessage("wrong variable status\n");
5902 	      SCIPABORT();
5903 	      return FALSE; /*lint !e527 */
5904 	   }
5905 	}
5906 	
5907 	/** gets negated variable x' = offset - x of problem variable x; the negated variable is created if not yet existing;
5908 	 *  the negation offset of binary variables is always 1, the offset of other variables is fixed to lb + ub when the
5909 	 *  negated variable is created
5910 	 */
5911 	SCIP_RETCODE SCIPvarNegate(
5912 	   SCIP_VAR*             var,                /**< problem variable to negate */
5913 	   BMS_BLKMEM*           blkmem,             /**< block memory of transformed problem */
5914 	   SCIP_SET*             set,                /**< global SCIP settings */
5915 	   SCIP_STAT*            stat,               /**< problem statistics */
5916 	   SCIP_VAR**            negvar              /**< pointer to store the negated variable */
5917 	   )
5918 	{
5919 	   assert(var != NULL);
5920 	   assert(var->scip == set->scip);
5921 	   assert(negvar != NULL);
5922 	
5923 	   /* check, if we already created the negated variable */
5924 	   if( var->negatedvar == NULL )
5925 	   {
5926 	      char negvarname[SCIP_MAXSTRLEN];
5927 	
5928 	      assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED);
5929 	
5930 	      SCIPsetDebugMsg(set, "creating negated variable of <%s>\n", var->name);
5931 	
5932 	      /* negation is only possible for bounded variables */
5933 	      if( SCIPsetIsInfinity(set, -var->glbdom.lb) || SCIPsetIsInfinity(set, var->glbdom.ub) )
5934 	      {
5935 	         SCIPerrorMessage("cannot negate unbounded variable\n");
5936 	         return SCIP_INVALIDDATA;
5937 	      }
5938 	
5939 	      (void) SCIPsnprintf(negvarname, SCIP_MAXSTRLEN, "%s_neg", var->name);
5940 	
5941 	      /* create negated variable */
5942 	      SCIP_CALL( varCreate(negvar, blkmem, set, stat, negvarname, var->glbdom.lb, var->glbdom.ub, 0.0,
5943 	            SCIPvarGetType(var), var->initial, var->removable, NULL, NULL, NULL, NULL, NULL) );
5944 	      (*negvar)->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
5945 	      if( SCIPvarIsBinary(var) )
5946 	         (*negvar)->data.negate.constant = 1.0;
5947 	      else
5948 	         (*negvar)->data.negate.constant = var->glbdom.lb + var->glbdom.ub;
5949 	
5950 	      /* create event filter for transformed variable */
5951 	      if( SCIPvarIsTransformed(var) )
5952 	      {
5953 	         SCIP_CALL( SCIPeventfilterCreate(&(*negvar)->eventfilter, blkmem) );
5954 	      }
5955 	
5956 	      /* set the bounds corresponding to the negation variable */
5957 	      (*negvar)->glbdom.lb = (*negvar)->data.negate.constant - var->glbdom.ub;
5958 	      (*negvar)->glbdom.ub = (*negvar)->data.negate.constant - var->glbdom.lb;
5959 	      (*negvar)->locdom.lb = (*negvar)->data.negate.constant - var->locdom.ub;
5960 	      (*negvar)->locdom.ub = (*negvar)->data.negate.constant - var->locdom.lb;
5961 	      /**@todo create holes in the negated variable corresponding to the holes of the negation variable */
5962 	
5963 	      /* link the variables together */
5964 	      var->negatedvar = *negvar;
5965 	      (*negvar)->negatedvar = var;
5966 	
5967 	      /* mark both variables to be non-deletable */
5968 	      SCIPvarMarkNotDeletable(var);
5969 	      SCIPvarMarkNotDeletable(*negvar);
5970 	
5971 	      /* copy the branch factor and priority, and use the negative preferred branching direction */
5972 	      (*negvar)->branchfactor = var->branchfactor;
5973 	      (*negvar)->branchpriority = var->branchpriority;
5974 	      (*negvar)->branchdirection = SCIPbranchdirOpposite((SCIP_BRANCHDIR)var->branchdirection); /*lint !e641*/
5975 	
5976 	      /* copy donot(mult)aggr status */
5977 	      (*negvar)->donotaggr = var->donotaggr;
5978 	      (*negvar)->donotmultaggr = var->donotmultaggr;
5979 	
5980 	      /* copy lazy bounds (they have to be flipped) */
5981 	      (*negvar)->lazylb = (*negvar)->data.negate.constant - var->lazyub;
5982 	      (*negvar)->lazyub = (*negvar)->data.negate.constant - var->lazylb;
5983 	
5984 	      /* make negated variable a parent of the negation variable (negated variable is captured as a parent) */
5985 	      SCIP_CALL( varAddParent(var, blkmem, set, *negvar) );
5986 	      assert((*negvar)->nuses == 1);
5987 	   }
5988 	   assert(var->negatedvar != NULL);
5989 	
5990 	   /* return the negated variable */
5991 	   *negvar = var->negatedvar;
5992 	
5993 	   /* exactly one variable of the negation pair has to be marked as negated variable */
5994 	   assert((SCIPvarGetStatus(*negvar) == SCIP_VARSTATUS_NEGATED) != (SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED));
5995 	
5996 	   return SCIP_OKAY;
5997 	}
5998 	
5999 	/** informs variable that its position in problem's vars array changed */
6000 	static
6001 	void varSetProbindex(
6002 	   SCIP_VAR*             var,                /**< problem variable */
6003 	   int                   probindex           /**< new problem index of variable (-1 for removal) */
6004 	   )
6005 	{
6006 	   assert(var != NULL);
6007 	   assert(probindex >= 0 || var->vlbs == NULL);
6008 	   assert(probindex >= 0 || var->vubs == NULL);
6009 	   assert(probindex >= 0 || var->implics == NULL);
6010 	
6011 	   var->probindex = probindex;
6012 	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN )
6013 	   {
6014 	      assert(var->data.col != NULL);
6015 	      var->data.col->var_probindex = probindex;
6016 	   }
6017 	}
6018 	
6019 	/** informs variable that its position in problem's vars array changed */
6020 	void SCIPvarSetProbindex(
6021 	   SCIP_VAR*             var,                /**< problem variable */
6022 	   int                   probindex           /**< new problem index of variable */
6023 	   )
6024 	{
6025 	   assert(var != NULL);
6026 	   assert(probindex >= 0);
6027 	
6028 	   varSetProbindex(var, probindex);
6029 	}
6030 	
6031 	/** gives the variable a new name
6032 	 *
6033 	 *  @note the old pointer is overwritten, which might result in a memory leakage
6034 	 */
6035 	void SCIPvarSetNamePointer(
6036 	   SCIP_VAR*             var,                /**< problem variable */
6037 	   const char*           name                /**< new name of variable */
6038 	   )
6039 	{
6040 	   assert(var != NULL);
6041 	   assert(name != NULL);
6042 	
6043 	   var->name = (char*)name;
6044 	}
6045 	
6046 	/** informs variable that it will be removed from the problem; adjusts probindex and removes variable from the
6047 	 *  implication graph;
6048 	 *  If 'final' is TRUE, the thorough implication graph removal is not performed. Instead, only the
6049 	 *  variable bounds and implication data structures of the variable are freed. Since in the final removal
6050 	 *  of all variables from the transformed problem, this deletes the implication graph completely and is faster
6051 	 *  than removing the variables one by one, each time updating all lists of the other variables.
6052 	 */
6053 	SCIP_RETCODE SCIPvarRemove(
6054 	   SCIP_VAR*             var,                /**< problem variable */
6055 	   BMS_BLKMEM*           blkmem,             /**< block memory buffer */
6056 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
6057 	   SCIP_SET*             set,                /**< global SCIP settings */
6058 	   SCIP_Bool             final               /**< is this the final removal of all problem variables? */
6059 	   )
6060 	{
6061 	   assert(SCIPvarGetProbindex(var) >= 0);
6062 	   assert(var->scip == set->scip);
6063 	
6064 	   /* if the variable is active in the transformed problem, remove it from the implication graph */
6065 	   if( SCIPvarIsTransformed(var)
6066 	      && (SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN) )
6067 	   {
6068 	      if( final )
6069 	      {
6070 	         /* just destroy the data structures */
6071 	         SCIPvboundsFree(&var->vlbs, blkmem);
6072 	         SCIPvboundsFree(&var->vubs, blkmem);
6073 	         SCIPimplicsFree(&var->implics, blkmem);
6074 	      }
6075 	      else
6076 	      {
6077 	         /* unlink the variable from all other variables' lists and free the data structures */
6078 	         SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
6079 	      }
6080 	   }
6081 	
6082 	   /* mark the variable to be no longer a member of the problem */
6083 	   varSetProbindex(var, -1);
6084 	
6085 	   return SCIP_OKAY;
6086 	}
6087 	
6088 	/** marks the variable to be deleted from the problem */
6089 	void SCIPvarMarkDeleted(
6090 	   SCIP_VAR*             var                 /**< problem variable */
6091 	   )
6092 	{
6093 	   assert(var != NULL);
6094 	   assert(var->probindex != -1);
6095 	
6096 	   var->deleted = TRUE;
6097 	}
6098 	
6099 	/** marks the variable to not to be aggregated */
6100 	SCIP_RETCODE SCIPvarMarkDoNotAggr(
6101 	   SCIP_VAR*             var                 /**< problem variable */
6102 	   )
6103 	{
6104 	   SCIP_VAR* retvar;
6105 	
6106 	   assert(var != NULL);
6107 	
6108 	   retvar = varGetActiveVar(var);
6109 	   assert(retvar != NULL);
6110 	
6111 	   switch( SCIPvarGetStatus(retvar) )
6112 	   {
6113 	   case SCIP_VARSTATUS_ORIGINAL:
6114 	   case SCIP_VARSTATUS_LOOSE:
6115 	   case SCIP_VARSTATUS_COLUMN:
6116 	   case SCIP_VARSTATUS_FIXED:
6117 	      retvar->donotaggr = TRUE;
6118 	      break;
6119 	
6120 	   case SCIP_VARSTATUS_MULTAGGR:
6121 	      SCIPerrorMessage("cannot mark a multi-aggregated variable to not be aggregated.\n");
6122 	      return SCIP_INVALIDDATA;
6123 	
6124 	   case SCIP_VARSTATUS_AGGREGATED:
6125 	   case SCIP_VARSTATUS_NEGATED:
6126 	   default:
6127 	      /* aggregated and negated variables should be resolved by varGetActiveVar() */
6128 	      SCIPerrorMessage("wrong variable status\n");
6129 	      return SCIP_INVALIDDATA;
6130 	   }
6131 	
6132 	   return SCIP_OKAY;
6133 	}
6134 	
6135 	/** marks the variable to not to be multi-aggregated */
6136 	SCIP_RETCODE SCIPvarMarkDoNotMultaggr(
6137 	   SCIP_VAR*             var                 /**< problem variable */
6138 	   )
6139 	{
6140 	   SCIP_VAR* retvar;
6141 	
6142 	   assert(var != NULL);
6143 	
6144 	   retvar = varGetActiveVar(var);
6145 	   assert(retvar != NULL);
6146 	
6147 	   switch( SCIPvarGetStatus(retvar) )
6148 	   {
6149 	   case SCIP_VARSTATUS_ORIGINAL:
6150 	   case SCIP_VARSTATUS_LOOSE:
6151 	   case SCIP_VARSTATUS_COLUMN:
6152 	   case SCIP_VARSTATUS_FIXED:
6153 	      retvar->donotmultaggr = TRUE;
6154 	      break;
6155 	
6156 	   case SCIP_VARSTATUS_MULTAGGR:
6157 	      SCIPerrorMessage("cannot mark a multi-aggregated variable to not be multi-aggregated.\n");
6158 	      return SCIP_INVALIDDATA;
6159 	
6160 	   case SCIP_VARSTATUS_AGGREGATED:
6161 	   case SCIP_VARSTATUS_NEGATED:
6162 	   default:
6163 	      /* aggregated and negated variables should be resolved by varGetActiveVar() */
6164 	      SCIPerrorMessage("wrong variable status\n");
6165 	      return SCIP_INVALIDDATA;
6166 	   }
6167 	
6168 	   return SCIP_OKAY;
6169 	}
6170 	
6171 	/** changes type of variable; cannot be called, if var belongs to a problem */
6172 	SCIP_RETCODE SCIPvarChgType(
6173 	   SCIP_VAR*             var,                /**< problem variable to change */
6174 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6175 	   SCIP_SET*             set,                /**< global SCIP settings */
6176 	   SCIP_PRIMAL*          primal,             /**< primal data */
6177 	   SCIP_LP*              lp,                 /**< current LP data */
6178 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
6179 	   SCIP_VARTYPE          vartype             /**< new type of variable */
6180 	   )
6181 	{
6182 	   SCIP_EVENT* event;
6183 	   SCIP_VARTYPE oldtype;
6184 	
6185 	   assert(var != NULL);
6186 	
6187 	   SCIPdebugMessage("change type of <%s> from %d to %d\n", var->name, SCIPvarGetType(var), vartype);
6188 	
6189 	   if( var->probindex >= 0 )
6190 	   {
6191 	      SCIPerrorMessage("cannot change type of variable already in the problem\n");
6192 	      return SCIP_INVALIDDATA;
6193 	   }
6194 	
6195 	   oldtype = (SCIP_VARTYPE)var->vartype;
6196 	   var->vartype = vartype; /*lint !e641*/
6197 	
6198 	   if( SCIPsetGetStage(set) > SCIP_STAGE_TRANSFORMING )
6199 	   {
6200 	      SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var, oldtype, vartype) );
6201 	      SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6202 	   }
6203 	
6204 	   if( var->negatedvar != NULL )
6205 	   {
6206 	      assert(oldtype == (SCIP_VARTYPE)var->negatedvar->vartype
6207 	            || SCIPvarIsBinary(var) == SCIPvarIsBinary(var->negatedvar));
6208 	
6209 	
6210 	      var->negatedvar->vartype = vartype; /*lint !e641*/
6211 	
6212 	      if( SCIPsetGetStage(set) > SCIP_STAGE_TRANSFORMING )
6213 	      {
6214 	         SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var->negatedvar, oldtype, vartype) );
6215 	         SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6216 	      }
6217 	   }
6218 	
6219 	   return SCIP_OKAY;
6220 	}
6221 	
6222 	/** appends OBJCHANGED event to the event queue */
6223 	static
6224 	SCIP_RETCODE varEventObjChanged(
6225 	   SCIP_VAR*             var,                /**< problem variable to change */
6226 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6227 	   SCIP_SET*             set,                /**< global SCIP settings */
6228 	   SCIP_PRIMAL*          primal,             /**< primal data */
6229 	   SCIP_LP*              lp,                 /**< current LP data */
6230 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
6231 	   SCIP_Real             oldobj,             /**< old objective value for variable */
6232 	   SCIP_Real             newobj              /**< new objective value for variable */
6233 	   )
6234 	{
6235 	   SCIP_EVENT* event;
6236 	
6237 	   assert(var != NULL);
6238 	   assert(var->scip == set->scip);
6239 	   assert(var->eventfilter != NULL);
6240 	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
6241 	   assert(SCIPvarIsTransformed(var));
6242 	
6243 	   /* In the case where the objcetive value of a variable is very close to epsilon, and it is aggregated
6244 	   * into a variable with a big objective value, round-off errors might make the assert oldobj != newobj fail.
6245 	   * Hence, we relax it by letting it pass if the variables are percieved the same and we use very large values
6246 	   * that make comparison with values close to epsilon inaccurate.
6247 	   */
6248 	   assert(!SCIPsetIsEQ(set, oldobj, newobj) ||
6249 	          (SCIPsetIsEQ(set, oldobj, newobj) && REALABS(newobj) > 1e+15 * SCIPsetEpsilon(set))
6250 	   );
6251 	
6252 	   SCIP_CALL( SCIPeventCreateObjChanged(&event, blkmem, var, oldobj, newobj) );
6253 	   SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6254 	
6255 	   return SCIP_OKAY;
6256 	}
6257 	
6258 	/** changes objective value of variable */
6259 	SCIP_RETCODE SCIPvarChgObj(
6260 	   SCIP_VAR*             var,                /**< variable to change */
6261 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6262 	   SCIP_SET*             set,                /**< global SCIP settings */
6263 	   SCIP_PROB*            prob,               /**< problem data */
6264 	   SCIP_PRIMAL*          primal,             /**< primal data */
6265 	   SCIP_LP*              lp,                 /**< current LP data */
6266 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
6267 	   SCIP_Real             newobj              /**< new objective value for variable */
6268 	   )
6269 	{
6270 	   SCIP_Real oldobj;
6271 	
6272 	   assert(var != NULL);
6273 	   assert(set != NULL);
6274 	   assert(var->scip == set->scip);
6275 	
6276 	   SCIPsetDebugMsg(set, "changing objective value of <%s> from %g to %g\n", var->name, var->obj, newobj);
6277 	
6278 	   if( !SCIPsetIsEQ(set, var->obj, newobj) )
6279 	   {
6280 	      switch( SCIPvarGetStatus(var) )
6281 	      {
6282 	      case SCIP_VARSTATUS_ORIGINAL:
6283 	         if( var->data.original.transvar != NULL )
6284 	         {
6285 	            assert(SCIPprobIsTransformed(prob));
6286 	
6287 	            SCIP_CALL( SCIPvarChgObj(var->data.original.transvar, blkmem, set, prob, primal, lp, eventqueue,
6288 	                  (SCIP_Real) prob->objsense * newobj/prob->objscale) );
6289 	         }
6290 	         else
6291 	            assert(set->stage == SCIP_STAGE_PROBLEM);
6292 	
6293 	         var->obj = newobj;
6294 	         var->unchangedobj = newobj;
6295 	
6296 	         break;
6297 	
6298 	      case SCIP_VARSTATUS_LOOSE:
6299 	      case SCIP_VARSTATUS_COLUMN:
6300 	         oldobj = var->obj;
6301 	         var->obj = newobj;
6302 	
6303 	         /* update unchanged objective value of variable */
6304 	         if( !lp->divingobjchg )
6305 	            var->unchangedobj = newobj;
6306 	
6307 	         /* update the number of variables with non-zero objective coefficient;
6308 	          * we only want to do the update, if the variable is added to the problem;
6309 	          * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6310 	          */
6311 	         if( SCIPvarIsActive(var) )
6312 	            SCIPprobUpdateNObjVars(prob, set, oldobj, var->obj);
6313 	
6314 	         SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6315 	         break;
6316 	
6317 	      case SCIP_VARSTATUS_FIXED:
6318 	      case SCIP_VARSTATUS_AGGREGATED:
6319 	      case SCIP_VARSTATUS_MULTAGGR:
6320 	      case SCIP_VARSTATUS_NEGATED:
6321 	         SCIPerrorMessage("cannot change objective value of a fixed, aggregated, multi-aggregated, or negated variable\n");
6322 	         return SCIP_INVALIDDATA;
6323 	
6324 	      default:
6325 	         SCIPerrorMessage("unknown variable status\n");
6326 	         return SCIP_INVALIDDATA;
6327 	      }
6328 	   }
6329 	
6330 	   return SCIP_OKAY;
6331 	}
6332 	
6333 	/** adds value to objective value of variable */
6334 	SCIP_RETCODE SCIPvarAddObj(
6335 	   SCIP_VAR*             var,                /**< variable to change */
6336 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6337 	   SCIP_SET*             set,                /**< global SCIP settings */
6338 	   SCIP_STAT*            stat,               /**< problem statistics */
6339 	   SCIP_PROB*            transprob,          /**< transformed problem data */
6340 	   SCIP_PROB*            origprob,           /**< original problem data */
6341 	   SCIP_PRIMAL*          primal,             /**< primal data */
6342 	   SCIP_TREE*            tree,               /**< branch and bound tree */
6343 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
6344 	   SCIP_LP*              lp,                 /**< current LP data */
6345 	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter for global (not variable dependent) events */
6346 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
6347 	   SCIP_Real             addobj              /**< additional objective value for variable */
6348 	   )
6349 	{
6350 	   assert(var != NULL);
6351 	   assert(set != NULL);
6352 	   assert(var->scip == set->scip);
6353 	   assert(set->stage < SCIP_STAGE_INITSOLVE);
6354 	
6355 	   SCIPsetDebugMsg(set, "adding %g to objective value %g of <%s>\n", addobj, var->obj, var->name);
6356 	
6357 	   if( !SCIPsetIsZero(set, addobj) )
6358 	   {
6359 	      SCIP_Real oldobj;
6360 	      int i;
6361 	
6362 	      switch( SCIPvarGetStatus(var) )
6363 	      {
6364 	      case SCIP_VARSTATUS_ORIGINAL:
6365 	         if( var->data.original.transvar != NULL )
6366 	         {
6367 	            SCIP_CALL( SCIPvarAddObj(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
6368 	                  reopt, lp, eventfilter, eventqueue, (SCIP_Real) transprob->objsense * addobj/transprob->objscale) );
6369 	         }
6370 	         else
6371 	            assert(set->stage == SCIP_STAGE_PROBLEM);
6372 	
6373 	         var->obj += addobj;
6374 	         var->unchangedobj += addobj;
6375 	         assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6376 	
6377 	         break;
6378 	
6379 	      case SCIP_VARSTATUS_LOOSE:
6380 	      case SCIP_VARSTATUS_COLUMN:
6381 	         oldobj = var->obj;
6382 	         var->obj += addobj;
6383 	
6384 	         /* update unchanged objective value of variable */
6385 	         if( !lp->divingobjchg )
6386 	         {
6387 	            var->unchangedobj += addobj;
6388 	            assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6389 	         }
6390 	
6391 	         /* update the number of variables with non-zero objective coefficient;
6392 	          * we only want to do the update, if the variable is added to the problem;
6393 	          * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6394 	          */
6395 	         if( SCIPvarIsActive(var) )
6396 		    SCIPprobUpdateNObjVars(transprob, set, oldobj, var->obj);
6397 	
6398 	         SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6399 	         break;
6400 	
6401 	      case SCIP_VARSTATUS_FIXED:
6402 	         assert(SCIPsetIsEQ(set, var->locdom.lb, var->locdom.ub));
6403 	         SCIPprobAddObjoffset(transprob, var->locdom.lb * addobj);
6404 	         SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6405 	         break;
6406 	
6407 	      case SCIP_VARSTATUS_AGGREGATED:
6408 	         assert(!var->donotaggr);
6409 	         /* x = a*y + c  ->  add a*addobj to obj. val. of y, and c*addobj to obj. offset of problem */
6410 	         SCIPprobAddObjoffset(transprob, var->data.aggregate.constant * addobj);
6411 	         SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6412 	         SCIP_CALL( SCIPvarAddObj(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
6413 	               lp, eventfilter, eventqueue, var->data.aggregate.scalar * addobj) );
6414 	         break;
6415 	
6416 	      case SCIP_VARSTATUS_MULTAGGR:
6417 	         assert(!var->donotmultaggr);
6418 	         /* x = a_1*y_1 + ... + a_n*y_n  + c  ->  add a_i*addobj to obj. val. of y_i, and c*addobj to obj. offset */
6419 	         SCIPprobAddObjoffset(transprob, var->data.multaggr.constant * addobj);
6420 	         SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6421 	         for( i = 0; i < var->data.multaggr.nvars; ++i )
6422 	         {
6423 	            SCIP_CALL( SCIPvarAddObj(var->data.multaggr.vars[i], blkmem, set, stat, transprob, origprob, primal, tree,
6424 	                  reopt, lp, eventfilter, eventqueue, var->data.multaggr.scalars[i] * addobj) );
6425 	         }
6426 	         break;
6427 	
6428 	      case SCIP_VARSTATUS_NEGATED:
6429 	         /* x' = offset - x  ->  add -addobj to obj. val. of x and offset*addobj to obj. offset of problem */
6430 	         assert(var->negatedvar != NULL);
6431 	         assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
6432 	         assert(var->negatedvar->negatedvar == var);
6433 	         SCIPprobAddObjoffset(transprob, var->data.negate.constant * addobj);
6434 	         SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6435 	         SCIP_CALL( SCIPvarAddObj(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
6436 	               eventfilter, eventqueue, -addobj) );
6437 	         break;
6438 	
6439 	      default:
6440 	         SCIPerrorMessage("unknown variable status\n");
6441 	         return SCIP_INVALIDDATA;
6442 	      }
6443 	   }
6444 	
6445 	   return SCIP_OKAY;
6446 	}
6447 	
6448 	/** changes objective value of variable in current dive */
6449 	SCIP_RETCODE SCIPvarChgObjDive(
6450 	   SCIP_VAR*             var,                /**< problem variable to change */
6451 	   SCIP_SET*             set,                /**< global SCIP settings */
6452 	   SCIP_LP*              lp,                 /**< current LP data */
6453 	   SCIP_Real             newobj              /**< new objective value for variable */
6454 	   )
6455 	{
6456 	   assert(var != NULL);
6457 	   assert(set != NULL);
6458 	   assert(var->scip == set->scip);
6459 	   assert(lp != NULL);
6460 	
6461 	   SCIPsetDebugMsg(set, "changing objective of <%s> to %g in current dive\n", var->name, newobj);
6462 	
6463 	   if( SCIPsetIsZero(set, newobj) )
6464 	      newobj = 0.0;
6465 	
6466 	   /* change objective value of attached variables */
6467 	   switch( SCIPvarGetStatus(var) )
6468 	   {
6469 	   case SCIP_VARSTATUS_ORIGINAL:
6470 	      assert(var->data.original.transvar != NULL);
6471 	      SCIP_CALL( SCIPvarChgObjDive(var->data.original.transvar, set, lp, newobj) );
6472 	      break;
6473 	
6474 	   case SCIP_VARSTATUS_COLUMN:
6475 	      assert(var->data.col != NULL);
6476 	      SCIP_CALL( SCIPcolChgObj(var->data.col, set, lp, newobj) );
6477 	      break;
6478 	
6479 	   case SCIP_VARSTATUS_LOOSE:
6480 	   case SCIP_VARSTATUS_FIXED:
6481 	      /* nothing to do here: only the constant shift in objective function would change */
6482 	      break;
6483 	
6484 	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
6485 	      assert(var->data.aggregate.var != NULL);
6486 	      assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
6487 	      SCIP_CALL( SCIPvarChgObjDive(var->data.aggregate.var, set, lp, newobj / var->data.aggregate.scalar) );
6488 	      /* the constant can be ignored, because it would only affect the objective shift */
6489 	      break;
6490 	
6491 	   case SCIP_VARSTATUS_MULTAGGR:
6492 	      SCIPerrorMessage("cannot change diving objective value of a multi-aggregated variable\n");
6493 	      return SCIP_INVALIDDATA;
6494 	
6495 	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
6496 	      assert(var->negatedvar != NULL);
6497 	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
6498 	      assert(var->negatedvar->negatedvar == var);
6499 	      SCIP_CALL( SCIPvarChgObjDive(var->negatedvar, set, lp, -newobj) );
6500 	      /* the offset can be ignored, because it would only affect the objective shift */
6501 	      break;
6502 	
6503 	   default:
6504 	      SCIPerrorMessage("unknown variable status\n");
6505 	      return SCIP_INVALIDDATA;
6506 	   }
6507 	
6508 	   return SCIP_OKAY;
6509 	}
6510 	
6511 	/** adjust lower bound to integral value, if variable is integral */
6512 	void SCIPvarAdjustLb(
6513 	   SCIP_VAR*             var,                /**< problem variable */
6514 	   SCIP_SET*             set,                /**< global SCIP settings */
6515 	   SCIP_Real*            lb                  /**< pointer to lower bound to adjust */
6516 	   )
6517 	{
6518 	   assert(var != NULL);
6519 	   assert(set != NULL);
6520 	   assert(var->scip == set->scip);
6521 	   assert(lb != NULL);
6522 	
6523 	   SCIPsetDebugMsg(set, "adjust lower bound %g of <%s>\n", *lb, var->name);
6524 	
6525 	   *lb = adjustedLb(set, SCIPvarGetType(var), *lb);
6526 	}
6527 	
6528 	/** adjust upper bound to integral value, if variable is integral */
6529 	void SCIPvarAdjustUb(
6530 	   SCIP_VAR*             var,                /**< problem variable */
6531 	   SCIP_SET*             set,                /**< global SCIP settings */
6532 	   SCIP_Real*            ub                  /**< pointer to upper bound to adjust */
6533 	   )
6534 	{
6535 	   assert(var != NULL);
6536 	   assert(set != NULL);
6537 	   assert(var->scip == set->scip);
6538 	   assert(ub != NULL);
6539 	
6540 	   SCIPsetDebugMsg(set, "adjust upper bound %g of <%s>\n", *ub, var->name);
6541 	
6542 	   *ub = adjustedUb(set, SCIPvarGetType(var), *ub);
6543 	}
6544 	
6545 	/** adjust lower or upper bound to integral value, if variable is integral */
6546 	void SCIPvarAdjustBd(
6547 	   SCIP_VAR*             var,                /**< problem variable */
6548 	   SCIP_SET*             set,                /**< global SCIP settings */
6549 	   SCIP_BOUNDTYPE        boundtype,          /**< type of bound to adjust */
6550 	   SCIP_Real*            bd                  /**< pointer to bound to adjust */
6551 	   )
6552 	{
6553 	   assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
6554 	
6555 	   if( boundtype == SCIP_BOUNDTYPE_LOWER )
6556 	      SCIPvarAdjustLb(var, set, bd);
6557 	   else
6558 	      SCIPvarAdjustUb(var, set, bd);
6559 	}
6560 	
6561 	/** changes lower bound of original variable in original problem */
6562 	SCIP_RETCODE SCIPvarChgLbOriginal(
6563 	   SCIP_VAR*             var,                /**< problem variable to change */
6564 	   SCIP_SET*             set,                /**< global SCIP settings */
6565 	   SCIP_Real             newbound            /**< new bound for variable */
6566 	   )
6567 	{
6568 	   int i;
6569 	
6570 	   assert(var != NULL);
6571 	   assert(!SCIPvarIsTransformed(var));
6572 	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL || SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
6573 	   assert(set != NULL);
6574 	   assert(var->scip == set->scip);
6575 	   assert(set->stage == SCIP_STAGE_PROBLEM);
6576 	
6577 	   /* check that the bound is feasible */
6578 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, SCIPvarGetUbOriginal(var)));
6579 	   /* adjust bound to integral value if variable is of integral type */
6580 	   newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6581 	
6582 	   if( SCIPsetIsZero(set, newbound) )
6583 	      newbound = 0.0;
6584 	
6585 	   /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6586 	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL )
6587 	   {
6588 	      SCIPsetDebugMsg(set, "changing original lower bound of <%s> from %g to %g\n",
6589 	         var->name, var->data.original.origdom.lb, newbound);
6590 	
6591 	      if( SCIPsetIsEQ(set, var->data.original.origdom.lb, newbound) )
6592 	         return SCIP_OKAY;
6593 	
6594 	      /* change the bound */
6595 	      var->data.original.origdom.lb = newbound;
6596 	   }
6597 	   else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6598 	   {
6599 	      assert( var->negatedvar != NULL );
6600 	      SCIP_CALL( SCIPvarChgUbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6601 	   }
6602 	
6603 	   /* process parent variables */
6604 	   for( i = 0; i < var->nparentvars; ++i )
6605 	   {
6606 	      SCIP_VAR* parentvar;
6607 	
6608 	      parentvar = var->parentvars[i];
6609 	      assert(parentvar != NULL);
6610 	      assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6611 	      assert(parentvar->negatedvar == var);
6612 	      assert(var->negatedvar == parentvar);
6613 	
6614 	      SCIP_CALL( SCIPvarChgUbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6615 	   }
6616 	
6617 	   return SCIP_OKAY;
6618 	}
6619 	
6620 	/** changes upper bound of original variable in original problem */
6621 	SCIP_RETCODE SCIPvarChgUbOriginal(
6622 	   SCIP_VAR*             var,                /**< problem variable to change */
6623 	   SCIP_SET*             set,                /**< global SCIP settings */
6624 	   SCIP_Real             newbound            /**< new bound for variable */
6625 	   )
6626 	{
6627 	   int i;
6628 	
6629 	   assert(var != NULL);
6630 	   assert(!SCIPvarIsTransformed(var));
6631 	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL || SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
6632 	   assert(set != NULL);
6633 	   assert(var->scip == set->scip);
6634 	   assert(set->stage == SCIP_STAGE_PROBLEM);
6635 	
6636 	   /* check that the bound is feasible */
6637 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, SCIPvarGetLbOriginal(var)));
6638 	   /* adjust bound to integral value if variable is of integral type */
6639 	   newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6640 	
6641 	   if( SCIPsetIsZero(set, newbound) )
6642 	      newbound = 0.0;
6643 	
6644 	   /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6645 	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL )
6646 	   {
6647 	      SCIPsetDebugMsg(set, "changing original upper bound of <%s> from %g to %g\n",
6648 	         var->name, var->data.original.origdom.ub, newbound);
6649 	
6650 	      if( SCIPsetIsEQ(set, var->data.original.origdom.ub, newbound) )
6651 	         return SCIP_OKAY;
6652 	
6653 	      /* change the bound */
6654 	      var->data.original.origdom.ub = newbound;
6655 	   }
6656 	   else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6657 	   {
6658 	      assert( var->negatedvar != NULL );
6659 	      SCIP_CALL( SCIPvarChgLbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6660 	   }
6661 	
6662 	   /* process parent variables */
6663 	   for( i = 0; i < var->nparentvars; ++i )
6664 	   {
6665 	      SCIP_VAR* parentvar;
6666 	
6667 	      parentvar = var->parentvars[i];
6668 	      assert(parentvar != NULL);
6669 	      assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6670 	      assert(parentvar->negatedvar == var);
6671 	      assert(var->negatedvar == parentvar);
6672 	
6673 	      SCIP_CALL( SCIPvarChgLbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6674 	   }
6675 	
6676 	   return SCIP_OKAY;
6677 	}
6678 	
6679 	/** appends GLBCHANGED event to the event queue */
6680 	static
6681 	SCIP_RETCODE varEventGlbChanged(
6682 	   SCIP_VAR*             var,                /**< problem variable to change */
6683 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6684 	   SCIP_SET*             set,                /**< global SCIP settings */
6685 	   SCIP_LP*              lp,                 /**< current LP data */
6686 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
6687 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
6688 	   SCIP_Real             oldbound,           /**< old lower bound for variable */
6689 	   SCIP_Real             newbound            /**< new lower bound for variable */
6690 	   )
6691 	{
6692 	   assert(var != NULL);
6693 	   assert(var->eventfilter != NULL);
6694 	   assert(SCIPvarIsTransformed(var));
6695 	   assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
6696 	   assert(set != NULL);
6697 	   assert(var->scip == set->scip);
6698 	
6699 	   /* check, if the variable is being tracked for bound changes
6700 	    * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6701 	    */
6702 	   if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GLBCHANGED) != 0)
6703 	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
6704 	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE )
6705 	   {
6706 	      SCIP_EVENT* event;
6707 	
6708 	      SCIPsetDebugMsg(set, "issue GLBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6709 	
6710 	      SCIP_CALL( SCIPeventCreateGlbChanged(&event, blkmem, var, oldbound, newbound) );
6711 	      SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6712 	   }
6713 	
6714 	   return SCIP_OKAY;
6715 	}
6716 	
6717 	/** appends GUBCHANGED event to the event queue */
6718 	static
6719 	SCIP_RETCODE varEventGubChanged(
6720 	   SCIP_VAR*             var,                /**< problem variable to change */
6721 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6722 	   SCIP_SET*             set,                /**< global SCIP settings */
6723 	   SCIP_LP*              lp,                 /**< current LP data */
6724 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
6725 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
6726 	   SCIP_Real             oldbound,           /**< old lower bound for variable */
6727 	   SCIP_Real             newbound            /**< new lower bound for variable */
6728 	   )
6729 	{
6730 	   assert(var != NULL);
6731 	   assert(var->eventfilter != NULL);
6732 	   assert(SCIPvarIsTransformed(var));
6733 	   assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
6734 	   assert(set != NULL);
6735 	   assert(var->scip == set->scip);
6736 	
6737 	   /* check, if the variable is being tracked for bound changes
6738 	    * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6739 	    */
6740 	   if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GUBCHANGED) != 0)
6741 	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
6742 	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE )
6743 	   {
6744 	      SCIP_EVENT* event;
6745 	
6746 	      SCIPsetDebugMsg(set, "issue GUBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6747 	
6748 	      SCIP_CALL( SCIPeventCreateGubChanged(&event, blkmem, var, oldbound, newbound) );
6749 	      SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6750 	   }
6751 	
6752 	   return SCIP_OKAY;
6753 	}
6754 	
6755 	/** appends GHOLEADDED event to the event queue */
6756 	static
6757 	SCIP_RETCODE varEventGholeAdded(
6758 	   SCIP_VAR*             var,                /**< problem variable to change */
6759 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6760 	   SCIP_SET*             set,                /**< global SCIP settings */
6761 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
6762 	   SCIP_Real             left,               /**< left bound of open interval in new hole */
6763 	   SCIP_Real             right               /**< right bound of open interval in new hole */
6764 	   )
6765 	{
6766 	   assert(var != NULL);
6767 	   assert(var->eventfilter != NULL);
6768 	   assert(SCIPvarIsTransformed(var));
6769 	   assert(set != NULL);
6770 	   assert(var->scip == set->scip);
6771 	   assert(SCIPsetIsLT(set, left, right));
6772 	
6773 	   /* check, if the variable is being tracked for bound changes */
6774 	   if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GHOLEADDED) != 0) )
6775 	   {
6776 	      SCIP_EVENT* event;
6777 	
6778 	      SCIPsetDebugMsg(set, "issue GHOLEADDED event for variable <%s>: (%.15g,%.15g)\n", var->name, left, right);
6779 	
6780 	      SCIP_CALL( SCIPeventCreateGholeAdded(&event, blkmem, var, left, right) );
6781 	      SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
6782 	   }
6783 	
6784 	   return SCIP_OKAY;
6785 	}
6786 	
6787 	/** increases root bound change statistics after a global bound change */
6788 	static
6789 	void varIncRootboundchgs(
6790 	   SCIP_VAR*             var,                /**< problem variable to change */
6791 	   SCIP_SET*             set,                /**< global SCIP settings */
6792 	   SCIP_STAT*            stat                /**< problem statistics */
6793 	   )
6794 	{
6795 	   assert(var != NULL);
6796 	   assert(set != NULL);
6797 	   assert(var->scip == set->scip);
6798 	   assert(stat != NULL);
6799 	
6800 	   if( SCIPvarIsActive(var) && SCIPvarIsTransformed(var) && set->stage == SCIP_STAGE_SOLVING )
6801 	   {
6802 	      stat->nrootboundchgs++;
6803 	      stat->nrootboundchgsrun++;
6804 	      if( SCIPvarIsIntegral(var) && SCIPvarGetLbGlobal(var) + 0.5 > SCIPvarGetUbGlobal(var) )
6805 	      {
6806 	         stat->nrootintfixings++;
6807 	         stat->nrootintfixingsrun++;
6808 	      }
6809 	   }
6810 	}
6811 	
6812 	/* forward declaration, because both methods call each other recursively */
6813 	
6814 	/* performs the current change in upper bound, changes all parents accordingly */
6815 	static
6816 	SCIP_RETCODE varProcessChgUbGlobal(
6817 	   SCIP_VAR*             var,                /**< problem variable to change */
6818 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6819 	   SCIP_SET*             set,                /**< global SCIP settings */
6820 	   SCIP_STAT*            stat,               /**< problem statistics */
6821 	   SCIP_LP*              lp,                 /**< current LP data, may be NULL for original variables */
6822 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage, may be NULL for original variables */
6823 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
6824 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
6825 	   SCIP_Real             newbound            /**< new bound for variable */
6826 	   );
6827 	
6828 	/** performs the current change in lower bound, changes all parents accordingly */
6829 	static
6830 	SCIP_RETCODE varProcessChgLbGlobal(
6831 	   SCIP_VAR*             var,                /**< problem variable to change */
6832 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6833 	   SCIP_SET*             set,                /**< global SCIP settings */
6834 	   SCIP_STAT*            stat,               /**< problem statistics */
6835 	   SCIP_LP*              lp,                 /**< current LP data, may be NULL for original variables */
6836 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage, may be NULL for original variables */
6837 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
6838 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
6839 	   SCIP_Real             newbound            /**< new bound for variable */
6840 	   )
6841 	{
6842 	   SCIP_VAR* parentvar;
6843 	   SCIP_Real oldbound;
6844 	   int i;
6845 	
6846 	   assert(var != NULL);
6847 	   /* local domains can violate global bounds but not more than feasibility epsilon */
6848 	   assert(SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb));
6849 	   assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6850 	   assert(blkmem != NULL);
6851 	   assert(set != NULL);
6852 	   assert(var->scip == set->scip);
6853 	   assert(stat != NULL);
6854 	
6855 	   /* adjust bound to integral value if variable is of integral type */
6856 	   newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6857 	
6858 	   /* check that the bound is feasible */
6859 	   if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound > var->glbdom.ub )
6860 	   {
6861 	      /* due to numerics we only want to be feasible in feasibility tolerance */
6862 	      assert(SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6863 	      newbound = var->glbdom.ub;
6864 	   }
6865 	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6866 	
6867 	   assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0));  /*lint !e641*/
6868 	
6869 	   SCIPsetDebugMsg(set, "process changing global lower bound of <%s> from %f to %f\n", var->name, var->glbdom.lb, newbound);
6870 	
6871 	   if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) )  /*lint !e777*/
6872 	      return SCIP_OKAY;
6873 	
6874 	   /* check bound on debugging solution */
6875 	   SCIP_CALL( SCIPdebugCheckLbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6876 	
6877 	   /* change the bound */
6878 	   oldbound = var->glbdom.lb;
6879 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6880 	   var->glbdom.lb = newbound;
6881 	   assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6882 	   assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6883 	
6884 	   if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6885 	   {
6886 	      /* merges overlapping holes into single holes, moves bounds respectively */
6887 	      domMerge(&var->glbdom, blkmem, set, &newbound, NULL);
6888 	   }
6889 	
6890 	   /* update the root bound changes counters */
6891 	   varIncRootboundchgs(var, set, stat);
6892 	
6893 	   /* update the lbchginfos array by replacing worse local bounds with the new global bound and changing the
6894 	    * redundant bound changes to be branching decisions
6895 	    */
6896 	   for( i = 0; i < var->nlbchginfos; ++i )
6897 	   {
6898 	      assert(var->lbchginfos[i].var == var);
6899 	
6900 	      if( var->lbchginfos[i].oldbound < var->glbdom.lb )
6901 	      {
6902 	         SCIPsetDebugMsg(set, " -> adjust lower bound change <%s>: %g -> %g due to new global lower bound %g\n",
6903 	            SCIPvarGetName(var), var->lbchginfos[i].oldbound, var->lbchginfos[i].newbound, var->glbdom.lb);
6904 	         var->lbchginfos[i].oldbound = var->glbdom.lb;
6905 	         if( SCIPsetIsLE(set, var->lbchginfos[i].newbound, var->glbdom.lb) )
6906 	         {
6907 	            /* this bound change is redundant due to the new global bound */
6908 	            var->lbchginfos[i].newbound = var->glbdom.lb;
6909 	            var->lbchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6910 	            var->lbchginfos[i].redundant = TRUE;
6911 	         }
6912 	         else
6913 	            break; /* from now on, the remaining local bound changes are not redundant */
6914 	      }
6915 	      else
6916 	         break; /* from now on, the remaining local bound changes are not redundant */
6917 	   }
6918 	
6919 	   /* remove redundant implications and variable bounds */
6920 	   if( (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE)
6921 	      && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
6922 	   {
6923 	      SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6924 	   }
6925 	
6926 	   /* issue bound change event */
6927 	   assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6928 	   if( var->eventfilter != NULL )
6929 	   {
6930 	      SCIP_CALL( varEventGlbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6931 	   }
6932 	
6933 	   /* process parent variables */
6934 	   for( i = 0; i < var->nparentvars; ++i )
6935 	   {
6936 	      parentvar = var->parentvars[i];
6937 	      assert(parentvar != NULL);
6938 	
6939 	      switch( SCIPvarGetStatus(parentvar) )
6940 	      {
6941 	      case SCIP_VARSTATUS_ORIGINAL:
6942 	         SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6943 	         break;
6944 	
6945 	      case SCIP_VARSTATUS_COLUMN:
6946 	      case SCIP_VARSTATUS_LOOSE:
6947 	      case SCIP_VARSTATUS_FIXED:
6948 	      case SCIP_VARSTATUS_MULTAGGR:
6949 	         SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6950 	         return SCIP_INVALIDDATA;
6951 	
6952 	      case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
6953 	         assert(parentvar->data.aggregate.var == var);
6954 	         if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6955 	         {
6956 	            SCIP_Real parentnewbound;
6957 	
6958 	            /* a > 0 -> change lower bound of y */
6959 	            assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, -oldbound)
6960 	               || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6961 	               || (SCIPsetIsZero(set, parentvar->glbdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6962 	
6963 	            if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6964 	               parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6965 	            else
6966 	               parentnewbound = newbound;
6967 	            SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6968 	         }
6969 	         else
6970 	         {
6971 	            SCIP_Real parentnewbound;
6972 	
6973 	            /* a < 0 -> change upper bound of y */
6974 	            assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6975 	            assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, -oldbound)
6976 	               || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6977 	               || (SCIPsetIsZero(set, parentvar->glbdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6978 	
6979 	            if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6980 	               parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6981 	            else
6982 	               parentnewbound = -newbound;
6983 	            SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6984 	         }
6985 	         break;
6986 	
6987 	      case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
6988 	         assert(parentvar->negatedvar != NULL);
6989 	         assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6990 	         assert(parentvar->negatedvar->negatedvar == parentvar);
6991 	         SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6992 	               parentvar->data.negate.constant - newbound) );
6993 	         break;
6994 	
6995 	      default:
6996 	         SCIPerrorMessage("unknown variable status\n");
6997 	         return SCIP_INVALIDDATA;
6998 	      }
6999 	   }
7000 	
7001 	   return SCIP_OKAY;
7002 	}
7003 	
7004 	/** performs the current change in upper bound, changes all parents accordingly */
7005 	static
7006 	SCIP_RETCODE varProcessChgUbGlobal(
7007 	   SCIP_VAR*             var,                /**< problem variable to change */
7008 	   BMS_BLKMEM*           blkmem,             /**< block memory */
7009 	   SCIP_SET*             set,                /**< global SCIP settings */
7010 	   SCIP_STAT*            stat,               /**< problem statistics */
7011 	   SCIP_LP*              lp,                 /**< current LP data, may be NULL for original variables */
7012 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage, may be NULL for original variables */
7013 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
7014 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
7015 	   SCIP_Real             newbound            /**< new bound for variable */
7016 	   )
7017 	{
7018 	   SCIP_VAR* parentvar;
7019 	   SCIP_Real oldbound;
7020 	   int i;
7021 	
7022 	   assert(var != NULL);
7023 	   /* local domains can violate global bounds but not more than feasibility epsilon */
7024 	   assert(SCIPsetIsFeasLE(set, var->glbdom.lb , var->locdom.lb));
7025 	   assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
7026 	   assert(blkmem != NULL);
7027 	   assert(set != NULL);
7028 	   assert(var->scip == set->scip);
7029 	   assert(stat != NULL);
7030 	
7031 	   /* adjust bound to integral value if variable is of integral type */
7032 	   newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7033 	
7034 	   /* check that the bound is feasible */
7035 	   if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound < var->glbdom.lb )
7036 	   {
7037 	      /* due to numerics we only want to be feasible in feasibility tolerance */
7038 	      assert(SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
7039 	      newbound = var->glbdom.lb;
7040 	   }
7041 	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7042 	
7043 	   assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0));  /*lint !e641*/
7044 	
7045 	   SCIPsetDebugMsg(set, "process changing global upper bound of <%s> from %f to %f\n", var->name, var->glbdom.ub, newbound);
7046 	
7047 	   if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) )  /*lint !e777*/
7048 	      return SCIP_OKAY;
7049 	
7050 	   /* check bound on debugging solution */
7051 	   SCIP_CALL( SCIPdebugCheckUbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
7052 	
7053 	   /* change the bound */
7054 	   oldbound = var->glbdom.ub;
7055 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
7056 	   var->glbdom.ub = newbound;
7057 	   assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
7058 	   assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
7059 	
7060 	   if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7061 	   {
7062 	      /* merges overlapping holes into single holes, moves bounds respectively */
7063 	      domMerge(&var->glbdom, blkmem, set, NULL, &newbound);
7064 	   }
7065 	
7066 	   /* update the root bound changes counters */
7067 	   varIncRootboundchgs(var, set, stat);
7068 	
7069 	   /* update the ubchginfos array by replacing worse local bounds with the new global bound and changing the
7070 	    * redundant bound changes to be branching decisions
7071 	    */
7072 	   for( i = 0; i < var->nubchginfos; ++i )
7073 	   {
7074 	      assert(var->ubchginfos[i].var == var);
7075 	      if( var->ubchginfos[i].oldbound > var->glbdom.ub )
7076 	      {
7077 	         SCIPsetDebugMsg(set, " -> adjust upper bound change <%s>: %g -> %g due to new global upper bound %g\n",
7078 	            SCIPvarGetName(var), var->ubchginfos[i].oldbound, var->ubchginfos[i].newbound, var->glbdom.ub);
7079 	         var->ubchginfos[i].oldbound = var->glbdom.ub;
7080 	         if( SCIPsetIsGE(set, var->ubchginfos[i].newbound, var->glbdom.ub) )
7081 	         {
7082 	            /* this bound change is redundant due to the new global bound */
7083 	            var->ubchginfos[i].newbound = var->glbdom.ub;
7084 	            var->ubchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
7085 	            var->ubchginfos[i].redundant = TRUE;
7086 	         }
7087 	         else
7088 	            break; /* from now on, the remaining local bound changes are not redundant */
7089 	      }
7090 	      else
7091 	         break; /* from now on, the remaining local bound changes are not redundant */
7092 	   }
7093 	
7094 	   /* remove redundant implications and variable bounds */
7095 	   if( (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE)
7096 	      && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
7097 	   {
7098 	      SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
7099 	   }
7100 	
7101 	   /* issue bound change event */
7102 	   assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7103 	   if( var->eventfilter != NULL )
7104 	   {
7105 	      SCIP_CALL( varEventGubChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7106 	   }
7107 	
7108 	   /* process parent variables */
7109 	   for( i = 0; i < var->nparentvars; ++i )
7110 	   {
7111 	      parentvar = var->parentvars[i];
7112 	      assert(parentvar != NULL);
7113 	
7114 	      switch( SCIPvarGetStatus(parentvar) )
7115 	      {
7116 	      case SCIP_VARSTATUS_ORIGINAL:
7117 	         SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7118 	         break;
7119 	
7120 	      case SCIP_VARSTATUS_COLUMN:
7121 	      case SCIP_VARSTATUS_LOOSE:
7122 	      case SCIP_VARSTATUS_FIXED:
7123 	      case SCIP_VARSTATUS_MULTAGGR:
7124 	         SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7125 	         return SCIP_INVALIDDATA;
7126 	
7127 	      case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
7128 	         assert(parentvar->data.aggregate.var == var);
7129 	         if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7130 	         {
7131 	            SCIP_Real parentnewbound;
7132 	
7133 	            /* a > 0 -> change upper bound of y */
7134 	            assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, oldbound)
7135 	               || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub,
7136 	                  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7137 	            if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7138 	               parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7139 	            else
7140 	               parentnewbound = newbound;
7141 	            SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
7142 	         }
7143 	         else
7144 	         {
7145 	            SCIP_Real parentnewbound;
7146 	
7147 	            /* a < 0 -> change lower bound of y */
7148 	            assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7149 	            assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, oldbound)
7150 	               || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb,
7151 	                  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7152 	            if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7153 	               parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7154 	            else
7155 	               parentnewbound = -newbound;
7156 	            SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
7157 	         }
7158 	         break;
7159 	
7160 	      case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
7161 	         assert(parentvar->negatedvar != NULL);
7162 	         assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7163 	         assert(parentvar->negatedvar->negatedvar == parentvar);
7164 	         SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7165 	               parentvar->data.negate.constant - newbound) );
7166 	         break;
7167 	
7168 	      default:
7169 	         SCIPerrorMessage("unknown variable status\n");
7170 	         return SCIP_INVALIDDATA;
7171 	      }
7172 	   }
7173 	
7174 	   return SCIP_OKAY;
7175 	}
7176 	
7177 	/** changes global lower bound of variable; if possible, adjusts bound to integral value;
7178 	 *  updates local lower bound if the global bound is tighter
7179 	 */
7180 	SCIP_RETCODE SCIPvarChgLbGlobal(
7181 	   SCIP_VAR*             var,                /**< problem variable to change */
7182 	   BMS_BLKMEM*           blkmem,             /**< block memory */
7183 	   SCIP_SET*             set,                /**< global SCIP settings */
7184 	   SCIP_STAT*            stat,               /**< problem statistics */
7185 	   SCIP_LP*              lp,                 /**< current LP data, may be NULL for original variables */
7186 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage, may be NULL for original variables */
7187 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
7188 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
7189 	   SCIP_Real             newbound            /**< new bound for variable */
7190 	   )
7191 	{
7192 	   assert(var != NULL);
7193 	   assert(blkmem != NULL);
7194 	   assert(set != NULL);
7195 	   assert(var->scip == set->scip);
7196 	
7197 	   /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7198 	    * of the domain within feastol
7199 	    */
7200 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
7201 	
7202 	   /* adjust bound to integral value if variable is of integral type */
7203 	   newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7204 	
7205 	   /* check that the adjusted bound is feasible
7206 	    * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
7207 	    *       here because we reset bounds to their original value!
7208 	    */
7209 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
7210 	
7211 	   if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7212 	   {
7213 	      /* we do not want to exceed the upperbound, which could have happened due to numerics */
7214 	      newbound = MIN(newbound, var->glbdom.ub);
7215 	   }
7216 	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7217 	
7218 	   /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
7219 	    * SCIPvarFix() allows fixings that are outside of the domain within feastol
7220 	    */
7221 	   assert(lp == NULL || SCIPsetIsFeasLE(set, var->glbdom.lb, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
7222 	
7223 	   SCIPsetDebugMsg(set, "changing global lower bound of <%s> from %g to %g\n", var->name, var->glbdom.lb, newbound);
7224 	
7225 	   if( SCIPsetIsEQ(set, var->glbdom.lb, newbound) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) )  /*lint !e777*/
7226 	      return SCIP_OKAY;
7227 	
7228 	   /* change bounds of attached variables */
7229 	   switch( SCIPvarGetStatus(var) )
7230 	   {
7231 	   case SCIP_VARSTATUS_ORIGINAL:
7232 	      if( var->data.original.transvar != NULL )
7233 	      {
7234 	         SCIP_CALL( SCIPvarChgLbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
7235 	               cliquetable, newbound) );
7236 	      }
7237 	      else
7238 	      {
7239 	         assert(set->stage == SCIP_STAGE_PROBLEM);
7240 	         if( newbound > SCIPvarGetLbLocal(var) )
7241 	         {
7242 	            SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7243 	         }
7244 	         SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7245 	      }
7246 	      break;
7247 	
7248 	   case SCIP_VARSTATUS_COLUMN:
7249 	   case SCIP_VARSTATUS_LOOSE:
7250 	      if( newbound > SCIPvarGetLbLocal(var) )
7251 	      {
7252 	         SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7253 	      }
7254 	      SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7255 	      break;
7256 	
7257 	   case SCIP_VARSTATUS_FIXED:
7258 	      SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7259 	      return SCIP_INVALIDDATA;
7260 	
7261 	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
7262 	      assert(var->data.aggregate.var != NULL);
7263 	      if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7264 	      {
7265 	         SCIP_Real childnewbound;
7266 	
7267 	         /* a > 0 -> change lower bound of y */
7268 	         assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
7269 	            || SCIPsetIsFeasEQ(set, var->glbdom.lb,
7270 	               var->data.aggregate.var->glbdom.lb * var->data.aggregate.scalar + var->data.aggregate.constant));
7271 	         if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7272 	            childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7273 	         else
7274 	            childnewbound = newbound;
7275 	         SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7276 	               childnewbound) );
7277 	      }
7278 	      else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7279 	      {
7280 	         SCIP_Real childnewbound;
7281 	
7282 	         /* a < 0 -> change upper bound of y */
7283 	         assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
7284 	            || SCIPsetIsFeasEQ(set, var->glbdom.lb,
7285 	               var->data.aggregate.var->glbdom.ub * var->data.aggregate.scalar + var->data.aggregate.constant));
7286 	         if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7287 	            childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7288 	         else
7289 	            childnewbound = -newbound;
7290 	         SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7291 	               childnewbound) );
7292 	      }
7293 	      else
7294 	      {
7295 	         SCIPerrorMessage("scalar is zero in aggregation\n");
7296 	         return SCIP_INVALIDDATA;
7297 	      }
7298 	      break;
7299 	
7300 	   case SCIP_VARSTATUS_MULTAGGR:
7301 	      SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7302 	      return SCIP_INVALIDDATA;
7303 	
7304 	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
7305 	      assert(var->negatedvar != NULL);
7306 	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
7307 	      assert(var->negatedvar->negatedvar == var);
7308 	      SCIP_CALL( SCIPvarChgUbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7309 	            var->data.negate.constant - newbound) );
7310 	      break;
7311 	
7312 	   default:
7313 	      SCIPerrorMessage("unknown variable status\n");
7314 	      return SCIP_INVALIDDATA;
7315 	   }
7316 	
7317 	   return SCIP_OKAY;
7318 	}
7319 	
7320 	/** changes global upper bound of variable; if possible, adjusts bound to integral value;
7321 	 *  updates local upper bound if the global bound is tighter
7322 	 */
7323 	SCIP_RETCODE SCIPvarChgUbGlobal(
7324 	   SCIP_VAR*             var,                /**< problem variable to change */
7325 	   BMS_BLKMEM*           blkmem,             /**< block memory */
7326 	   SCIP_SET*             set,                /**< global SCIP settings */
7327 	   SCIP_STAT*            stat,               /**< problem statistics */
7328 	   SCIP_LP*              lp,                 /**< current LP data, may be NULL for original variables */
7329 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage, may be NULL for original variables */
7330 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
7331 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
7332 	   SCIP_Real             newbound            /**< new bound for variable */
7333 	   )
7334 	{
7335 	   assert(var != NULL);
7336 	   assert(blkmem != NULL);
7337 	   assert(set != NULL);
7338 	   assert(var->scip == set->scip);
7339 	
7340 	   /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7341 	    * of the domain within feastol
7342 	    */
7343 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
7344 	
7345 	   /* adjust bound to integral value if variable is of integral type */
7346 	   newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7347 	
7348 	   /* check that the adjusted bound is feasible
7349 	    * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
7350 	    *       here because we reset bounds to their original value!
7351 	    */
7352 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
7353 	
7354 	   if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7355 	   {
7356 	      /* we do not want to undercut the lowerbound, which could have happened due to numerics */
7357 	      newbound = MAX(newbound, var->glbdom.lb);
7358 	   }
7359 	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7360 	
7361 	   /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
7362 	    * SCIPvarFix() allows fixings that are outside of the domain within feastol
7363 	    */
7364 	   assert(lp == NULL || SCIPsetIsFeasGE(set, var->glbdom.ub, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
7365 	
7366 	   SCIPsetDebugMsg(set, "changing global upper bound of <%s> from %g to %g\n", var->name, var->glbdom.ub, newbound);
7367 	
7368 	   if( SCIPsetIsEQ(set, var->glbdom.ub, newbound) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) )  /*lint !e777*/
7369 	      return SCIP_OKAY;
7370 	
7371 	   /* change bounds of attached variables */
7372 	   switch( SCIPvarGetStatus(var) )
7373 	   {
7374 	   case SCIP_VARSTATUS_ORIGINAL:
7375 	      if( var->data.original.transvar != NULL )
7376 	      {
7377 	         SCIP_CALL( SCIPvarChgUbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7378 	               newbound) );
7379 	      }
7380 	      else
7381 	      {
7382 	         assert(set->stage == SCIP_STAGE_PROBLEM);
7383 	         if( newbound < SCIPvarGetUbLocal(var) )
7384 	         {
7385 	            SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7386 	         }
7387 	         SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7388 	      }
7389 	      break;
7390 	
7391 	   case SCIP_VARSTATUS_COLUMN:
7392 	   case SCIP_VARSTATUS_LOOSE:
7393 	      if( newbound < SCIPvarGetUbLocal(var) )
7394 	      {
7395 	         SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7396 	      }
7397 	      SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7398 	      break;
7399 	
7400 	   case SCIP_VARSTATUS_FIXED:
7401 	      SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7402 	      return SCIP_INVALIDDATA;
7403 	
7404 	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
7405 	      assert(var->data.aggregate.var != NULL);
7406 	      if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7407 	      {
7408 	         SCIP_Real childnewbound;
7409 	
7410 	         /* a > 0 -> change lower bound of y */
7411 	         assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
7412 	            || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7413 	               var->data.aggregate.var->glbdom.ub * var->data.aggregate.scalar + var->data.aggregate.constant));
7414 	         if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7415 	            childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7416 	         else
7417 	            childnewbound = newbound;
7418 	         SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7419 	               childnewbound) );
7420 	      }
7421 	      else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7422 	      {
7423 	         SCIP_Real childnewbound;
7424 	
7425 	         /* a < 0 -> change upper bound of y */
7426 	         assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
7427 	            || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7428 	               var->data.aggregate.var->glbdom.lb * var->data.aggregate.scalar + var->data.aggregate.constant));
7429 	         if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7430 	            childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7431 	         else
7432 	            childnewbound = -newbound;
7433 	         SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7434 	               childnewbound) );
7435 	      }
7436 	      else
7437 	      {
7438 	         SCIPerrorMessage("scalar is zero in aggregation\n");
7439 	         return SCIP_INVALIDDATA;
7440 	      }
7441 	      break;
7442 	
7443 	   case SCIP_VARSTATUS_MULTAGGR:
7444 	      SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7445 	      return SCIP_INVALIDDATA;
7446 	
7447 	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
7448 	      assert(var->negatedvar != NULL);
7449 	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
7450 	      assert(var->negatedvar->negatedvar == var);
7451 	      SCIP_CALL( SCIPvarChgLbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7452 	            var->data.negate.constant - newbound) );
7453 	      break;
7454 	
7455 	   default:
7456 	      SCIPerrorMessage("unknown variable status\n");
7457 	      return SCIP_INVALIDDATA;
7458 	   }
7459 	
7460 	   return SCIP_OKAY;
7461 	}
7462 	
7463 	/** changes lazy lower bound of the variable, this is only possible if the variable is not in the LP yet */
7464 	SCIP_RETCODE SCIPvarChgLbLazy(
7465 	   SCIP_VAR*             var,                /**< problem variable */
7466 	   SCIP_SET*             set,                /**< global SCIP settings */
7467 	   SCIP_Real             lazylb              /**< the lazy lower bound to be set */
7468 	   )
7469 	{
7470 	   assert(var != NULL);
7471 	   assert(var->probindex != -1);
7472 	   assert(SCIPsetIsFeasGE(set, var->glbdom.ub, lazylb));
7473 	   assert(SCIPsetIsFeasGE(set, var->lazyub, lazylb));
7474 	   assert(set != NULL);
7475 	   assert(var->scip == set->scip);
7476 	
7477 	   /* variable should not be in the LP */
7478 	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN )
7479 	      return SCIP_INVALIDCALL;
7480 	
7481 	   var->lazylb = lazylb;
7482 	
7483 	   return SCIP_OKAY;
7484 	}
7485 	
7486 	/** changes lazy upper bound of the variable, this is only possible if the variable is not in the LP yet */
7487 	SCIP_RETCODE SCIPvarChgUbLazy(
7488 	   SCIP_VAR*             var,                /**< problem variable */
7489 	   SCIP_SET*             set,                /**< global SCIP settings */
7490 	   SCIP_Real             lazyub              /**< the lazy lower bound to be set */
7491 	   )
7492 	{
7493 	   assert(var != NULL);
7494 	   assert(var->probindex != -1);
7495 	   assert(SCIPsetIsFeasGE(set, lazyub, var->glbdom.lb));
7496 	   assert(SCIPsetIsFeasGE(set, lazyub, var->lazylb));
7497 	   assert(set != NULL);
7498 	   assert(var->scip == set->scip);
7499 	
7500 	   /* variable should not be in the LP */
7501 	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN )
7502 	      return SCIP_INVALIDCALL;
7503 	
7504 	   var->lazyub = lazyub;
7505 	
7506 	   return SCIP_OKAY;
7507 	}
7508 	
7509 	
7510 	/** changes global bound of variable; if possible, adjusts bound to integral value;
7511 	 *  updates local bound if the global bound is tighter
7512 	 */
7513 	SCIP_RETCODE SCIPvarChgBdGlobal(
7514 	   SCIP_VAR*             var,                /**< problem variable to change */
7515 	   BMS_BLKMEM*           blkmem,             /**< block memory */
7516 	   SCIP_SET*             set,                /**< global SCIP settings */
7517 	   SCIP_STAT*            stat,               /**< problem statistics */
7518 	   SCIP_LP*              lp,                 /**< current LP data, may be NULL for original variables */
7519 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage, may be NULL for original variables */
7520 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
7521 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
7522 	   SCIP_Real             newbound,           /**< new bound for variable */
7523 	   SCIP_BOUNDTYPE        boundtype           /**< type of bound: lower or upper bound */
7524 	   )
7525 	{
7526 	   /* apply bound change to the LP data */
7527 	   switch( boundtype )
7528 	   {
7529 	   case SCIP_BOUNDTYPE_LOWER:
7530 	      return SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7531 	   case SCIP_BOUNDTYPE_UPPER:
7532 	      return SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7533 	   default:
7534 	      SCIPerrorMessage("unknown bound type\n");
7535 	      return SCIP_INVALIDDATA;
7536 	   }
7537 	}
7538 	
7539 	/** appends LBTIGHTENED or LBRELAXED event to the event queue */
7540 	static
7541 	SCIP_RETCODE varEventLbChanged(
7542 	   SCIP_VAR*             var,                /**< problem variable to change */
7543 	   BMS_BLKMEM*           blkmem,             /**< block memory */
7544 	   SCIP_SET*             set,                /**< global SCIP settings */
7545 	   SCIP_LP*              lp,                 /**< current LP data */
7546 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
7547 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
7548 	   SCIP_Real             oldbound,           /**< old lower bound for variable */
7549 	   SCIP_Real             newbound            /**< new lower bound for variable */
7550 	   )
7551 	{
7552 	   assert(var != NULL);
7553 	   assert(var->eventfilter != NULL);
7554 	   assert(SCIPvarIsTransformed(var));
7555 	   assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.lb || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
7556 	   assert(set != NULL);
7557 	   assert(var->scip == set->scip);
7558 	
7559 	   /* check, if the variable is being tracked for bound changes
7560 	    * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7561 	    */
7562 	   if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_LBCHANGED) != 0)
7563 	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
7564 	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE )
7565 	   {
7566 	      SCIP_EVENT* event;
7567 	
7568 	      SCIPsetDebugMsg(set, "issue LBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7569 	
7570 	      SCIP_CALL( SCIPeventCreateLbChanged(&event, blkmem, var, oldbound, newbound) );
7571 	      SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7572 	   }
7573 	
7574 	   return SCIP_OKAY;
7575 	}
7576 	
7577 	/** appends UBTIGHTENED or UBRELAXED event to the event queue */
7578 	static
7579 	SCIP_RETCODE varEventUbChanged(
7580 	   SCIP_VAR*             var,                /**< problem variable to change */
7581 	   BMS_BLKMEM*           blkmem,             /**< block memory */
7582 	   SCIP_SET*             set,                /**< global SCIP settings */
7583 	   SCIP_LP*              lp,                 /**< current LP data */
7584 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
7585 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
7586 	   SCIP_Real             oldbound,           /**< old upper bound for variable */
7587 	   SCIP_Real             newbound            /**< new upper bound for variable */
7588 	   )
7589 	{
7590 	   assert(var != NULL);
7591 	   assert(var->eventfilter != NULL);
7592 	   assert(SCIPvarIsTransformed(var));
7593 	   assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.ub || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
7594 	   assert(set != NULL);
7595 	   assert(var->scip == set->scip);
7596 	
7597 	   /* check, if the variable is being tracked for bound changes
7598 	    * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7599 	    */
7600 	   if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_UBCHANGED) != 0)
7601 	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
7602 	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE )
7603 	   {
7604 	      SCIP_EVENT* event;
7605 	
7606 	      SCIPsetDebugMsg(set, "issue UBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7607 	
7608 	      SCIP_CALL( SCIPeventCreateUbChanged(&event, blkmem, var, oldbound, newbound) );
7609 	      SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7610 	   }
7611 	
7612 	   return SCIP_OKAY;
7613 	}
7614 	
7615 	/* forward declaration, because both methods call each other recursively */
7616 	
7617 	/* performs the current change in upper bound, changes all parents accordingly */
7618 	static
7619 	SCIP_RETCODE varProcessChgUbLocal(
7620 	   SCIP_VAR*             var,                /**< problem variable to change */
7621 	   BMS_BLKMEM*           blkmem,             /**< block memory */
7622 	   SCIP_SET*             set,                /**< global SCIP settings */
7623 	   SCIP_STAT*            stat,               /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7624 	   SCIP_LP*              lp,                 /**< current LP data, may be NULL for original variables */
7625 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage, may be NULL for original variables */
7626 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
7627 	   SCIP_Real             newbound            /**< new bound for variable */
7628 	   );
7629 	
7630 	/** performs the current change in lower bound, changes all parents accordingly */
7631 	static
7632 	SCIP_RETCODE varProcessChgLbLocal(
7633 	   SCIP_VAR*             var,                /**< problem variable to change */
7634 	   BMS_BLKMEM*           blkmem,             /**< block memory */
7635 	   SCIP_SET*             set,                /**< global SCIP settings */
7636 	   SCIP_STAT*            stat,               /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7637 	   SCIP_LP*              lp,                 /**< current LP data, may be NULL for original variables */
7638 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage, may be NULL for original variables */
7639 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
7640 	   SCIP_Real             newbound            /**< new bound for variable */
7641 	   )
7642 	{
7643 	   SCIP_VAR* parentvar;
7644 	   SCIP_Real oldbound;
7645 	   int i;
7646 	
7647 	   assert(var != NULL);
7648 	   assert(set != NULL);
7649 	   assert(var->scip == set->scip);
7650 	   assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7651 	            || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7652 	      || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && (SCIPsetIsIntegral(set, newbound)
7653 	            || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7654 	      || SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
7655 	
7656 	   /* check that the bound is feasible */
7657 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, var->glbdom.ub));
7658 	   /* adjust bound to integral value if variable is of integral type */
7659 	   newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7660 	
7661 	   if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7662 	   {
7663 	      /* we do not want to exceed the upper bound, which could have happened due to numerics */
7664 	      newbound = MIN(newbound, var->locdom.ub);
7665 	
7666 	      /* we do not want to undercut the global lower bound, which could have happened due to numerics */
7667 	      newbound = MAX(newbound, var->glbdom.lb);
7668 	   }
7669 	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7670 	
7671 	   SCIPsetDebugMsg(set, "process changing lower bound of <%s> from %g to %g\n", var->name, var->locdom.lb, newbound);
7672 	
7673 	   if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && var->glbdom.lb != var->locdom.lb ) /*lint !e777*/
7674 	      newbound = var->glbdom.lb;
7675 	   else if( SCIPsetIsEQ(set, newbound, var->locdom.lb) && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) )  /*lint !e777*/
7676 	      return SCIP_OKAY;
7677 	
7678 	   /* change the bound */
7679 	   oldbound = var->locdom.lb;
7680 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->locdom.ub));
7681 	   var->locdom.lb = newbound;
7682 	
7683 	   /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7684 	    * once update the statistic
7685 	    */
7686 	   if( stat != NULL )
7687 	      SCIPstatIncrement(stat, set, domchgcount);
7688 	
7689 	   if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7690 	   {
7691 	      /* merges overlapping holes into single holes, moves bounds respectively */
7692 	      domMerge(&var->locdom, blkmem, set, &newbound, NULL);
7693 	   }
7694 	
7695 	   /* issue bound change event */
7696 	   assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7697 	   if( var->eventfilter != NULL )
7698 	   {
7699 	      SCIP_CALL( varEventLbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7700 	   }
7701 	
7702 	   /* process parent variables */
7703 	   for( i = 0; i < var->nparentvars; ++i )
7704 	   {
7705 	      parentvar = var->parentvars[i];
7706 	      assert(parentvar != NULL);
7707 	
7708 	      switch( SCIPvarGetStatus(parentvar) )
7709 	      {
7710 	      case SCIP_VARSTATUS_ORIGINAL:
7711 	         SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7712 	         break;
7713 	
7714 	      case SCIP_VARSTATUS_COLUMN:
7715 	      case SCIP_VARSTATUS_LOOSE:
7716 	      case SCIP_VARSTATUS_FIXED:
7717 	      case SCIP_VARSTATUS_MULTAGGR:
7718 	         SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7719 	         return SCIP_INVALIDDATA;
7720 	
7721 	      case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
7722 	         assert(parentvar->data.aggregate.var == var);
7723 	         if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7724 	         {
7725 	            SCIP_Real parentnewbound;
7726 	
7727 	            /* a > 0 -> change lower bound of y */
7728 	            assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, -oldbound)
7729 	               || SCIPsetIsFeasEQ(set, parentvar->locdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7730 	               || (SCIPsetIsZero(set, parentvar->locdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7731 	
7732 	            if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7733 	            {
7734 	               parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7735 	               /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7736 	                * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7737 	                * as a result, the parent's lower bound is set to it's upper bound, and not above
7738 	                */
7739 	               if( parentnewbound > parentvar->glbdom.ub )
7740 	               {
7741 	                  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7742 	                  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7743 	                  parentnewbound = parentvar->glbdom.ub;
7744 	               }
7745 	            }
7746 	            else
7747 	               parentnewbound = newbound;
7748 	            SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7749 	         }
7750 	         else
7751 	         {
7752 	            SCIP_Real parentnewbound;
7753 	
7754 	            /* a < 0 -> change upper bound of y */
7755 	            assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7756 	            assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, -oldbound)
7757 	               || SCIPsetIsFeasEQ(set, parentvar->locdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7758 	               || (SCIPsetIsZero(set, parentvar->locdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7759 	
7760 	            if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7761 	            {
7762 	               parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7763 	               /* if parent's new upper bound is below its lower bound, then this could be due to numerical difficulties, e.g., if numbers are large
7764 	                * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7765 	                * as a result, the parent's upper bound is set to it's lower bound, and not below
7766 	                */
7767 	               if( parentnewbound < parentvar->glbdom.lb )
7768 	               {
7769 	                  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7770 	                  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7771 	                  parentnewbound = parentvar->glbdom.lb;
7772 	               }
7773 	            }
7774 	            else
7775 	               parentnewbound = -newbound;
7776 	            SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7777 	         }
7778 	         break;
7779 	
7780 	      case SCIP_VARSTATUS_NEGATED: /* x = offset - x'  ->  x' = offset - x */
7781 	         assert(parentvar->negatedvar != NULL);
7782 	         assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7783 	         assert(parentvar->negatedvar->negatedvar == parentvar);
7784 	         SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7785 	               parentvar->data.negate.constant - newbound) );
7786 	         break;
7787 	
7788 	      default:
7789 	         SCIPerrorMessage("unknown variable status\n");
7790 	         return SCIP_INVALIDDATA;
7791 	      }
7792 	   }
7793 	
7794 	   return SCIP_OKAY;
7795 	}
7796 	
7797 	/** performs the current change in upper bound, changes all parents accordingly */
7798 	static
7799 	SCIP_RETCODE varProcessChgUbLocal(
7800 	   SCIP_VAR*             var,                /**< problem variable to change */
7801 	   BMS_BLKMEM*           blkmem,             /**< block memory */
7802 	   SCIP_SET*             set,                /**< global SCIP settings */
7803 	   SCIP_STAT*            stat,               /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7804 	   SCIP_LP*              lp,                 /**< current LP data, may be NULL for original variables */
7805 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage, may be NULL for original variables */
7806 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
7807 	   SCIP_Real             newbound            /**< new bound for variable */
7808 	   )
7809 	{
7810 	   SCIP_VAR* parentvar;
7811 	   SCIP_Real oldbound;
7812 	   int i;
7813 	
7814 	   assert(var != NULL);
7815 	   assert(set != NULL);
7816 	   assert(var->scip == set->scip);
7817 	   assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7818 	            || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7819 	      || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && (SCIPsetIsIntegral(set, newbound)
7820 	            || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7821 	      || SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
7822 	
7823 	   /* check that the bound is feasible */
7824 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, var->glbdom.lb));
7825 	   /* adjust bound to integral value if variable is of integral type */
7826 	   newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7827 	
7828 	   if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7829 	   {
7830 	      /* we do not want to undercut the lower bound, which could have happened due to numerics */
7831 	      newbound = MAX(newbound, var->locdom.lb);
7832 	
7833 	      /* we do not want to exceed the global upper bound, which could have happened due to numerics */
7834 	      newbound = MIN(newbound, var->glbdom.ub);
7835 	   }
7836 	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7837 	
7838 	   SCIPsetDebugMsg(set, "process changing upper bound of <%s> from %g to %g\n", var->name, var->locdom.ub, newbound);
7839 	
7840 	   if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && var->glbdom.ub != var->locdom.ub  ) /*lint !e777*/
7841 	      newbound = var->glbdom.ub;
7842 	   else if( SCIPsetIsEQ(set, newbound, var->locdom.ub) && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) )  /*lint !e777*/
7843 	      return SCIP_OKAY;
7844 	
7845 	   /* change the bound */
7846 	   oldbound = var->locdom.ub;
7847 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->locdom.lb));
7848 	   var->locdom.ub = newbound;
7849 	
7850 	   /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7851 	    * once update the statistic
7852 	    */
7853 	   if( stat != NULL )
7854 	      SCIPstatIncrement(stat, set, domchgcount);
7855 	
7856 	   if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7857 	   {
7858 	      /* merges overlapping holes into single holes, moves bounds respectively */
7859 	      domMerge(&var->locdom, blkmem, set, NULL, &newbound);
7860 	   }
7861 	
7862 	   /* issue bound change event */
7863 	   assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7864 	   if( var->eventfilter != NULL )
7865 	   {
7866 	      SCIP_CALL( varEventUbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7867 	   }
7868 	
7869 	   /* process parent variables */
7870 	   for( i = 0; i < var->nparentvars; ++i )
7871 	   {
7872 	      parentvar = var->parentvars[i];
7873 	      assert(parentvar != NULL);
7874 	
7875 	      switch( SCIPvarGetStatus(parentvar) )
7876 	      {
7877 	      case SCIP_VARSTATUS_ORIGINAL:
7878 	         SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7879 	         break;
7880 	
7881 	      case SCIP_VARSTATUS_COLUMN:
7882 	      case SCIP_VARSTATUS_LOOSE:
7883 	      case SCIP_VARSTATUS_FIXED:
7884 	      case SCIP_VARSTATUS_MULTAGGR:
7885 	         SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7886 	         return SCIP_INVALIDDATA;
7887 	
7888 	      case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
7889 	         assert(parentvar->data.aggregate.var == var);
7890 	         if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7891 	         {
7892 	            SCIP_Real parentnewbound;
7893 	
7894 	            /* a > 0 -> change upper bound of x */
7895 	            assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, oldbound)
7896 	               || SCIPsetIsFeasEQ(set, parentvar->locdom.ub,
7897 	                  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7898 	            if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7899 	            {
7900 	               parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7901 	               /* if parent's new upper bound is below its lower bound, then this could be due to numerical difficulties, e.g., if numbers are large
7902 	                * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7903 	                * as a result, the parent's upper bound is set to it's lower bound, and not below
7904 	                */
7905 	               if( parentnewbound < parentvar->glbdom.lb )
7906 	               {
7907 	                  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7908 	                  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7909 	                  parentnewbound = parentvar->glbdom.lb;
7910 	               }
7911 	            }
7912 	            else
7913 	               parentnewbound = newbound;
7914 	            SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7915 	         }
7916 	         else
7917 	         {
7918 	            SCIP_Real parentnewbound;
7919 	
7920 	            /* a < 0 -> change lower bound of x */
7921 	            assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7922 	            assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, oldbound)
7923 	               || SCIPsetIsFeasEQ(set, parentvar->locdom.lb,
7924 	                  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7925 	            if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7926 	            {
7927 	               parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7928 	               /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7929 	                * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7930 	                * as a result, the parent's lower bound is set to it's upper bound, and not above
7931 	                */
7932 	               if( parentnewbound > parentvar->glbdom.ub )
7933 	               {
7934 	                  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7935 	                  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7936 	                  parentnewbound = parentvar->glbdom.ub;
7937 	               }
7938 	            }
7939 	            else
7940 	               parentnewbound = -newbound;
7941 	            SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7942 	         }
7943 	         break;
7944 	
7945 	      case SCIP_VARSTATUS_NEGATED: /* x = offset - x'  ->  x' = offset - x */
7946 	         assert(parentvar->negatedvar != NULL);
7947 	         assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7948 	         assert(parentvar->negatedvar->negatedvar == parentvar);
7949 	         SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7950 	               parentvar->data.negate.constant - newbound) );
7951 	         break;
7952 	
7953 	      default:
7954 	         SCIPerrorMessage("unknown variable status\n");
7955 	         return SCIP_INVALIDDATA;
7956 	      }
7957 	   }
7958 	
7959 	   return SCIP_OKAY;
7960 	}
7961 	
7962 	/** changes current local lower bound of variable; if possible, adjusts bound to integral value; stores inference
7963 	 *  information in variable
7964 	 */
7965 	SCIP_RETCODE SCIPvarChgLbLocal(
7966 	   SCIP_VAR*             var,                /**< problem variable to change */
7967 	   BMS_BLKMEM*           blkmem,             /**< block memory */
7968 	   SCIP_SET*             set,                /**< global SCIP settings */
7969 	   SCIP_STAT*            stat,               /**< problem statistics */
7970 	   SCIP_LP*              lp,                 /**< current LP data, may be NULL for original variables */
7971 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage, may be NULL for original variables */
7972 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
7973 	   SCIP_Real             newbound            /**< new bound for variable */
7974 	   )
7975 	{
7976 	   assert(var != NULL);
7977 	   assert(blkmem != NULL);
7978 	   assert(set != NULL);
7979 	   assert(var->scip == set->scip);
7980 	
7981 	   /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7982 	    * of the domain within feastol
7983 	    */
7984 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7985 	
7986 	   /* adjust bound to integral value if variable is of integral type */
7987 	   newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7988 	
7989 	   /* check that the adjusted bound is feasible */
7990 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7991 	
7992 	   if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7993 	   {
7994 	      /* we do not want to exceed the upperbound, which could have happened due to numerics */
7995 	      newbound = MIN(newbound, var->locdom.ub);
7996 	   }
7997 	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7998 	
7999 	   SCIPsetDebugMsg(set, "changing lower bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
8000 	
8001 	   if( SCIPsetIsEQ(set, var->locdom.lb, newbound) && (!SCIPsetIsEQ(set, var->glbdom.lb, newbound) || var->locdom.lb == newbound) /*lint !e777*/
8002 	         && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) ) /*lint !e777*/
8003 	      return SCIP_OKAY;
8004 	
8005 	   /* change bounds of attached variables */
8006 	   switch( SCIPvarGetStatus(var) )
8007 	   {
8008 	   case SCIP_VARSTATUS_ORIGINAL:
8009 	      if( var->data.original.transvar != NULL )
8010 	      {
8011 	         SCIP_CALL( SCIPvarChgLbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
8012 	               newbound) );
8013 	      }
8014 	      else
8015 	      {
8016 	         assert(set->stage == SCIP_STAGE_PROBLEM);
8017 	         SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8018 	      }
8019 	      break;
8020 	
8021 	   case SCIP_VARSTATUS_COLUMN:
8022 	   case SCIP_VARSTATUS_LOOSE:
8023 	      SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8024 	      break;
8025 	
8026 	   case SCIP_VARSTATUS_FIXED:
8027 	      SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8028 	      return SCIP_INVALIDDATA;
8029 	
8030 	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
8031 	      assert(var->data.aggregate.var != NULL);
8032 	      if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8033 	      {
8034 	         SCIP_Real childnewbound;
8035 	
8036 	         /* a > 0 -> change lower bound of y */
8037 	         assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
8038 	            || SCIPsetIsFeasEQ(set, var->locdom.lb,
8039 	               var->data.aggregate.var->locdom.lb * var->data.aggregate.scalar + var->data.aggregate.constant));
8040 	         if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8041 	            childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8042 	         else
8043 	            childnewbound = newbound;
8044 	         SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8045 	               childnewbound) );
8046 	      }
8047 	      else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8048 	      {
8049 	         SCIP_Real childnewbound;
8050 	
8051 	         /* a < 0 -> change upper bound of y */
8052 	         assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
8053 	            || SCIPsetIsFeasEQ(set, var->locdom.lb,
8054 	               var->data.aggregate.var->locdom.ub * var->data.aggregate.scalar + var->data.aggregate.constant));
8055 	         if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8056 	            childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8057 	         else
8058 	            childnewbound = -newbound;
8059 	         SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8060 	               childnewbound) );
8061 	      }
8062 	      else
8063 	      {
8064 	         SCIPerrorMessage("scalar is zero in aggregation\n");
8065 	         return SCIP_INVALIDDATA;
8066 	      }
8067 	      break;
8068 	
8069 	   case SCIP_VARSTATUS_MULTAGGR:
8070 	      SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8071 	      return SCIP_INVALIDDATA;
8072 	
8073 	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
8074 	      assert(var->negatedvar != NULL);
8075 	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
8076 	      assert(var->negatedvar->negatedvar == var);
8077 	      SCIP_CALL( SCIPvarChgUbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
8078 	            var->data.negate.constant - newbound) );
8079 	      break;
8080 	
8081 	   default:
8082 	      SCIPerrorMessage("unknown variable status\n");
8083 	      return SCIP_INVALIDDATA;
8084 	   }
8085 	
8086 	   return SCIP_OKAY;
8087 	}
8088 	
8089 	/** changes current local upper bound of variable; if possible, adjusts bound to integral value; stores inference
8090 	 *  information in variable
8091 	 */
8092 	SCIP_RETCODE SCIPvarChgUbLocal(
8093 	   SCIP_VAR*             var,                /**< problem variable to change */
8094 	   BMS_BLKMEM*           blkmem,             /**< block memory */
8095 	   SCIP_SET*             set,                /**< global SCIP settings */
8096 	   SCIP_STAT*            stat,               /**< problem statistics */
8097 	   SCIP_LP*              lp,                 /**< current LP data, may be NULL for original variables */
8098 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage, may be NULL for original variables */
8099 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
8100 	   SCIP_Real             newbound            /**< new bound for variable */
8101 	   )
8102 	{
8103 	   assert(var != NULL);
8104 	   assert(blkmem != NULL);
8105 	   assert(set != NULL);
8106 	   assert(var->scip == set->scip);
8107 	
8108 	   /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
8109 	    * of the domain within feastol
8110 	    */
8111 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
8112 	
8113 	   /* adjust bound to integral value if variable is of integral type */
8114 	   newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
8115 	
8116 	   /* check that the adjusted bound is feasible */
8117 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
8118 	
8119 	   if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
8120 	   {
8121 	      /* we do not want to undercut the lowerbound, which could have happened due to numerics */
8122 	      newbound = MAX(newbound, var->locdom.lb);
8123 	   }
8124 	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
8125 	
8126 	   SCIPsetDebugMsg(set, "changing upper bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
8127 	
8128 	   if( SCIPsetIsEQ(set, var->locdom.ub, newbound) && (!SCIPsetIsEQ(set, var->glbdom.ub, newbound) || var->locdom.ub == newbound) /*lint !e777*/
8129 	      && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) ) /*lint !e777*/
8130 	      return SCIP_OKAY;
8131 	
8132 	   /* change bounds of attached variables */
8133 	   switch( SCIPvarGetStatus(var) )
8134 	   {
8135 	   case SCIP_VARSTATUS_ORIGINAL:
8136 	      if( var->data.original.transvar != NULL )
8137 	      {
8138 	         SCIP_CALL( SCIPvarChgUbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8139 	      }
8140 	      else
8141 	      {
8142 	         assert(set->stage == SCIP_STAGE_PROBLEM);
8143 	         SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8144 	      }
8145 	      break;
8146 	
8147 	   case SCIP_VARSTATUS_COLUMN:
8148 	   case SCIP_VARSTATUS_LOOSE:
8149 	      SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8150 	      break;
8151 	
8152 	   case SCIP_VARSTATUS_FIXED:
8153 	      SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8154 	      return SCIP_INVALIDDATA;
8155 	
8156 	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
8157 	      assert(var->data.aggregate.var != NULL);
8158 	      if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8159 	      {
8160 	         SCIP_Real childnewbound;
8161 	
8162 	         /* a > 0 -> change upper bound of y */
8163 	         assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
8164 	            || SCIPsetIsFeasEQ(set, var->locdom.ub,
8165 	               var->data.aggregate.var->locdom.ub * var->data.aggregate.scalar + var->data.aggregate.constant));
8166 	         if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8167 	            childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8168 	         else
8169 	            childnewbound = newbound;
8170 	         SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8171 	               childnewbound) );
8172 	      }
8173 	      else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8174 	      {
8175 	         SCIP_Real childnewbound;
8176 	
8177 	         /* a < 0 -> change lower bound of y */
8178 	         assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
8179 	            || SCIPsetIsFeasEQ(set, var->locdom.ub,
8180 	               var->data.aggregate.var->locdom.lb * var->data.aggregate.scalar + var->data.aggregate.constant));
8181 	         if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8182 	            childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8183 	         else
8184 	            childnewbound = -newbound;
8185 	         SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8186 	               childnewbound) );
8187 	      }
8188 	      else
8189 	      {
8190 	         SCIPerrorMessage("scalar is zero in aggregation\n");
8191 	         return SCIP_INVALIDDATA;
8192 	      }
8193 	      break;
8194 	
8195 	   case SCIP_VARSTATUS_MULTAGGR:
8196 	      SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8197 	      return SCIP_INVALIDDATA;
8198 	
8199 	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
8200 	      assert(var->negatedvar != NULL);
8201 	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
8202 	      assert(var->negatedvar->negatedvar == var);
8203 	      SCIP_CALL( SCIPvarChgLbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
8204 	            var->data.negate.constant - newbound) );
8205 	      break;
8206 	
8207 	   default:
8208 	      SCIPerrorMessage("unknown variable status\n");
8209 	      return SCIP_INVALIDDATA;
8210 	   }
8211 	
8212 	   return SCIP_OKAY;
8213 	}
8214 	
8215 	/** changes current local bound of variable; if possible, adjusts bound to integral value; stores inference
8216 	 *  information in variable
8217 	 */
8218 	SCIP_RETCODE SCIPvarChgBdLocal(
8219 	   SCIP_VAR*             var,                /**< problem variable to change */
8220 	   BMS_BLKMEM*           blkmem,             /**< block memory */
8221 	   SCIP_SET*             set,                /**< global SCIP settings */
8222 	   SCIP_STAT*            stat,               /**< problem statistics */
8223 	   SCIP_LP*              lp,                 /**< current LP data, may be NULL for original variables */
8224 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage, may be NULL for original variables */
8225 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
8226 	   SCIP_Real             newbound,           /**< new bound for variable */
8227 	   SCIP_BOUNDTYPE        boundtype           /**< type of bound: lower or upper bound */
8228 	   )
8229 	{
8230 	   /* apply bound change to the LP data */
8231 	   switch( boundtype )
8232 	   {
8233 	   case SCIP_BOUNDTYPE_LOWER:
8234 	      return SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
8235 	   case SCIP_BOUNDTYPE_UPPER:
8236 	      return SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
8237 	   default:
8238 	      SCIPerrorMessage("unknown bound type\n");
8239 	      return SCIP_INVALIDDATA;
8240 	   }
8241 	}
8242 	
8243 	/** changes lower bound of variable in current dive; if possible, adjusts bound to integral value */
8244 	SCIP_RETCODE SCIPvarChgLbDive(
8245 	   SCIP_VAR*             var,                /**< problem variable to change */
8246 	   SCIP_SET*             set,                /**< global SCIP settings */
8247 	   SCIP_LP*              lp,                 /**< current LP data */
8248 	   SCIP_Real             newbound            /**< new bound for variable */
8249 	   )
8250 	{
8251 	   assert(var != NULL);
8252 	   assert(set != NULL);
8253 	   assert(var->scip == set->scip);
8254 	   assert(lp != NULL);
8255 	   assert(SCIPlpDiving(lp));
8256 	
8257 	   /* adjust bound for integral variables */
8258 	   SCIPvarAdjustLb(var, set, &newbound);
8259 	
8260 	   SCIPsetDebugMsg(set, "changing lower bound of <%s> to %g in current dive\n", var->name, newbound);
8261 	
8262 	   /* change bounds of attached variables */
8263 	   switch( SCIPvarGetStatus(var) )
8264 	   {
8265 	   case SCIP_VARSTATUS_ORIGINAL:
8266 	      assert(var->data.original.transvar != NULL);
8267 	      SCIP_CALL( SCIPvarChgLbDive(var->data.original.transvar, set, lp, newbound) );
8268 	      break;
8269 	
8270 	   case SCIP_VARSTATUS_COLUMN:
8271 	      assert(var->data.col != NULL);
8272 	      SCIP_CALL( SCIPcolChgLb(var->data.col, set, lp, newbound) );
8273 	      break;
8274 	
8275 	   case SCIP_VARSTATUS_LOOSE:
8276 	      SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
8277 	      return SCIP_INVALIDDATA;
8278 	
8279 	   case SCIP_VARSTATUS_FIXED:
8280 	      SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8281 	      return SCIP_INVALIDDATA;
8282 	
8283 	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
8284 	      assert(var->data.aggregate.var != NULL);
8285 	      if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8286 	      {
8287 	         SCIP_Real childnewbound;
8288 	
8289 	         /* a > 0 -> change lower bound of y */
8290 	         if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8291 	            childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8292 	         else
8293 	            childnewbound = newbound;
8294 	         SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8295 	      }
8296 	      else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8297 	      {
8298 	         SCIP_Real childnewbound;
8299 	
8300 	         /* a < 0 -> change upper bound of y */
8301 	         if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8302 	            childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8303 	         else
8304 	            childnewbound = -newbound;
8305 	         SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8306 	      }
8307 	      else
8308 	      {
8309 	         SCIPerrorMessage("scalar is zero in aggregation\n");
8310 	         return SCIP_INVALIDDATA;
8311 	      }
8312 	      break;
8313 	
8314 	   case SCIP_VARSTATUS_MULTAGGR:
8315 	      SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8316 	      return SCIP_INVALIDDATA;
8317 	
8318 	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
8319 	      assert(var->negatedvar != NULL);
8320 	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
8321 	      assert(var->negatedvar->negatedvar == var);
8322 	      SCIP_CALL( SCIPvarChgUbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8323 	      break;
8324 	
8325 	   default:
8326 	      SCIPerrorMessage("unknown variable status\n");
8327 	      return SCIP_INVALIDDATA;
8328 	   }
8329 	
8330 	   return SCIP_OKAY;
8331 	}
8332 	
8333 	/** changes upper bound of variable in current dive; if possible, adjusts bound to integral value */
8334 	SCIP_RETCODE SCIPvarChgUbDive(
8335 	   SCIP_VAR*             var,                /**< problem variable to change */
8336 	   SCIP_SET*             set,                /**< global SCIP settings */
8337 	   SCIP_LP*              lp,                 /**< current LP data */
8338 	   SCIP_Real             newbound            /**< new bound for variable */
8339 	   )
8340 	{
8341 	   assert(var != NULL);
8342 	   assert(set != NULL);
8343 	   assert(var->scip == set->scip);
8344 	   assert(lp != NULL);
8345 	   assert(SCIPlpDiving(lp));
8346 	
8347 	   /* adjust bound for integral variables */
8348 	   SCIPvarAdjustUb(var, set, &newbound);
8349 	
8350 	   SCIPsetDebugMsg(set, "changing upper bound of <%s> to %g in current dive\n", var->name, newbound);
8351 	
8352 	   /* change bounds of attached variables */
8353 	   switch( SCIPvarGetStatus(var) )
8354 	   {
8355 	   case SCIP_VARSTATUS_ORIGINAL:
8356 	      assert(var->data.original.transvar != NULL);
8357 	      SCIP_CALL( SCIPvarChgUbDive(var->data.original.transvar, set, lp, newbound) );
8358 	      break;
8359 	
8360 	   case SCIP_VARSTATUS_COLUMN:
8361 	      assert(var->data.col != NULL);
8362 	      SCIP_CALL( SCIPcolChgUb(var->data.col, set, lp, newbound) );
8363 	      break;
8364 	
8365 	   case SCIP_VARSTATUS_LOOSE:
8366 	      SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
8367 	      return SCIP_INVALIDDATA;
8368 	
8369 	   case SCIP_VARSTATUS_FIXED:
8370 	      SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8371 	      return SCIP_INVALIDDATA;
8372 	
8373 	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
8374 	      assert(var->data.aggregate.var != NULL);
8375 	      if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8376 	      {
8377 	         SCIP_Real childnewbound;
8378 	
8379 	         /* a > 0 -> change upper bound of y */
8380 	         if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8381 	            childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8382 	         else
8383 	            childnewbound = newbound;
8384 	         SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8385 	      }
8386 	      else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8387 	      {
8388 	         SCIP_Real childnewbound;
8389 	
8390 	         /* a < 0 -> change lower bound of y */
8391 	         if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8392 	            childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8393 	         else
8394 	            childnewbound = -newbound;
8395 	         SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8396 	      }
8397 	      else
8398 	      {
8399 	         SCIPerrorMessage("scalar is zero in aggregation\n");
8400 	         return SCIP_INVALIDDATA;
8401 	      }
8402 	      break;
8403 	
8404 	   case SCIP_VARSTATUS_MULTAGGR:
8405 	      SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8406 	      return SCIP_INVALIDDATA;
8407 	
8408 	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
8409 	      assert(var->negatedvar != NULL);
8410 	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
8411 	      assert(var->negatedvar->negatedvar == var);
8412 	      SCIP_CALL( SCIPvarChgLbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8413 	      break;
8414 	
8415 	   default:
8416 	      SCIPerrorMessage("unknown variable status\n");
8417 	      return SCIP_INVALIDDATA;
8418 	   }
8419 	
8420 	   return SCIP_OKAY;
8421 	}
8422 	
8423 	/** for a multi-aggregated variable, gives the local lower bound computed by adding the local bounds from all
8424 	 *  aggregation variables, this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is
8425 	 *  not updated if bounds of aggregation variables are changing
8426 	 *
8427 	 *  calling this function for a non-multi-aggregated variable is not allowed
8428 	 */
8429 	SCIP_Real SCIPvarGetMultaggrLbLocal(
8430 	   SCIP_VAR*             var,                /**< problem variable */
8431 	   SCIP_SET*             set                 /**< global SCIP settings */
8432 	   )
8433 	{
8434 	   int i;
8435 	   SCIP_Real lb;
8436 	   SCIP_Real bnd;
8437 	   SCIP_VAR* aggrvar;
8438 	   SCIP_Bool posinf;
8439 	   SCIP_Bool neginf;
8440 	
8441 	   assert(var != NULL);
8442 	   assert(set != NULL);
8443 	   assert(var->scip == set->scip);
8444 	   assert((SCIP_VARSTATUS) var->varstatus == SCIP_VARSTATUS_MULTAGGR);
8445 	
8446 	   posinf = FALSE;
8447 	   neginf = FALSE;
8448 	   lb = var->data.multaggr.constant;
8449 	   for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8450 	   {
8451 	      aggrvar = var->data.multaggr.vars[i];
8452 	      if( var->data.multaggr.scalars[i] > 0.0 )
8453 	      {
8454 	         bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8455 	
8456 	         if( SCIPsetIsInfinity(set, bnd) )
8457 	            posinf = TRUE;
8458 	         else if( SCIPsetIsInfinity(set, -bnd) )
8459 	            neginf = TRUE;
8460 	         else
8461 	            lb += var->data.multaggr.scalars[i] * bnd;
8462 	      }
8463 	      else
8464 	      {
8465 	         bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8466 	
8467 	         if( SCIPsetIsInfinity(set, -bnd) )
8468 	            posinf = TRUE;
8469 	         else if( SCIPsetIsInfinity(set, bnd) )
8470 	            neginf = TRUE;
8471 	         else
8472 	            lb += var->data.multaggr.scalars[i] * bnd;
8473 	      }
8474 	
8475 	      /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
8476 	       * variable
8477 	       */
8478 	      if( neginf )
8479 	         return SCIPvarGetLbLocal(var);
8480 	   }
8481 	
8482 	   /* if positive infinity flag was set to true return infinity */
8483 	   if( posinf )
8484 	      return SCIPsetInfinity(set);
8485 	
8486 	   return (MAX(lb, SCIPvarGetLbLocal(var))); /*lint !e666*/
8487 	}
8488 	
8489 	/** for a multi-aggregated variable, gives the local upper bound computed by adding the local bounds from all
8490 	 *  aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is
8491 	 *  not updated if bounds of aggregation variables are changing
8492 	 *
8493 	 *  calling this function for a non-multi-aggregated variable is not allowed
8494 	 */
8495 	SCIP_Real SCIPvarGetMultaggrUbLocal(
8496 	   SCIP_VAR*             var,                /**< problem variable */
8497 	   SCIP_SET*             set                 /**< global SCIP settings */
8498 	   )
8499 	{
8500 	   int i;
8501 	   SCIP_Real ub;
8502 	   SCIP_Real bnd;
8503 	   SCIP_VAR* aggrvar;
8504 	   SCIP_Bool posinf;
8505 	   SCIP_Bool neginf;
8506 	
8507 	   assert(var != NULL);
8508 	   assert(set != NULL);
8509 	   assert(var->scip == set->scip);
8510 	   assert((SCIP_VARSTATUS) var->varstatus == SCIP_VARSTATUS_MULTAGGR);
8511 	
8512 	   posinf = FALSE;
8513 	   neginf = FALSE;
8514 	   ub = var->data.multaggr.constant;
8515 	   for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8516 	   {
8517 	      aggrvar = var->data.multaggr.vars[i];
8518 	      if( var->data.multaggr.scalars[i] > 0.0 )
8519 	      {
8520 	         bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8521 	
8522 	         if( SCIPsetIsInfinity(set, bnd) )
8523 	            posinf = TRUE;
8524 	         else if( SCIPsetIsInfinity(set, -bnd) )
8525 	            neginf = TRUE;
8526 	         else
8527 	            ub += var->data.multaggr.scalars[i] * bnd;
8528 	      }
8529 	      else
8530 	      {
8531 	         bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8532 	
8533 	         if( SCIPsetIsInfinity(set, -bnd) )
8534 	            posinf = TRUE;
8535 	         else if( SCIPsetIsInfinity(set, bnd) )
8536 	            neginf = TRUE;
8537 	         else
8538 	            ub += var->data.multaggr.scalars[i] * bnd;
8539 	      }
8540 	
8541 	      /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8542 	       * variable
8543 	       */
8544 	      if( posinf )
8545 	         return SCIPvarGetUbLocal(var);
8546 	   }
8547 	
8548 	   /* if negative infinity flag was set to true return -infinity */
8549 	   if( neginf )
8550 	      return -SCIPsetInfinity(set);
8551 	
8552 	   return (MIN(ub, SCIPvarGetUbLocal(var))); /*lint !e666*/
8553 	}
8554 	
8555 	/** for a multi-aggregated variable, gives the global lower bound computed by adding the global bounds from all
8556 	 *  aggregation variables, this global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is
8557 	 *  not updated if bounds of aggregation variables are changing
8558 	 *
8559 	 *  calling this function for a non-multi-aggregated variable is not allowed
8560 	 */
8561 	SCIP_Real SCIPvarGetMultaggrLbGlobal(
8562 	   SCIP_VAR*             var,                /**< problem variable */
8563 	   SCIP_SET*             set                 /**< global SCIP settings */
8564 	   )
8565 	{
8566 	   int i;
8567 	   SCIP_Real lb;
8568 	   SCIP_Real bnd;
8569 	   SCIP_VAR* aggrvar;
8570 	   SCIP_Bool posinf;
8571 	   SCIP_Bool neginf;
8572 	
8573 	   assert(var != NULL);
8574 	   assert(set != NULL);
8575 	   assert(var->scip == set->scip);
8576 	   assert((SCIP_VARSTATUS) var->varstatus == SCIP_VARSTATUS_MULTAGGR);
8577 	
8578 	   posinf = FALSE;
8579 	   neginf = FALSE;
8580 	   lb = var->data.multaggr.constant;
8581 	   for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8582 	   {
8583 	      aggrvar = var->data.multaggr.vars[i];
8584 	      if( var->data.multaggr.scalars[i] > 0.0 )
8585 	      {
8586 	         bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8587 	
8588 	         if( SCIPsetIsInfinity(set, bnd) )
8589 	            posinf = TRUE;
8590 	         else if( SCIPsetIsInfinity(set, -bnd) )
8591 	            neginf = TRUE;
8592 	         else
8593 	            lb += var->data.multaggr.scalars[i] * bnd;
8594 	      }
8595 	      else
8596 	      {
8597 	         bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8598 	
8599 	         if( SCIPsetIsInfinity(set, -bnd) )
8600 	            posinf = TRUE;
8601 	         else if( SCIPsetIsInfinity(set, bnd) )
8602 	            neginf = TRUE;
8603 	         else
8604 	            lb += var->data.multaggr.scalars[i] * bnd;
8605 	      }
8606 	
8607 	      /* stop if two diffrent infinities (or a -infinity) were found and return global lower bound of multi aggregated
8608 	       * variable
8609 	       */
8610 	      if( neginf )
8611 	         return SCIPvarGetLbGlobal(var);
8612 	   }
8613 	
8614 	   /* if positive infinity flag was set to true return infinity */
8615 	   if( posinf )
8616 	      return SCIPsetInfinity(set);
8617 	
8618 	   return (MAX(lb, SCIPvarGetLbGlobal(var))); /*lint !e666*/
8619 	}
8620 	
8621 	/** for a multi-aggregated variable, gives the global upper bound computed by adding the global bounds from all
8622 	 *  aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is
8623 	 *  not updated if bounds of aggregation variables are changing
8624 	 *
8625 	 *  calling this function for a non-multi-aggregated variable is not allowed
8626 	 */
8627 	SCIP_Real SCIPvarGetMultaggrUbGlobal(
8628 	   SCIP_VAR*             var,                /**< problem variable */
8629 	   SCIP_SET*             set                 /**< global SCIP settings */
8630 	   )
8631 	{
8632 	   int i;
8633 	   SCIP_Real ub;
8634 	   SCIP_Real bnd;
8635 	   SCIP_VAR* aggrvar;
8636 	   SCIP_Bool posinf;
8637 	   SCIP_Bool neginf;
8638 	
8639 	   assert(var != NULL);
8640 	   assert(set != NULL);
8641 	   assert(var->scip == set->scip);
8642 	   assert((SCIP_VARSTATUS) var->varstatus == SCIP_VARSTATUS_MULTAGGR);
8643 	
8644 	   posinf = FALSE;
8645 	   neginf = FALSE;
8646 	   ub = var->data.multaggr.constant;
8647 	   for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8648 	   {
8649 	      aggrvar = var->data.multaggr.vars[i];
8650 	      if( var->data.multaggr.scalars[i] > 0.0 )
8651 	      {
8652 	         bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8653 	
8654 	         if( SCIPsetIsInfinity(set, bnd) )
8655 	            posinf = TRUE;
8656 	         else if( SCIPsetIsInfinity(set, -bnd) )
8657 	            neginf = TRUE;
8658 	         else
8659 	            ub += var->data.multaggr.scalars[i] * bnd;
8660 	      }
8661 	      else
8662 	      {
8663 	         bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8664 	
8665 	         if( SCIPsetIsInfinity(set, -bnd) )
8666 	            posinf = TRUE;
8667 	         else if( SCIPsetIsInfinity(set, bnd) )
8668 	            neginf = TRUE;
8669 	         else
8670 	            ub += var->data.multaggr.scalars[i] * bnd;
8671 	      }
8672 	
8673 	      /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8674 	       * variable
8675 	       */
8676 	      if( posinf )
8677 	         return SCIPvarGetUbGlobal(var);
8678 	   }
8679 	
8680 	   /* if negative infinity flag was set to true return -infinity */
8681 	   if( neginf )
8682 	      return -SCIPsetInfinity(set);
8683 	
8684 	   return (MIN(ub, SCIPvarGetUbGlobal(var))); /*lint !e666*/
8685 	}
8686 	
8687 	/** adds a hole to the original domain of the variable */
8688 	SCIP_RETCODE SCIPvarAddHoleOriginal(
8689 	   SCIP_VAR*             var,                /**< problem variable */
8690 	   BMS_BLKMEM*           blkmem,             /**< block memory */
8691 	   SCIP_SET*             set,                /**< global SCIP settings */
8692 	   SCIP_Real             left,               /**< left bound of open interval in new hole */
8693 	   SCIP_Real             right               /**< right bound of open interval in new hole */
8694 	   )
8695 	{
8696 	   SCIP_Bool added;
8697 	
8698 	   assert(var != NULL);
8699 	   assert(!SCIPvarIsTransformed(var));
8700 	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL || SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
8701 	   assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8702 	   assert(set != NULL);
8703 	   assert(var->scip == set->scip);
8704 	   assert(set->stage == SCIP_STAGE_PROBLEM);
8705 	
8706 	   SCIPsetDebugMsg(set, "adding original hole (%g,%g) to <%s>\n", left, right, var->name);
8707 	
8708 	   if( SCIPsetIsEQ(set, left, right) )
8709 	      return SCIP_OKAY;
8710 	
8711 	   /* the interval should not be empty */
8712 	   assert(SCIPsetIsLT(set, left, right));
8713 	
8714 	   /* the the interval bound should already be adjusted */
8715 	   assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8716 	   assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8717 	
8718 	   /* the the interval should lay between the lower and upper bound */
8719 	   assert(SCIPsetIsGE(set, left, SCIPvarGetLbOriginal(var)));
8720 	   assert(SCIPsetIsLE(set, right, SCIPvarGetUbOriginal(var)));
8721 	
8722 	   /* add domain hole */
8723 	   SCIP_CALL( domAddHole(&var->data.original.origdom, blkmem, set, left, right, &added) );
8724 	
8725 	   /* merges overlapping holes into single holes, moves bounds respectively if hole was added */
8726 	   if( added )
8727 	   {
8728 	      domMerge(&var->data.original.origdom, blkmem, set, NULL, NULL);
8729 	   }
8730 	
8731 	   /**@todo add hole in parent and child variables (just like with bound changes);
8732 	    *       warning! original vars' holes are in original blkmem, transformed vars' holes in transformed blkmem
8733 	    */
8734 	
8735 	   return SCIP_OKAY;
8736 	}
8737 	
8738 	/** performs the current add of domain, changes all parents accordingly */
8739 	static
8740 	SCIP_RETCODE varProcessAddHoleGlobal(
8741 	   SCIP_VAR*             var,                /**< problem variable */
8742 	   BMS_BLKMEM*           blkmem,             /**< block memory */
8743 	   SCIP_SET*             set,                /**< global SCIP settings */
8744 	   SCIP_STAT*            stat,               /**< problem statistics */
8745 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
8746 	   SCIP_Real             left,               /**< left bound of open interval in new hole */
8747 	   SCIP_Real             right,              /**< right bound of open interval in new hole */
8748 	   SCIP_Bool*            added               /**< pointer to store whether the hole was added */
8749 	   )
8750 	{
8751 	   SCIP_VAR* parentvar;
8752 	   SCIP_Real newlb;
8753 	   SCIP_Real newub;
8754 	   int i;
8755 	
8756 	   assert(var != NULL);
8757 	   assert(added != NULL);
8758 	   assert(blkmem != NULL);
8759 	
8760 	   /* the interval should not be empty */
8761 	   assert(SCIPsetIsLT(set, left, right));
8762 	
8763 	   /* the interval bound should already be adjusted */
8764 	   assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8765 	   assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8766 	
8767 	   /* the interval should lay between the lower and upper bound */
8768 	   assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8769 	   assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8770 	
8771 	   /* @todo add debugging mechanism for holes when using a debugging solution */
8772 	
8773 	   /* add hole to hole list */
8774 	   SCIP_CALL( domAddHole(&var->glbdom, blkmem, set, left, right, added) );
8775 	
8776 	   /* check if the hole is redundant */
8777 	   if( !(*added) )
8778 	      return SCIP_OKAY;
8779 	
8780 	   /* current bounds */
8781 	   newlb = var->glbdom.lb;
8782 	   newub = var->glbdom.ub;
8783 	
8784 	   /* merge domain holes */
8785 	   domMerge(&var->glbdom, blkmem, set, &newlb, &newub);
8786 	
8787 	   /* the bound should not be changed */
8788 	   assert(SCIPsetIsEQ(set, newlb, var->glbdom.lb));
8789 	   assert(SCIPsetIsEQ(set, newub, var->glbdom.ub));
8790 	
8791 	   /* issue bound change event */
8792 	   assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8793 	   if( var->eventfilter != NULL )
8794 	   {
8795 	      SCIP_CALL( varEventGholeAdded(var, blkmem, set, eventqueue, left, right) );
8796 	   }
8797 	
8798 	   /* process parent variables */
8799 	   for( i = 0; i < var->nparentvars; ++i )
8800 	   {
8801 	      SCIP_Real parentnewleft;
8802 	      SCIP_Real parentnewright;
8803 	      SCIP_Bool localadded;
8804 	
8805 	      parentvar = var->parentvars[i];
8806 	      assert(parentvar != NULL);
8807 	
8808 	      switch( SCIPvarGetStatus(parentvar) )
8809 	      {
8810 	      case SCIP_VARSTATUS_ORIGINAL:
8811 	         parentnewleft = left;
8812 	         parentnewright = right;
8813 	         break;
8814 	
8815 	      case SCIP_VARSTATUS_COLUMN:
8816 	      case SCIP_VARSTATUS_LOOSE:
8817 	      case SCIP_VARSTATUS_FIXED:
8818 	      case SCIP_VARSTATUS_MULTAGGR:
8819 	         SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8820 	         return SCIP_INVALIDDATA;
8821 	
8822 	      case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
8823 	         assert(parentvar->data.aggregate.var == var);
8824 	
8825 	         if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8826 	         {
8827 	            /* a > 0 -> change upper bound of x */
8828 	            parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8829 	            parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8830 	         }
8831 	         else
8832 	         {
8833 	            /* a < 0 -> change lower bound of x */
8834 	            assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8835 	
8836 	            parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8837 	            parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8838 	         }
8839 	         break;
8840 	
8841 	      case SCIP_VARSTATUS_NEGATED: /* x = offset - x'  ->  x' = offset - x */
8842 	         assert(parentvar->negatedvar != NULL);
8843 	         assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8844 	         assert(parentvar->negatedvar->negatedvar == parentvar);
8845 	
8846 	         parentnewright = -left + parentvar->data.negate.constant;
8847 	         parentnewleft = -right + parentvar->data.negate.constant;
8848 	         break;
8849 	
8850 	      default:
8851 	         SCIPerrorMessage("unknown variable status\n");
8852 	         return SCIP_INVALIDDATA;
8853 	      }
8854 	
8855 	      SCIPsetDebugMsg(set, "add global hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8856 	
8857 	      /* perform hole added for parent variable */
8858 	      assert(blkmem != NULL);
8859 	      assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8860 	      SCIP_CALL( varProcessAddHoleGlobal(parentvar, blkmem, set, stat, eventqueue, 
8861 	            parentnewleft, parentnewright, &localadded) );
8862 	      assert(localadded);
8863 	   }
8864 	
8865 	   return SCIP_OKAY;
8866 	}
8867 	
8868 	/** adds a hole to the variable's global and local domain */
8869 	SCIP_RETCODE SCIPvarAddHoleGlobal(
8870 	   SCIP_VAR*             var,                /**< problem variable */
8871 	   BMS_BLKMEM*           blkmem,             /**< block memory */
8872 	   SCIP_SET*             set,                /**< global SCIP settings */
8873 	   SCIP_STAT*            stat,               /**< problem statistics */
8874 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
8875 	   SCIP_Real             left,               /**< left bound of open interval in new hole */
8876 	   SCIP_Real             right,              /**< right bound of open interval in new hole */
8877 	   SCIP_Bool*            added               /**< pointer to store whether the hole was added */
8878 	   )
8879 	{
8880 	   SCIP_Real childnewleft;
8881 	   SCIP_Real childnewright;
8882 	
8883 	   assert(var != NULL);
8884 	   assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8885 	   assert(blkmem != NULL);
8886 	   assert(added != NULL);
8887 	
8888 	   SCIPsetDebugMsg(set, "adding global hole (%g,%g) to <%s>\n", left, right, var->name);
8889 	
8890 	   /* the interval should not be empty */
8891 	   assert(SCIPsetIsLT(set, left, right));
8892 	
8893 	   /* the the interval bound should already be adjusted */
8894 	   assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8895 	   assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8896 	
8897 	   /* the the interval should lay between the lower and upper bound */
8898 	   assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8899 	   assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8900 	
8901 	   /* change bounds of attached variables */
8902 	   switch( SCIPvarGetStatus(var) )
8903 	   {
8904 	   case SCIP_VARSTATUS_ORIGINAL:
8905 	      if( var->data.original.transvar != NULL )
8906 	      {
8907 	         SCIP_CALL( SCIPvarAddHoleGlobal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8908 	               left, right, added) );
8909 	      }
8910 	      else
8911 	      {
8912 	         assert(set->stage == SCIP_STAGE_PROBLEM);
8913 	
8914 	         SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8915 	         if( *added )
8916 	         {
8917 	            SCIP_Bool localadded;
8918 	
8919 	            SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8920 	         }
8921 	      }
8922 	      break;
8923 	
8924 	   case SCIP_VARSTATUS_COLUMN:
8925 	   case SCIP_VARSTATUS_LOOSE:
8926 	      SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8927 	      if( *added )
8928 	      {
8929 	         SCIP_Bool localadded;
8930 	
8931 	         SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8932 	      }
8933 	      break;
8934 	
8935 	   case SCIP_VARSTATUS_FIXED:
8936 	      SCIPerrorMessage("cannot add hole of a fixed variable\n");
8937 	      return SCIP_INVALIDDATA;
8938 	
8939 	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
8940 	      assert(var->data.aggregate.var != NULL);
8941 	
8942 	      if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8943 	      {
8944 	         /* a > 0 -> change lower bound of y */
8945 	         childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8946 	         childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8947 	      }
8948 	      else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8949 	      {
8950 	         childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8951 	         childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8952 	      }
8953 	      else
8954 	      { 
8955 	         SCIPerrorMessage("scalar is zero in aggregation\n");
8956 	         return SCIP_INVALIDDATA;
8957 	      }
8958 	      SCIP_CALL( SCIPvarAddHoleGlobal(var->data.aggregate.var, blkmem, set, stat, eventqueue, 
8959 	            childnewleft, childnewright, added) );
8960 	      break;
8961 	
8962 	   case SCIP_VARSTATUS_MULTAGGR:
8963 	      SCIPerrorMessage("cannot add a hole of a multi-aggregated variable.\n");
8964 	      return SCIP_INVALIDDATA;
8965 	
8966 	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
8967 	      assert(var->negatedvar != NULL);
8968 	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
8969 	      assert(var->negatedvar->negatedvar == var);
8970 	
8971 	      childnewright = -left + var->data.negate.constant;
8972 	      childnewleft = -right + var->data.negate.constant;
8973 	
8974 	      SCIP_CALL( SCIPvarAddHoleGlobal(var->negatedvar, blkmem, set, stat, eventqueue, 
8975 	            childnewleft, childnewright, added) );
8976 	      break;
8977 	
8978 	   default:
8979 	      SCIPerrorMessage("unknown variable status\n");
8980 	      return SCIP_INVALIDDATA;
8981 	   }
8982 	
8983 	   return SCIP_OKAY;
8984 	}
8985 	
8986 	/** performs the current add of domain, changes all parents accordingly */
8987 	static
8988 	SCIP_RETCODE varProcessAddHoleLocal(
8989 	   SCIP_VAR*             var,                /**< problem variable */
8990 	   BMS_BLKMEM*           blkmem,             /**< block memory */
8991 	   SCIP_SET*             set,                /**< global SCIP settings */
8992 	   SCIP_STAT*            stat,               /**< problem statistics */
8993 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
8994 	   SCIP_Real             left,               /**< left bound of open interval in new hole */
8995 	   SCIP_Real             right,              /**< right bound of open interval in new hole */
8996 	   SCIP_Bool*            added               /**< pointer to store whether the hole was added, or NULL */
8997 	   )
8998 	{
8999 	   SCIP_VAR* parentvar;
9000 	   SCIP_Real newlb;
9001 	   SCIP_Real newub;
9002 	   int i;
9003 	
9004 	   assert(var != NULL);
9005 	   assert(added != NULL);
9006 	   assert(blkmem != NULL);
9007 	
9008 	   /* the interval should not be empty */
9009 	   assert(SCIPsetIsLT(set, left, right));
9010 	
9011 	   /* the the interval bound should already be adjusted */
9012 	   assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
9013 	   assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
9014 	
9015 	   /* the the interval should lay between the lower and upper bound */
9016 	   assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
9017 	   assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
9018 	
9019 	   /* add hole to hole list */
9020 	   SCIP_CALL( domAddHole(&var->locdom, blkmem, set, left, right, added) );
9021 	
9022 	   /* check if the hole is redundant */
9023 	   if( !(*added) )
9024 	      return SCIP_OKAY;
9025 	
9026 	   /* current bounds */
9027 	   newlb = var->locdom.lb;
9028 	   newub = var->locdom.ub;
9029 	
9030 	   /* merge domain holes */
9031 	   domMerge(&var->locdom, blkmem, set, &newlb, &newub);
9032 	
9033 	   /* the bound should not be changed */
9034 	   assert(SCIPsetIsEQ(set, newlb, var->locdom.lb));
9035 	   assert(SCIPsetIsEQ(set, newub, var->locdom.ub));
9036 	
9037 	#if 0
9038 	   /* issue bound change event */
9039 	   assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
9040 	   if( var->eventfilter != NULL )
9041 	   {
9042 	      SCIP_CALL( varEventLholeAdded(var, blkmem, set, lp, branchcand, eventqueue, left, right) );
9043 	   }
9044 	#endif
9045 	
9046 	   /* process parent variables */
9047 	   for( i = 0; i < var->nparentvars; ++i )
9048 	   {
9049 	      SCIP_Real parentnewleft;
9050 	      SCIP_Real parentnewright;
9051 	      SCIP_Bool localadded;
9052 	
9053 	      parentvar = var->parentvars[i];
9054 	      assert(parentvar != NULL);
9055 	
9056 	      switch( SCIPvarGetStatus(parentvar) )
9057 	      {
9058 	      case SCIP_VARSTATUS_ORIGINAL:
9059 	         parentnewleft = left;
9060 	         parentnewright = right;
9061 	         break;
9062 	
9063 	      case SCIP_VARSTATUS_COLUMN:
9064 	      case SCIP_VARSTATUS_LOOSE:
9065 	      case SCIP_VARSTATUS_FIXED:
9066 	      case SCIP_VARSTATUS_MULTAGGR:
9067 	         SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
9068 	         return SCIP_INVALIDDATA;
9069 	
9070 	      case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
9071 	         assert(parentvar->data.aggregate.var == var);
9072 	
9073 	         if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
9074 	         {
9075 	            /* a > 0 -> change upper bound of x */
9076 	            parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
9077 	            parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
9078 	         }
9079 	         else
9080 	         {
9081 	            /* a < 0 -> change lower bound of x */
9082 	            assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
9083 	
9084 	            parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
9085 	            parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
9086 	         }
9087 	         break;
9088 	
9089 	      case SCIP_VARSTATUS_NEGATED: /* x = offset - x'  ->  x' = offset - x */
9090 	         assert(parentvar->negatedvar != NULL);
9091 	         assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
9092 	         assert(parentvar->negatedvar->negatedvar == parentvar);
9093 	
9094 	         parentnewright = -left + parentvar->data.negate.constant;
9095 	         parentnewleft = -right + parentvar->data.negate.constant;
9096 	         break;
9097 	
9098 	      default:
9099 	         SCIPerrorMessage("unknown variable status\n");
9100 	         return SCIP_INVALIDDATA;
9101 	      }
9102 	
9103 	      SCIPsetDebugMsg(set, "add local hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
9104 	
9105 	      /* perform hole added for parent variable */
9106 	      assert(blkmem != NULL);
9107 	      assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
9108 	      SCIP_CALL( varProcessAddHoleLocal(parentvar, blkmem, set, stat, eventqueue, 
9109 	            parentnewleft, parentnewright, &localadded) );
9110 	      assert(localadded);
9111 	   }
9112 	
9113 	   return SCIP_OKAY;
9114 	}
9115 	
9116 	/** adds a hole to the variable's current local domain */
9117 	SCIP_RETCODE SCIPvarAddHoleLocal(
9118 	   SCIP_VAR*             var,                /**< problem variable */
9119 	   BMS_BLKMEM*           blkmem,             /**< block memory */
9120 	   SCIP_SET*             set,                /**< global SCIP settings */
9121 	   SCIP_STAT*            stat,               /**< problem statistics */
9122 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
9123 	   SCIP_Real             left,               /**< left bound of open interval in new hole */
9124 	   SCIP_Real             right,              /**< right bound of open interval in new hole */
9125 	   SCIP_Bool*            added               /**< pointer to store whether the hole was added */
9126 	   )
9127 	{
9128 	   SCIP_Real childnewleft;
9129 	   SCIP_Real childnewright;
9130 	
9131 	   assert(var != NULL);
9132 	
9133 	   SCIPsetDebugMsg(set, "adding local hole (%g,%g) to <%s>\n", left, right, var->name);
9134 	
9135 	   assert(set != NULL);
9136 	   assert(var->scip == set->scip);
9137 	   assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
9138 	   assert(blkmem != NULL);
9139 	   assert(added != NULL);
9140 	
9141 	   /* the interval should not be empty */
9142 	   assert(SCIPsetIsLT(set, left, right));
9143 	
9144 	   /* the the interval bound should already be adjusted */
9145 	   assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
9146 	   assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
9147 	
9148 	   /* the the interval should lay between the lower and upper bound */
9149 	   assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
9150 	   assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
9151 	
9152 	   /* change bounds of attached variables */
9153 	   switch( SCIPvarGetStatus(var) )
9154 	   {
9155 	   case SCIP_VARSTATUS_ORIGINAL:
9156 	      if( var->data.original.transvar != NULL )
9157 	      {
9158 	         SCIP_CALL( SCIPvarAddHoleLocal(var->data.original.transvar, blkmem, set, stat, eventqueue, 
9159 	               left, right, added) );
9160 	      }
9161 	      else
9162 	      {
9163 	         assert(set->stage == SCIP_STAGE_PROBLEM);
9164 	         SCIPstatIncrement(stat, set, domchgcount);
9165 	         SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
9166 	      }
9167 	      break;
9168 	
9169 	   case SCIP_VARSTATUS_COLUMN:
9170 	   case SCIP_VARSTATUS_LOOSE:
9171 	      SCIPstatIncrement(stat, set, domchgcount);
9172 	      SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
9173 	      break;
9174 	
9175 	   case SCIP_VARSTATUS_FIXED:
9176 	      SCIPerrorMessage("cannot add domain hole to a fixed variable\n");
9177 	      return SCIP_INVALIDDATA;
9178 	
9179 	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
9180 	      assert(var->data.aggregate.var != NULL);
9181 	
9182 	      if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
9183 	      {
9184 	         /* a > 0 -> change lower bound of y */
9185 	         childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
9186 	         childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
9187 	      }
9188 	      else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
9189 	      {
9190 	         childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
9191 	         childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
9192 	      }
9193 	      else
9194 	      {         
9195 	         SCIPerrorMessage("scalar is zero in aggregation\n");
9196 	         return SCIP_INVALIDDATA;
9197 	      }
9198 	      SCIP_CALL( SCIPvarAddHoleLocal(var->data.aggregate.var, blkmem, set, stat, eventqueue, 
9199 	            childnewleft, childnewright, added) );
9200 	      break;
9201 	
9202 	   case SCIP_VARSTATUS_MULTAGGR:
9203 	      SCIPerrorMessage("cannot add domain hole to a multi-aggregated variable.\n");
9204 	      return SCIP_INVALIDDATA;
9205 	
9206 	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
9207 	      assert(var->negatedvar != NULL);
9208 	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
9209 	      assert(var->negatedvar->negatedvar == var);
9210 	
9211 	      childnewright = -left + var->data.negate.constant;
9212 	      childnewleft = -right + var->data.negate.constant;
9213 	
9214 	      SCIP_CALL( SCIPvarAddHoleLocal(var->negatedvar, blkmem, set, stat, eventqueue, childnewleft, childnewright, added) );
9215 	      break;
9216 	
9217 	   default:
9218 	      SCIPerrorMessage("unknown variable status\n");
9219 	      return SCIP_INVALIDDATA;
9220 	   }
9221 	
9222 	   return SCIP_OKAY;
9223 	}
9224 	
9225 	/** resets the global and local bounds of original variable to their original values */
9226 	SCIP_RETCODE SCIPvarResetBounds(
9227 	   SCIP_VAR*             var,                /**< problem variable */
9228 	   BMS_BLKMEM*           blkmem,             /**< block memory */
9229 	   SCIP_SET*             set,                /**< global SCIP settings */
9230 	   SCIP_STAT*            stat                /**< problem statistics */
9231 	   )
9232 	{
9233 	   assert(var != NULL);
9234 	   assert(set != NULL);
9235 	   assert(var->scip == set->scip);
9236 	   assert(SCIPvarIsOriginal(var));
9237 	   /* resetting of bounds on original variables which have a transformed counterpart easily fails if, e.g.,
9238 	    * the transformed variable has been fixed */ 
9239 	   assert(SCIPvarGetTransVar(var) == NULL);
9240 	
9241 	   /* copy the original bounds back to the global and local bounds */
9242 	   SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.lb) );
9243 	   SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.ub) );
9244 	   SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.lb) );
9245 	   SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.ub) );
9246 	
9247 	   /* free the global and local holelists and duplicate the original ones */
9248 	   /**@todo this has also to be called recursively with methods similar to SCIPvarChgLbGlobal() */
9249 	   holelistFree(&var->glbdom.holelist, blkmem);
9250 	   holelistFree(&var->locdom.holelist, blkmem);
9251 	   SCIP_CALL( holelistDuplicate(&var->glbdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
9252 	   SCIP_CALL( holelistDuplicate(&var->locdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
9253 	
9254 	   return SCIP_OKAY;
9255 	}
9256 	
9257 	/** issues a IMPLADDED event on the given variable */
9258 	static
9259 	SCIP_RETCODE varEventImplAdded(
9260 	   SCIP_VAR*             var,                /**< problem variable to change */
9261 	   BMS_BLKMEM*           blkmem,             /**< block memory */
9262 	   SCIP_SET*             set,                /**< global SCIP settings */
9263 	   SCIP_EVENTQUEUE*      eventqueue          /**< event queue */
9264 	   )
9265 	{
9266 	   SCIP_EVENT* event;
9267 	
9268 	   assert(var != NULL);
9269 	
9270 	   /* issue IMPLADDED event on variable */
9271 	   SCIP_CALL( SCIPeventCreateImplAdded(&event, blkmem, var) );
9272 	   SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
9273 	
9274 	   return SCIP_OKAY;
9275 	}
9276 	
9277 	/** actually performs the addition of a variable bound to the variable's vbound arrays */
9278 	static
9279 	SCIP_RETCODE varAddVbound(
9280 	   SCIP_VAR*             var,                /**< problem variable x in x <= b*z + d  or  x >= b*z + d */
9281 	   BMS_BLKMEM*           blkmem,             /**< block memory */
9282 	   SCIP_SET*             set,                /**< global SCIP settings */
9283 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
9284 	   SCIP_BOUNDTYPE        vbtype,             /**< type of variable bound (LOWER or UPPER) */
9285 	   SCIP_VAR*             vbvar,              /**< variable z    in x <= b*z + d  or  x >= b*z + d */
9286 	   SCIP_Real             vbcoef,             /**< coefficient b in x <= b*z + d  or  x >= b*z + d */
9287 	   SCIP_Real             vbconstant          /**< constant d    in x <= b*z + d  or  x >= b*z + d */
9288 	   )
9289 	{
9290 	   SCIP_Bool added;
9291 	
9292 	   /* It can happen that the variable "var" and the variable "vbvar" are the same variable. For example if a variable
9293 	    * gets aggregated, the variable bounds (vbound) of that variable are copied to the other variable. A variable bound
9294 	    * variable of the aggregated variable might be the same as the one its gets aggregated too.
9295 	    * 
9296 	    * If the variable "var" and the variable "vbvar" are the same, the variable bound which should be added here has to
9297 	    * be redundant. This is the case since an infeasibility should have be detected in the previous methods. As well as
9298 	    * the bounds of the variable which should be also already be tightened in the previous methods. Therefore, the
9299 	    * variable bound can be ignored.
9300 	    *
9301 	    * From the way the the variable bound system is implemented (detecting infeasibility, tighten bounds), the
9302 	    * equivalence of the variables should be checked here.
9303 	    */
9304 	   if( var == vbvar )
9305 	   {
9306 	      /* in this case the variable bound has to be redundant, this means for possible assignments to this variable; this
9307 	       * can be checked via the global bounds of the variable */
9308 	#ifndef NDEBUG
9309 	      SCIP_Real lb;
9310 	      SCIP_Real ub;
9311 	
9312 	      lb = SCIPvarGetLbGlobal(var);
9313 	      ub = SCIPvarGetUbGlobal(var);
9314 	
9315 	      if(vbtype == SCIP_BOUNDTYPE_LOWER)
9316 	      {
9317 	         if( vbcoef > 0.0 )
9318 	         {
9319 	            assert(SCIPsetIsGE(set, lb,  lb * vbcoef + vbconstant) );
9320 	            assert(SCIPsetIsGE(set, ub,  ub * vbcoef + vbconstant) );
9321 	         }
9322 	         else
9323 	         {
9324 	            assert(SCIPsetIsGE(set, lb,  ub * vbcoef + vbconstant) );
9325 	            assert(SCIPsetIsGE(set, ub,  lb * vbcoef + vbconstant) );
9326 	         }
9327 	      }
9328 	      else
9329 	      {
9330 	         assert(vbtype == SCIP_BOUNDTYPE_UPPER);
9331 	         if( vbcoef > 0.0 )
9332 	         {
9333 	            assert(SCIPsetIsLE(set, lb,  lb * vbcoef + vbconstant) );
9334 	            assert(SCIPsetIsLE(set, ub,  ub * vbcoef + vbconstant) );
9335 	         }
9336 	         else
9337 	         {
9338 	            assert(SCIPsetIsLE(set, lb,  ub * vbcoef + vbconstant) );
9339 	            assert(SCIPsetIsLE(set, ub,  lb * vbcoef + vbconstant) );
9340 	         }
9341 	      }
9342 	#endif
9343 	      SCIPsetDebugMsg(set, "redundant variable bound: <%s> %s %g<%s> %+g\n",
9344 	         SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
9345 	
9346 	      return SCIP_OKAY;
9347 	   }
9348 	
9349 	   SCIPsetDebugMsg(set, "adding variable bound: <%s> %s %g<%s> %+g\n",
9350 	      SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
9351 	
9352 	   /* check variable bound on debugging solution */
9353 	   SCIP_CALL( SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant) ); /*lint !e506 !e774*/
9354 	
9355 	   /* perform the addition */
9356 	   if( vbtype == SCIP_BOUNDTYPE_LOWER )
9357 	   {
9358 	      SCIP_CALL( SCIPvboundsAdd(&var->vlbs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9359 	   }
9360 	   else
9361 	   {
9362 	      SCIP_CALL( SCIPvboundsAdd(&var->vubs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9363 	   }
9364 	   var->closestvblpcount = -1;
9365 	
9366 	   if( added )
9367 	   {
9368 	      /* issue IMPLADDED event */
9369 	      SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9370 	   }
9371 	
9372 	   return SCIP_OKAY;
9373 	}
9374 	
9375 	/** checks whether the given implication is redundant or infeasible w.r.t. the implied variables global bounds */
9376 	static
9377 	void checkImplic(
9378 	   SCIP_SET*             set,                /**< global SCIP settings */
9379 	   SCIP_VAR*             implvar,            /**< variable y in implication y <= b or y >= b */
9380 	   SCIP_BOUNDTYPE        impltype,           /**< type       of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9381 	   SCIP_Real             implbound,          /**< bound b    in implication y <= b or y >= b */
9382 	   SCIP_Bool*            redundant,          /**< pointer to store whether the implication is redundant */
9383 	   SCIP_Bool*            infeasible          /**< pointer to store whether the implication is infeasible */
9384 	   )
9385 	{
9386 	   SCIP_Real impllb;
9387 	   SCIP_Real implub;
9388 	
9389 	   assert(redundant != NULL);
9390 	   assert(infeasible != NULL);
9391 	
9392 	   impllb = SCIPvarGetLbGlobal(implvar);
9393 	   implub = SCIPvarGetUbGlobal(implvar);
9394 	   if( impltype == SCIP_BOUNDTYPE_LOWER )
9395 	   {
9396 	      *infeasible = SCIPsetIsFeasGT(set, implbound, implub);
9397 	      *redundant = SCIPsetIsFeasLE(set, implbound, impllb);
9398 	   }
9399 	   else
9400 	   {
9401 	      *infeasible = SCIPsetIsFeasLT(set, implbound, impllb);
9402 	      *redundant = SCIPsetIsFeasGE(set, implbound, implub);
9403 	   }
9404 	}
9405 	
9406 	/** applies the given implication, if it is not redundant */
9407 	static
9408 	SCIP_RETCODE applyImplic(
9409 	   BMS_BLKMEM*           blkmem,             /**< block memory */
9410 	   SCIP_SET*             set,                /**< global SCIP settings */
9411 	   SCIP_STAT*            stat,               /**< problem statistics */
9412 	   SCIP_PROB*            transprob,          /**< transformed problem */
9413 	   SCIP_PROB*            origprob,           /**< original problem */
9414 	   SCIP_TREE*            tree,               /**< branch and bound tree if in solving stage */
9415 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
9416 	   SCIP_LP*              lp,                 /**< current LP data */
9417 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
9418 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
9419 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
9420 	   SCIP_VAR*             implvar,            /**< variable y in implication y <= b or y >= b */
9421 	   SCIP_BOUNDTYPE        impltype,           /**< type       of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9422 	   SCIP_Real             implbound,          /**< bound b    in implication y <= b or y >= b */
9423 	   SCIP_Bool*            infeasible,         /**< pointer to store whether an infeasibility was detected */
9424 	   int*                  nbdchgs             /**< pointer to count the number of performed bound changes, or NULL */
9425 	   )
9426 	{
9427 	   SCIP_Real implub;
9428 	   SCIP_Real impllb;
9429 	
9430 	   assert(infeasible != NULL);
9431 	
9432 	   *infeasible = FALSE;
9433 	
9434 	   implub = SCIPvarGetUbGlobal(implvar);
9435 	   impllb = SCIPvarGetLbGlobal(implvar);
9436 	   if( impltype == SCIP_BOUNDTYPE_LOWER )
9437 	   {
9438 	      if( SCIPsetIsFeasGT(set, implbound, implub) )
9439 	      {
9440 	         /* the implication produces a conflict: the problem is infeasible */
9441 	         *infeasible = TRUE;
9442 	      }
9443 	      else if( SCIPsetIsFeasGT(set, implbound, impllb) )
9444 	      {
9445 	         /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9446 	          * with the local bound, in this case we need to store the bound change as pending bound change
9447 	          */
9448 	         if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9449 	         {
9450 	            assert(tree != NULL);
9451 	            assert(transprob != NULL);
9452 	            assert(SCIPprobIsTransformed(transprob));
9453 	
9454 	            SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9455 	                  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
9456 	         }
9457 	         else
9458 	         {
9459 	            SCIP_CALL( SCIPvarChgLbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9460 	         }
9461 	
9462 	         if( nbdchgs != NULL )
9463 	            (*nbdchgs)++;
9464 	      }
9465 	   }
9466 	   else
9467 	   {
9468 	      if( SCIPsetIsFeasLT(set, implbound, impllb) )
9469 	      {
9470 	         /* the implication produces a conflict: the problem is infeasible */
9471 	         *infeasible = TRUE;
9472 	      }
9473 	      else if( SCIPsetIsFeasLT(set, implbound, implub) )
9474 	      {
9475 	         /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9476 	          * with the local bound, in this case we need to store the bound change as pending bound change
9477 	          */
9478 	         if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9479 	         {
9480 	            assert(tree != NULL);
9481 	            assert(transprob != NULL);
9482 	            assert(SCIPprobIsTransformed(transprob));
9483 	
9484 	            SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9485 	                  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
9486 	         }
9487 	         else
9488 	         {
9489 	            SCIP_CALL( SCIPvarChgUbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9490 	         }
9491 	
9492 	         if( nbdchgs != NULL )
9493 	            (*nbdchgs)++;
9494 	      }
9495 	   }
9496 	
9497 	   return SCIP_OKAY;
9498 	}
9499 	
9500 	/** actually performs the addition of an implication to the variable's implication arrays,
9501 	 *  and adds the corresponding implication or variable bound to the implied variable;
9502 	 *  if the implication is conflicting, the variable is fixed to the opposite value;
9503 	 *  if the variable is already fixed to the given value, the implication is performed immediately;
9504 	 *  if the implication is redundant with respect to the variables' global bounds, it is ignored
9505 	 */
9506 	static
9507 	SCIP_RETCODE varAddImplic(
9508 	   SCIP_VAR*             var,                /**< problem variable */
9509 	   BMS_BLKMEM*           blkmem,             /**< block memory */
9510 	   SCIP_SET*             set,                /**< global SCIP settings */
9511 	   SCIP_STAT*            stat,               /**< problem statistics */
9512 	   SCIP_PROB*            transprob,          /**< transformed problem */
9513 	   SCIP_PROB*            origprob,           /**< original problem */
9514 	   SCIP_TREE*            tree,               /**< branch and bound tree if in solving stage */
9515 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
9516 	   SCIP_LP*              lp,                 /**< current LP data */
9517 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
9518 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
9519 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
9520 	   SCIP_Bool             varfixing,          /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9521 	   SCIP_VAR*             implvar,            /**< variable y in implication y <= b or y >= b */
9522 	   SCIP_BOUNDTYPE        impltype,           /**< type       of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9523 	   SCIP_Real             implbound,          /**< bound b    in implication y <= b or y >= b */
9524 	   SCIP_Bool             isshortcut,         /**< is the implication a shortcut, i.e., added as part of the transitive closure of another implication? */
9525 	   SCIP_Bool*            infeasible,         /**< pointer to store whether an infeasibility was detected */
9526 	   int*                  nbdchgs,            /**< pointer to count the number of performed bound changes, or NULL */
9527 	   SCIP_Bool*            added               /**< pointer to store whether an implication was added */
9528 	   )
9529 	{
9530 	   SCIP_Bool redundant;
9531 	   SCIP_Bool conflict;
9532 	
9533 	   assert(var != NULL);
9534 	   assert(SCIPvarIsActive(var));
9535 	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
9536 	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9537 	   assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9538 	   assert(infeasible != NULL);
9539 	   assert(added != NULL);
9540 	
9541 	   /* check implication on debugging solution */
9542 	   SCIP_CALL( SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound) ); /*lint !e506 !e774*/
9543 	
9544 	   *infeasible = FALSE;
9545 	   *added = FALSE;
9546 	
9547 	   /* check, if the implication is redundant or infeasible */
9548 	   checkImplic(set, implvar, impltype, implbound, &redundant, &conflict);
9549 	   assert(!redundant || !conflict);
9550 	   if( redundant )
9551 	      return SCIP_OKAY;
9552 	
9553 	   if( var == implvar )
9554 	   {
9555 	      /* special cases appear were a bound to a variable implies itself to be outside the bounds:
9556 	       * x == varfixing  =>  x < 0 or x > 1
9557 	       */
9558 	      if( SCIPsetIsLT(set, implbound, 0.0) || SCIPsetIsGT(set, implbound, 1.0) )
9559 	         conflict = TRUE;
9560 	      else
9561 	      {
9562 	         /* variable implies itself: x == varfixing  =>  x == (impltype == SCIP_BOUNDTYPE_LOWER) */
9563 	         assert(SCIPsetIsZero(set, implbound) || SCIPsetIsEQ(set, implbound, 1.0));
9564 	         assert(SCIPsetIsZero(set, implbound) == (impltype == SCIP_BOUNDTYPE_UPPER));
9565 	         assert(SCIPsetIsEQ(set, implbound, 1.0) == (impltype == SCIP_BOUNDTYPE_LOWER));
9566 	         conflict = conflict || ((varfixing == TRUE) == (impltype == SCIP_BOUNDTYPE_UPPER));
9567 	         if( !conflict )
9568 	            return SCIP_OKAY;
9569 	      }
9570 	   }
9571 	
9572 	   /* check, if the variable is already fixed */
9573 	   if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
9574 	   {
9575 	      /* if the variable is fixed to the given value, perform the implication; otherwise, ignore the implication */
9576 	      if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
9577 	      {
9578 	         SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
9579 	               cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
9580 	      }
9581 	      return SCIP_OKAY;
9582 	   }
9583 	
9584 	   assert((impltype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, implbound, SCIPvarGetLbGlobal(implvar)))
9585 	      || (impltype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, implbound, SCIPvarGetUbGlobal(implvar))));
9586 	
9587 	   if( !conflict )
9588 	   {
9589 	      assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9590 	
9591 	      if( SCIPvarIsBinary(implvar) )
9592 	      {
9593 	         SCIP_VAR* vars[2];
9594 	         SCIP_Bool vals[2];
9595 	
9596 	         assert(SCIPsetIsFeasEQ(set, implbound, 1.0) || SCIPsetIsFeasZero(set, implbound));
9597 	         assert((impltype == SCIP_BOUNDTYPE_UPPER) == SCIPsetIsFeasZero(set, implbound));
9598 	
9599 	         vars[0] = var;
9600 	         vars[1] = implvar;
9601 	         vals[0] = varfixing;
9602 	         vals[1] = (impltype == SCIP_BOUNDTYPE_UPPER);
9603 	
9604 	         /* add the clique to the clique table */
9605 	         SCIP_CALL( SCIPcliquetableAdd(cliquetable, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
9606 	               eventqueue, vars, vals, 2, FALSE, &conflict, nbdchgs) );
9607 	
9608 	         if( !conflict )
9609 	            return SCIP_OKAY;
9610 	      }
9611 	      else
9612 	      {
9613 	         /* add implication x == 0/1 -> y <= b / y >= b to the implications list of x */
9614 	         SCIPsetDebugMsg(set, "adding implication: <%s> == %u  ==>  <%s> %s %g\n",
9615 	            SCIPvarGetName(var), varfixing,
9616 	            SCIPvarGetName(implvar), impltype == SCIP_BOUNDTYPE_UPPER ? "<=" : ">=", implbound);
9617 	         SCIP_CALL( SCIPimplicsAdd(&var->implics, blkmem, set, stat, varfixing, implvar, impltype, implbound,
9618 	               isshortcut, &conflict, added) );
9619 	      }
9620 	   }
9621 	   assert(!conflict || !(*added));
9622 	
9623 	   /* on conflict, fix the variable to the opposite value */
9624 	   if( conflict )
9625 	   {
9626 	      SCIPsetDebugMsg(set, " -> implication yields a conflict: fix <%s> == %d\n", SCIPvarGetName(var), !varfixing);
9627 	
9628 	      /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9629 	       * with the local bound, in this case we need to store the bound change as pending bound change
9630 	       */
9631 	      if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9632 	      {
9633 	         assert(tree != NULL);
9634 	         assert(transprob != NULL);
9635 	         assert(SCIPprobIsTransformed(transprob));
9636 	
9637 	         if( varfixing )
9638 	         {
9639 	            SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9640 	                  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
9641 	         }
9642 	         else
9643 	         {
9644 	            SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9645 	                  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
9646 	         }
9647 	      }
9648 	      else
9649 	      {
9650 	         if( varfixing )
9651 	         {
9652 	            SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
9653 	         }
9654 	         else
9655 	         {
9656 	            SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
9657 	         }
9658 	      }
9659 	      if( nbdchgs != NULL )
9660 	         (*nbdchgs)++;
9661 	
9662 	      return SCIP_OKAY;
9663 	   }
9664 	   else if( *added )
9665 	   {
9666 	      /* issue IMPLADDED event */
9667 	      SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9668 	   }
9669 	   else
9670 	   {
9671 	      /* the implication was redundant: the inverse is also redundant */
9672 	      return SCIP_OKAY;
9673 	   }
9674 	
9675 	   assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9676 	
9677 	   /* check, whether implied variable is binary */
9678 	   if( !SCIPvarIsBinary(implvar) )
9679 	   {
9680 	      SCIP_Real lb;
9681 	      SCIP_Real ub;
9682 	
9683 	      /* add inverse variable bound to the variable bounds of y with global bounds y \in [lb,ub]:
9684 	       *   x == 0 -> y <= b  <->  y <= (ub - b)*x + b
9685 	       *   x == 1 -> y <= b  <->  y <= (b - ub)*x + ub
9686 	       *   x == 0 -> y >= b  <->  y >= (lb - b)*x + b
9687 	       *   x == 1 -> y >= b  <->  y >= (b - lb)*x + lb
9688 	       * for numerical reasons, ignore variable bounds with large absolute coefficient
9689 	       */
9690 	      lb = SCIPvarGetLbGlobal(implvar);
9691 	      ub = SCIPvarGetUbGlobal(implvar);
9692 	      if( impltype == SCIP_BOUNDTYPE_UPPER )
9693 	      {
9694 	         if( REALABS(implbound - ub) <= MAXABSVBCOEF ) 
9695 	         {
9696 	            SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, var,
9697 	                  varfixing ? implbound - ub : ub - implbound, varfixing ? ub : implbound) );
9698 	         }
9699 	      }
9700 	      else
9701 	      {
9702 	         if( REALABS(implbound - lb) <= MAXABSVBCOEF ) 
9703 	         {
9704 	            SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, var,
9705 	                  varfixing ? implbound - lb : lb - implbound, varfixing ? lb : implbound) );
9706 	         }
9707 	      }
9708 	   }
9709 	
9710 	   return SCIP_OKAY;
9711 	}
9712 	
9713 	/** adds transitive closure for binary implication x = a -> y = b */
9714 	static
9715 	SCIP_RETCODE varAddTransitiveBinaryClosureImplic(
9716 	   SCIP_VAR*             var,                /**< problem variable */
9717 	   BMS_BLKMEM*           blkmem,             /**< block memory */
9718 	   SCIP_SET*             set,                /**< global SCIP settings */
9719 	   SCIP_STAT*            stat,               /**< problem statistics */
9720 	   SCIP_PROB*            transprob,          /**< transformed problem */
9721 	   SCIP_PROB*            origprob,           /**< original problem */
9722 	   SCIP_TREE*            tree,               /**< branch and bound tree if in solving stage */
9723 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
9724 	   SCIP_LP*              lp,                 /**< current LP data */
9725 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
9726 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
9727 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
9728 	   SCIP_Bool             varfixing,          /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9729 	   SCIP_VAR*             implvar,            /**< variable y in implication y <= b or y >= b */
9730 	   SCIP_Bool             implvarfixing,      /**< fixing b in implication */
9731 	   SCIP_Bool*            infeasible,         /**< pointer to store whether an infeasibility was detected */
9732 	   int*                  nbdchgs             /**< pointer to count the number of performed bound changes, or NULL */
9733 	   )
9734 	{
9735 	   SCIP_VAR** implvars;
9736 	   SCIP_BOUNDTYPE* impltypes;
9737 	   SCIP_Real* implbounds;
9738 	   int nimpls;
9739 	   int i;
9740 	
9741 	   *infeasible = FALSE;
9742 	
9743 	   /* binary variable: implications of implvar */
9744 	   nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9745 	   implvars = SCIPimplicsGetVars(implvar->implics, implvarfixing);
9746 	   impltypes = SCIPimplicsGetTypes(implvar->implics, implvarfixing);
9747 	   implbounds = SCIPimplicsGetBounds(implvar->implics, implvarfixing);
9748 	
9749 	   /* if variable has too many implications, the implication graph may become too dense */
9750 	   i = MIN(nimpls, MAXIMPLSCLOSURE) - 1;
9751 	
9752 	   /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9753 	    * implvars[i] is fixed, s.t. the implication y == varfixing -> z <= b / z >= b is deleted; this affects the
9754 	    * array over which we currently iterate; the only thing that can happen, is that elements of the array are
9755 	    * deleted; in this case, the subsequent elements are moved to the front; if we iterate from back to front, the
9756 	    * only thing that can happen is that we add the same implication twice - this does no harm
9757 	    */
9758 	   while ( i >= 0 && !(*infeasible) )
9759 	   {
9760 	      SCIP_Bool added;
9761 	
9762 	      assert(implvars[i] != implvar);
9763 	
9764 	      /* we have x == varfixing -> y == implvarfixing -> z <= b / z >= b:
9765 	       * add implication x == varfixing -> z <= b / z >= b to the implications list of x 
9766 	       */
9767 	      if( SCIPvarIsActive(implvars[i]) )
9768 	      {
9769 	         SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9770 	               eventqueue, varfixing, implvars[i], impltypes[i], implbounds[i], TRUE, infeasible, nbdchgs, &added) );
9771 	         assert(SCIPimplicsGetNImpls(implvar->implics, implvarfixing) <= nimpls);
9772 	         nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9773 	         i = MIN(i, nimpls); /* some elements from the array could have been removed */
9774 	      }
9775 	      --i;
9776 	   }
9777 	
9778 	   return SCIP_OKAY;
9779 	}
9780 	
9781 	/** adds given implication to the variable's implication list, and adds all implications directly implied by this
9782 	 *  implication to the variable's implication list;
9783 	 *  if the implication is conflicting, the variable is fixed to the opposite value;
9784 	 *  if the variable is already fixed to the given value, the implication is performed immediately;
9785 	 *  if the implication is redundant with respect to the variables' global bounds, it is ignored
9786 	 */
9787 	static
9788 	SCIP_RETCODE varAddTransitiveImplic(
9789 	   SCIP_VAR*             var,                /**< problem variable */
9790 	   BMS_BLKMEM*           blkmem,             /**< block memory */
9791 	   SCIP_SET*             set,                /**< global SCIP settings */
9792 	   SCIP_STAT*            stat,               /**< problem statistics */
9793 	   SCIP_PROB*            transprob,          /**< transformed problem */
9794 	   SCIP_PROB*            origprob,           /**< original problem */
9795 	   SCIP_TREE*            tree,               /**< branch and bound tree if in solving stage */
9796 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
9797 	   SCIP_LP*              lp,                 /**< current LP data */
9798 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
9799 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
9800 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
9801 	   SCIP_Bool             varfixing,          /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9802 	   SCIP_VAR*             implvar,            /**< variable y in implication y <= b or y >= b */
9803 	   SCIP_BOUNDTYPE        impltype,           /**< type       of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9804 	   SCIP_Real             implbound,          /**< bound b    in implication y <= b or y >= b */
9805 	   SCIP_Bool             transitive,         /**< should transitive closure of implication also be added? */
9806 	   SCIP_Bool*            infeasible,         /**< pointer to store whether an infeasibility was detected */
9807 	   int*                  nbdchgs             /**< pointer to count the number of performed bound changes, or NULL */
9808 	   )
9809 	{
9810 	   SCIP_Bool added;
9811 	
9812 	   assert(var != NULL);
9813 	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9814 	   assert(SCIPvarIsActive(var));
9815 	   assert(implvar != NULL);
9816 	   assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9817 	   assert(infeasible != NULL);
9818 	
9819 	   /* add implication x == varfixing -> y <= b / y >= b to the implications list of x */
9820 	   SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9821 	         eventqueue, varfixing, implvar, impltype, implbound, FALSE, infeasible, nbdchgs, &added) );
9822 	
9823 	   if( *infeasible || var == implvar || !transitive || !added )
9824 	      return SCIP_OKAY;
9825 	
9826 	   assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9827 	
9828 	   /* add transitive closure */
9829 	   if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
9830 	   {
9831 	      SCIP_Bool implvarfixing;
9832 	
9833 	      implvarfixing = (impltype == SCIP_BOUNDTYPE_LOWER);
9834 	
9835 	      /* binary variable: implications of implvar */
9836 	      SCIP_CALL( varAddTransitiveBinaryClosureImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9837 	            cliquetable, branchcand, eventqueue, varfixing, implvar, implvarfixing, infeasible, nbdchgs) );
9838 	
9839 	      /* inverse implication */
9840 	      if( !(*infeasible) )
9841 	      {
9842 	         SCIP_CALL( varAddTransitiveBinaryClosureImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9843 	               cliquetable, branchcand, eventqueue, !implvarfixing, var, !varfixing, infeasible, nbdchgs) );
9844 	      }
9845 	   }
9846 	   else
9847 	   {
9848 	      /* non-binary variable: variable lower bounds of implvar */
9849 	      if( impltype == SCIP_BOUNDTYPE_UPPER && implvar->vlbs != NULL )
9850 	      {
9851 	         SCIP_VAR** vlbvars;
9852 	         SCIP_Real* vlbcoefs;
9853 	         SCIP_Real* vlbconstants;
9854 	         int nvlbvars;
9855 	         int i;
9856 	
9857 	         nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9858 	         vlbvars = SCIPvboundsGetVars(implvar->vlbs);
9859 	         vlbcoefs = SCIPvboundsGetCoefs(implvar->vlbs);
9860 	         vlbconstants = SCIPvboundsGetConstants(implvar->vlbs);
9861 	
9862 	         /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9863 	          * vlbvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9864 	          * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9865 	          * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9866 	          * is that we add the same implication twice - this does no harm
9867 	          */
9868 	         i = nvlbvars-1;
9869 	         while ( i >= 0 && !(*infeasible) )
9870 	         {
9871 	            assert(vlbvars[i] != implvar);
9872 	            assert(!SCIPsetIsZero(set, vlbcoefs[i]));
9873 	
9874 	            /* we have x == varfixing -> y <= b and y >= c*z + d:
9875 	             *   c > 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9876 	             *   c < 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9877 	             *
9878 	             * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9879 	             *       SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9880 	             *       aggregation variable (the one which will stay active); 
9881 	             *
9882 	             *       W.l.o.g. we consider the variable upper bounds for now. Let "vubvar" be a variable upper bound of
9883 	             *       the aggregated variable "aggvar"; During that copying of that variable upper bound variable
9884 	             *       "vubvar" the variable lower and upper bounds of this variable "vubvar" are also considered; note
9885 	             *       that the "aggvar" can be a variable lower bound variable of the variable "vubvar"; Due to that
9886 	             *       situation it can happen that we reach that code place where "vlbvars[i] == aggvar". In particular
9887 	             *       the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9888 	             *       but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9889 	             *       have to explicitly check that the active variable has not a variable status
9890 	             *       SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9891 	             */
9892 	            if( SCIPvarIsActive(vlbvars[i]) && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_NEGATED )
9893 	            {
9894 	               SCIP_Real vbimplbound;
9895 	
9896 	               vbimplbound = (implbound - vlbconstants[i])/vlbcoefs[i];
9897 	               if( vlbcoefs[i] >= 0.0 )
9898 	               {
9899 	                  vbimplbound = adjustedUb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9900 	                  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9901 	                        branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9902 	                        infeasible, nbdchgs, &added) );
9903 	               }
9904 	               else
9905 	               {
9906 	                  vbimplbound = adjustedLb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9907 	                  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9908 	                        branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9909 	                        infeasible, nbdchgs, &added) );
9910 	               }
9911 	               nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9912 	               i = MIN(i, nvlbvars); /* some elements from the array could have been removed */
9913 	            }
9914 	            --i;
9915 	         }
9916 	      }
9917 	
9918 	      /* non-binary variable: variable upper bounds of implvar */
9919 	      if( impltype == SCIP_BOUNDTYPE_LOWER && implvar->vubs != NULL )
9920 	      {
9921 	         SCIP_VAR** vubvars;
9922 	         SCIP_Real* vubcoefs;
9923 	         SCIP_Real* vubconstants;
9924 	         int nvubvars;
9925 	         int i;
9926 	
9927 	         nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9928 	         vubvars = SCIPvboundsGetVars(implvar->vubs);
9929 	         vubcoefs = SCIPvboundsGetCoefs(implvar->vubs);
9930 	         vubconstants = SCIPvboundsGetConstants(implvar->vubs);
9931 	
9932 	         /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9933 	          * vubvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9934 	          * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9935 	          * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9936 	          * is that we add the same implication twice - this does no harm
9937 	          */
9938 	         i = nvubvars-1;
9939 	         while ( i >= 0 && !(*infeasible) )
9940 	         {
9941 	            assert(vubvars[i] != implvar);
9942 	            assert(!SCIPsetIsZero(set, vubcoefs[i]));
9943 	
9944 	            /* we have x == varfixing -> y >= b and y <= c*z + d:
9945 	             *   c > 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9946 	             *   c < 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9947 	             *
9948 	             * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9949 	             *       SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9950 	             *       aggregation variable (the one which will stay active); 
9951 	             *
9952 	             *       W.l.o.g. we consider the variable lower bounds for now. Let "vlbvar" be a variable lower bound of
9953 	             *       the aggregated variable "aggvar"; During that copying of that variable lower bound variable
9954 	             *       "vlbvar" the variable lower and upper bounds of this variable "vlbvar" are also considered; note
9955 	             *       that the "aggvar" can be a variable upper bound variable of the variable "vlbvar"; Due to that
9956 	             *       situation it can happen that we reach that code place where "vubvars[i] == aggvar". In particular
9957 	             *       the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9958 	             *       but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9959 	             *       have to explicitly check that the active variable has not a variable status
9960 	             *       SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9961 	             */
9962 	            if( SCIPvarIsActive(vubvars[i]) && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_NEGATED )
9963 	            {
9964 	               SCIP_Real vbimplbound;
9965 	
9966 	               vbimplbound = (implbound - vubconstants[i])/vubcoefs[i];
9967 	               if( vubcoefs[i] >= 0.0 )
9968 	               {
9969 	                  vbimplbound = adjustedLb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9970 	                  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9971 	                        branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9972 	                        infeasible, nbdchgs, &added) );
9973 	               }
9974 	               else
9975 	               {
9976 	                  vbimplbound = adjustedUb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9977 	                  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9978 	                        branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9979 	                        infeasible, nbdchgs, &added) );
9980 	               }
9981 	               nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9982 	               i = MIN(i, nvubvars); /* some elements from the array could have been removed */
9983 	            }
9984 	            --i;
9985 	         }
9986 	      }
9987 	   }
9988 	
9989 	   return SCIP_OKAY;
9990 	}
9991 	
9992 	/** informs variable x about a globally valid variable lower bound x >= b*z + d with integer variable z;
9993 	 *  if z is binary, the corresponding valid implication for z is also added;
9994 	 *  improves the global bounds of the variable and the vlb variable if possible
9995 	 */
9996 	SCIP_RETCODE SCIPvarAddVlb(
9997 	   SCIP_VAR*             var,                /**< problem variable */
9998 	   BMS_BLKMEM*           blkmem,             /**< block memory */
9999 	   SCIP_SET*             set,                /**< global SCIP settings */
10000	   SCIP_STAT*            stat,               /**< problem statistics */
10001	   SCIP_PROB*            transprob,          /**< transformed problem */
10002	   SCIP_PROB*            origprob,           /**< original problem */
10003	   SCIP_TREE*            tree,               /**< branch and bound tree if in solving stage */
10004	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
10005	   SCIP_LP*              lp,                 /**< current LP data */
10006	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
10007	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
10008	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
10009	   SCIP_VAR*             vlbvar,             /**< variable z    in x >= b*z + d */
10010	   SCIP_Real             vlbcoef,            /**< coefficient b in x >= b*z + d */
10011	   SCIP_Real             vlbconstant,        /**< constant d    in x >= b*z + d */
10012	   SCIP_Bool             transitive,         /**< should transitive closure of implication also be added? */
10013	   SCIP_Bool*            infeasible,         /**< pointer to store whether an infeasibility was detected */
10014	   int*                  nbdchgs             /**< pointer to store the number of performed bound changes, or NULL */
10015	   )
10016	{
10017	   assert(var != NULL);
10018	   assert(set != NULL);
10019	   assert(var->scip == set->scip);
10020	   assert(SCIPvarGetType(vlbvar) != SCIP_VARTYPE_CONTINUOUS);
10021	   assert(infeasible != NULL);
10022	
10023	   SCIPsetDebugMsg(set, "adding variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
10024	
10025	   *infeasible = FALSE;
10026	   if( nbdchgs != NULL )
10027	      *nbdchgs = 0;
10028	
10029	   switch( SCIPvarGetStatus(var) )
10030	   {
10031	   case SCIP_VARSTATUS_ORIGINAL:
10032	      assert(var->data.original.transvar != NULL);
10033	      SCIP_CALL( SCIPvarAddVlb(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10034	            cliquetable, branchcand, eventqueue, vlbvar, vlbcoef, vlbconstant, transitive, infeasible, nbdchgs) );
10035	      break;
10036	
10037	   case SCIP_VARSTATUS_COLUMN:
10038	   case SCIP_VARSTATUS_LOOSE:
10039	   case SCIP_VARSTATUS_FIXED:
10040	      /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
10041	      SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );
10042	      SCIPsetDebugMsg(set, " -> transformed to variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
10043	
10044	      /* if the vlb coefficient is zero, just update the lower bound of the variable */
10045	      if( SCIPsetIsZero(set, vlbcoef) )
10046	      {
10047	         if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetUbGlobal(var)) )
10048	            *infeasible = TRUE;
10049	         else if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetLbGlobal(var)) )
10050	         {
10051	            /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10052	             * with the local bound, in this case we need to store the bound change as pending bound change
10053	             */
10054	            if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10055	            {
10056	               assert(tree != NULL);
10057	               assert(transprob != NULL);
10058	               assert(SCIPprobIsTransformed(transprob));
10059	
10060	               SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10061	                     tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vlbconstant, SCIP_BOUNDTYPE_LOWER, FALSE) );
10062	            }
10063	            else
10064	            {
10065	               SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vlbconstant) );
10066	            }
10067	
10068	            if( nbdchgs != NULL )
10069	               (*nbdchgs)++;
10070	         }
10071	      }
10072	      else if( var == vlbvar )
10073	      {
10074	         /* the variables cancels out, the variable bound constraint is either redundant or proves global infeasibility */
10075	         if( SCIPsetIsEQ(set, vlbcoef, 1.0) )
10076	         {
10077	            if( SCIPsetIsPositive(set, vlbconstant) )
10078	               *infeasible = TRUE;
10079	            return SCIP_OKAY;
10080	         }
10081	         else
10082	         {
10083	            SCIP_Real lb = SCIPvarGetLbGlobal(var);
10084	            SCIP_Real ub = SCIPvarGetUbGlobal(var);
10085	
10086	            /* the variable bound constraint defines a new upper bound */
10087	            if( SCIPsetIsGT(set, vlbcoef, 1.0) )
10088	            {
10089	               SCIP_Real newub = vlbconstant / (1.0 - vlbcoef);
10090	
10091	               if( SCIPsetIsFeasLT(set, newub, lb) )
10092	               {
10093	                  *infeasible = TRUE;
10094	                  return SCIP_OKAY;
10095	               }
10096	               else if( SCIPsetIsFeasLT(set, newub, ub) )
10097	               {
10098	                  /* bound might be adjusted due to integrality condition */
10099	                  newub = adjustedUb(set, SCIPvarGetType(var), newub);
10100	
10101	                  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10102	                   * with the local bound, in this case we need to store the bound change as pending bound change
10103	                   */
10104	                  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10105	                  {
10106	                     assert(tree != NULL);
10107	                     assert(transprob != NULL);
10108	                     assert(SCIPprobIsTransformed(transprob));
10109	
10110	                     SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10111	                           tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10112	                  }
10113	                  else
10114	                  {
10115	                     SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
10116	                  }
10117	
10118	                  if( nbdchgs != NULL )
10119	                     (*nbdchgs)++;
10120	               }
10121	            }
10122	            /* the variable bound constraint defines a new lower bound */
10123	            else
10124	            {
10125	               SCIP_Real newlb;
10126	
10127	               assert(SCIPsetIsLT(set, vlbcoef, 1.0));
10128	
10129	               newlb = vlbconstant / (1.0 - vlbcoef);
10130	
10131	               if( SCIPsetIsFeasGT(set, newlb, ub) )
10132	               {
10133	                  *infeasible = TRUE;
10134	                  return SCIP_OKAY;
10135	               }
10136	               else if( SCIPsetIsFeasGT(set, newlb, lb) )
10137	               {
10138	                  /* bound might be adjusted due to integrality condition */
10139	                  newlb = adjustedLb(set, SCIPvarGetType(var), newlb);
10140	
10141	                  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10142	                   * with the local bound, in this case we need to store the bound change as pending bound change
10143	                   */
10144	                  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10145	                  {
10146	                     assert(tree != NULL);
10147	                     assert(transprob != NULL);
10148	                     assert(SCIPprobIsTransformed(transprob));
10149	
10150	                     SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10151	                           tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10152	                  }
10153	                  else
10154	                  {
10155	                     SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
10156	                  }
10157	
10158	                  if( nbdchgs != NULL )
10159	                     (*nbdchgs)++;
10160	               }
10161	            }
10162	         }
10163	      }
10164	      else if( SCIPvarIsActive(vlbvar) )
10165	      {
10166	         SCIP_Real xlb;
10167	         SCIP_Real xub;
10168	         SCIP_Real zlb;
10169	         SCIP_Real zub;
10170	         SCIP_Real minvlb;
10171	         SCIP_Real maxvlb;
10172	
10173	         assert(SCIPvarGetStatus(vlbvar) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(vlbvar) == SCIP_VARSTATUS_COLUMN);
10174	         assert(vlbcoef != 0.0);
10175	
10176	         minvlb = -SCIPsetInfinity(set);
10177	         maxvlb = SCIPsetInfinity(set);
10178	
10179	         xlb = SCIPvarGetLbGlobal(var);
10180	         xub = SCIPvarGetUbGlobal(var);
10181	         zlb = SCIPvarGetLbGlobal(vlbvar);
10182	         zub = SCIPvarGetUbGlobal(vlbvar);
10183	
10184	         /* improve global bounds of vlb variable, and calculate minimal and maximal value of variable bound */
10185	         if( vlbcoef >= 0.0 )
10186	         {
10187	            SCIP_Real newzub;
10188	
10189	            if( !SCIPsetIsInfinity(set, xub) )
10190	            {
10191	               /* x >= b*z + d  ->  z <= (x-d)/b */
10192	               newzub = (xub - vlbconstant)/vlbcoef;
10193	
10194	               /* return if the new bound is less than -infinity */
10195	               if( SCIPsetIsInfinity(set, REALABS(newzub)) )
10196	                  return SCIP_OKAY;
10197	
10198	               if( SCIPsetIsFeasLT(set, newzub, zlb) )
10199	               {
10200	                  *infeasible = TRUE;
10201	                  return SCIP_OKAY;
10202	               }
10203	               if( SCIPsetIsFeasLT(set, newzub, zub) )
10204	               {
10205	                  /* bound might be adjusted due to integrality condition */
10206	                  newzub = adjustedUb(set, SCIPvarGetType(vlbvar), newzub);
10207	
10208	                  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10209	                   * with the local bound, in this case we need to store the bound change as pending bound change
10210	                   */
10211	                  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10212	                  {
10213	                     assert(tree != NULL);
10214	                     assert(transprob != NULL);
10215	                     assert(SCIPprobIsTransformed(transprob));
10216	
10217	                     SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10218	                           tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10219	                  }
10220	                  else
10221	                  {
10222	                     SCIP_CALL( SCIPvarChgUbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10223	                  }
10224	                  zub = newzub;
10225	
10226	                  if( nbdchgs != NULL )
10227	                     (*nbdchgs)++;
10228	               }
10229	               maxvlb = vlbcoef * zub + vlbconstant;
10230	               if( !SCIPsetIsInfinity(set, -zlb) )
10231	                  minvlb = vlbcoef * zlb + vlbconstant;
10232	            }
10233	            else
10234	            {
10235	               if( !SCIPsetIsInfinity(set, zub) )
10236	                  maxvlb = vlbcoef * zub + vlbconstant;
10237	               if( !SCIPsetIsInfinity(set, -zlb) )
10238	                  minvlb = vlbcoef * zlb + vlbconstant;
10239	            }
10240	         }
10241	         else
10242	         {
10243	            SCIP_Real newzlb;
10244	
10245	            if( !SCIPsetIsInfinity(set, xub) )
10246	            {
10247	               /* x >= b*z + d  ->  z >= (x-d)/b */
10248	               newzlb = (xub - vlbconstant)/vlbcoef;
10249	
10250	               /* return if the new bound is larger than infinity */
10251	               if( SCIPsetIsInfinity(set, REALABS(newzlb)) )
10252	                  return SCIP_OKAY;
10253	
10254	               if( SCIPsetIsFeasGT(set, newzlb, zub) )
10255	               {
10256	                  *infeasible = TRUE;
10257	                  return SCIP_OKAY;
10258	               }
10259	               if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10260	               {
10261	                  /* bound might be adjusted due to integrality condition */
10262	                  newzlb = adjustedLb(set, SCIPvarGetType(vlbvar), newzlb);
10263	
10264	                  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10265	                   * with the local bound, in this case we need to store the bound change as pending bound change
10266	                   */
10267	                  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10268	                  {
10269	                     assert(tree != NULL);
10270	                     assert(transprob != NULL);
10271	                     assert(SCIPprobIsTransformed(transprob));
10272	
10273	                     SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10274	                           tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10275	                  }
10276	                  else
10277	                  {
10278	                     SCIP_CALL( SCIPvarChgLbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10279	                  }
10280	                  zlb = newzlb;
10281	
10282	                  if( nbdchgs != NULL )
10283	                     (*nbdchgs)++;
10284	               }
10285	               maxvlb = vlbcoef * zlb + vlbconstant;
10286	               if( !SCIPsetIsInfinity(set, zub) )
10287	                  minvlb = vlbcoef * zub + vlbconstant;
10288	            }
10289	            else
10290	            {
10291	               if( !SCIPsetIsInfinity(set, -zlb) )
10292	                  maxvlb = vlbcoef * zlb + vlbconstant;
10293	               if( !SCIPsetIsInfinity(set, zub) )
10294	                  minvlb = vlbcoef * zub + vlbconstant;
10295	            }
10296	         }
10297	         if( maxvlb < minvlb )
10298	            maxvlb = minvlb;
10299	
10300	         /* adjust bounds due to integrality of variable */
10301	         minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
10302	         maxvlb = adjustedLb(set, SCIPvarGetType(var), maxvlb);
10303	
10304	         /* check bounds for feasibility */
10305	         if( SCIPsetIsFeasGT(set, minvlb, xub) || (var == vlbvar && SCIPsetIsEQ(set, vlbcoef, 1.0) && SCIPsetIsFeasPositive(set, vlbconstant))  )
10306	         {
10307	            *infeasible = TRUE;
10308	            return SCIP_OKAY;
10309	         }
10310	         /* improve global lower bound of variable */
10311	         if( SCIPsetIsFeasGT(set, minvlb, xlb) )
10312	         {
10313	            /* bound might be adjusted due to integrality condition */
10314	            minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
10315	
10316	            /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10317	             * with the local bound, in this case we need to store the bound change as pending bound change
10318	             */
10319	            if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10320	            {
10321	               assert(tree != NULL);
10322	               assert(transprob != NULL);
10323	               assert(SCIPprobIsTransformed(transprob));
10324	
10325	               SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10326	                     tree, reopt, lp, branchcand, eventqueue, cliquetable, var, minvlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10327	            }
10328	            else
10329	            {
10330	               SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, minvlb) );
10331	            }
10332	            xlb = minvlb;
10333	
10334	            if( nbdchgs != NULL )
10335	               (*nbdchgs)++;
10336	         }
10337	         minvlb = xlb;
10338	
10339	         /* improve variable bound for binary z by moving the variable's global bound to the vlb constant */
10340	         if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
10341	         {
10342	            /* b > 0: x >= (maxvlb - minvlb) * z + minvlb
10343	             * b < 0: x >= (minvlb - maxvlb) * z + maxvlb
10344	             */
10345	
10346	            assert(!SCIPsetIsInfinity(set, maxvlb) && !SCIPsetIsInfinity(set, -minvlb));
10347	
10348	            if( vlbcoef >= 0.0 )
10349	            {
10350	               vlbcoef = maxvlb - minvlb;
10351	               vlbconstant = minvlb;
10352	            }
10353	            else
10354	            {
10355	               vlbcoef = minvlb - maxvlb;
10356	               vlbconstant = maxvlb;
10357	            }
10358	         }
10359	
10360	         /* add variable bound to the variable bounds list */
10361	         if( SCIPsetIsFeasGT(set, maxvlb, xlb) )
10362	         {
10363	            assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10364	            assert(!SCIPsetIsZero(set, vlbcoef));
10365	
10366	            /* if one of the variables is binary, add the corresponding implication to the variable's implication
10367	             * list, thereby also adding the variable bound (or implication) to the other variable
10368	             */
10369	            if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
10370	            {
10371	               /* add corresponding implication:
10372	                *   b > 0, x >= b*z + d  <->  z == 1 -> x >= b+d
10373	                *   b < 0, x >= b*z + d  <->  z == 0 -> x >= d
10374	                */
10375	               SCIP_CALL( varAddTransitiveImplic(vlbvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10376	                     cliquetable, branchcand, eventqueue, (vlbcoef >= 0.0), var, SCIP_BOUNDTYPE_LOWER, maxvlb, transitive,
10377	                     infeasible, nbdchgs) );
10378	            }
10379	            else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10380	            {
10381	               /* add corresponding implication:
10382	                *   b > 0, x >= b*z + d  <->  x == 0 -> z <= -d/b
10383	                *   b < 0, x >= b*z + d  <->  x == 0 -> z >= -d/b
10384	                */
10385	               SCIP_Real implbound;
10386	               implbound = -vlbconstant/vlbcoef;
10387	
10388	               /* tighten the implication bound if the variable is integer */
10389	               if( SCIPvarIsIntegral(vlbvar) )
10390	               {
10391	                  if( vlbcoef >= 0 )
10392	                     implbound = SCIPsetFloor(set, implbound);
10393	                  else
10394	                     implbound = SCIPsetCeil(set, implbound);
10395	               }
10396	               SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10397	                     cliquetable, branchcand, eventqueue, FALSE, vlbvar, (vlbcoef >= 0.0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER),
10398	                     implbound, transitive, infeasible, nbdchgs) );
10399	            }
10400	            else
10401	            {
10402	               SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, vlbvar, vlbcoef, vlbconstant) );
10403	            }
10404	         }
10405	      }
10406	      break;
10407	
10408	   case SCIP_VARSTATUS_AGGREGATED:
10409	      /* x = a*y + c:  x >= b*z + d  <=>  a*y + c >= b*z + d  <=>  y >= b/a * z + (d-c)/a, if a > 0
10410	       *                                                           y <= b/a * z + (d-c)/a, if a < 0
10411	       */
10412	      assert(var->data.aggregate.var != NULL);
10413	      if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10414	      {
10415	         /* a > 0 -> add variable lower bound */
10416	         SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10417	               cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10418	               (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10419	      }
10420	      else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10421	      {
10422	         /* a < 0 -> add variable upper bound */
10423	         SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10424	               cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10425	               (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10426	      }
10427	      else
10428	      {
10429	         SCIPerrorMessage("scalar is zero in aggregation\n");
10430	         return SCIP_INVALIDDATA;
10431	      }
10432	      break;
10433	
10434	   case SCIP_VARSTATUS_MULTAGGR:
10435	      /* nothing to do here */
10436	      break;
10437	
10438	   case SCIP_VARSTATUS_NEGATED:
10439	      /* x = offset - x':  x >= b*z + d  <=>  offset - x' >= b*z + d  <=>  x' <= -b*z + (offset-d) */
10440	      assert(var->negatedvar != NULL);
10441	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
10442	      assert(var->negatedvar->negatedvar == var);
10443	      SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10444	            branchcand, eventqueue, vlbvar, -vlbcoef, var->data.negate.constant - vlbconstant, transitive, infeasible,
10445	            nbdchgs) );
10446	      break;
10447	
10448	   default:
10449	      SCIPerrorMessage("unknown variable status\n");
10450	      return SCIP_INVALIDDATA;
10451	   }
10452	
10453	   return SCIP_OKAY;
10454	}
10455	
10456	/** informs variable x about a globally valid variable upper bound x <= b*z + d with integer variable z;
10457	 *  if z is binary, the corresponding valid implication for z is also added;
10458	 *  updates the global bounds of the variable and the vub variable correspondingly
10459	 */
10460	SCIP_RETCODE SCIPvarAddVub(
10461	   SCIP_VAR*             var,                /**< problem variable */
10462	   BMS_BLKMEM*           blkmem,             /**< block memory */
10463	   SCIP_SET*             set,                /**< global SCIP settings */
10464	   SCIP_STAT*            stat,               /**< problem statistics */
10465	   SCIP_PROB*            transprob,          /**< transformed problem */
10466	   SCIP_PROB*            origprob,           /**< original problem */
10467	   SCIP_TREE*            tree,               /**< branch and bound tree if in solving stage */
10468	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
10469	   SCIP_LP*              lp,                 /**< current LP data */
10470	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
10471	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
10472	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
10473	   SCIP_VAR*             vubvar,             /**< variable z    in x <= b*z + d */
10474	   SCIP_Real             vubcoef,            /**< coefficient b in x <= b*z + d */
10475	   SCIP_Real             vubconstant,        /**< constant d    in x <= b*z + d */
10476	   SCIP_Bool             transitive,         /**< should transitive closure of implication also be added? */
10477	   SCIP_Bool*            infeasible,         /**< pointer to store whether an infeasibility was detected */
10478	   int*                  nbdchgs             /**< pointer to store the number of performed bound changes, or NULL */
10479	   )
10480	{
10481	   assert(var != NULL);
10482	   assert(set != NULL);
10483	   assert(var->scip == set->scip);
10484	   assert(SCIPvarGetType(vubvar) != SCIP_VARTYPE_CONTINUOUS);
10485	   assert(infeasible != NULL);
10486	
10487	   SCIPsetDebugMsg(set, "adding variable upper bound <%s> <= %g<%s> + %g\n", SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10488	
10489	   *infeasible = FALSE;
10490	   if( nbdchgs != NULL )
10491	      *nbdchgs = 0;
10492	
10493	   switch( SCIPvarGetStatus(var) )
10494	   {
10495	   case SCIP_VARSTATUS_ORIGINAL:
10496	      assert(var->data.original.transvar != NULL);
10497	      SCIP_CALL( SCIPvarAddVub(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10498	            cliquetable, branchcand, eventqueue, vubvar, vubcoef, vubconstant, transitive, infeasible, nbdchgs) );
10499	      break;
10500	
10501	   case SCIP_VARSTATUS_COLUMN:
10502	   case SCIP_VARSTATUS_LOOSE:
10503	   case SCIP_VARSTATUS_FIXED:
10504	      /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
10505	      SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );
10506	      SCIPsetDebugMsg(set, " -> transformed to variable upper bound <%s> <= %g<%s> + %g\n",
10507	         SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10508	
10509	      /* if the vub coefficient is zero, just update the upper bound of the variable */
10510	      if( SCIPsetIsZero(set, vubcoef) )
10511	      {
10512	         if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetLbGlobal(var)) )
10513	            *infeasible = TRUE;
10514	         else if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetUbGlobal(var)) )
10515	         {
10516	            /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10517	             * with the local bound, in this case we need to store the bound change as pending bound change
10518	             */
10519	            if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10520	            {
10521	               assert(tree != NULL);
10522	               assert(transprob != NULL);
10523	               assert(SCIPprobIsTransformed(transprob));
10524	
10525	               SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10526	                     tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vubconstant, SCIP_BOUNDTYPE_UPPER, FALSE) );
10527	            }
10528	            else
10529	            {
10530	               SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vubconstant) );
10531	            }
10532	
10533	            if( nbdchgs != NULL )
10534	               (*nbdchgs)++;
10535	         }
10536	      }
10537	      else if( var == vubvar )
10538	      {
10539	         /* the variables cancels out, the variable bound constraint is either redundant or proves global infeasibility */
10540	         if( SCIPsetIsEQ(set, vubcoef, 1.0) )
10541	         {
10542	            if( SCIPsetIsNegative(set, vubconstant) )
10543	               *infeasible = TRUE;
10544	            return SCIP_OKAY;
10545	         }
10546	         else
10547	         {
10548	            SCIP_Real lb = SCIPvarGetLbGlobal(var);
10549	            SCIP_Real ub = SCIPvarGetUbGlobal(var);
10550	
10551	            /* the variable bound constraint defines a new lower bound */
10552	            if( SCIPsetIsGT(set, vubcoef, 1.0) )
10553	            {
10554	               SCIP_Real newlb = vubconstant / (1.0 - vubcoef);
10555	
10556	               if( SCIPsetIsFeasGT(set, newlb, ub) )
10557	               {
10558	                  *infeasible = TRUE;
10559	                  return SCIP_OKAY;
10560	               }
10561	               else if( SCIPsetIsFeasGT(set, newlb, lb) )
10562	               {
10563	                  /* bound might be adjusted due to integrality condition */
10564	                  newlb = adjustedLb(set, SCIPvarGetType(var), newlb);
10565	
10566	                  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10567	                   * with the local bound, in this case we need to store the bound change as pending bound change
10568	                   */
10569	                  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10570	                  {
10571	                     assert(tree != NULL);
10572	                     assert(transprob != NULL);
10573	                     assert(SCIPprobIsTransformed(transprob));
10574	
10575	                     SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10576	                           tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10577	                  }
10578	                  else
10579	                  {
10580	                     SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
10581	                  }
10582	
10583	                  if( nbdchgs != NULL )
10584	                     (*nbdchgs)++;
10585	               }
10586	            }
10587	            /* the variable bound constraint defines a new upper bound */
10588	            else
10589	            {
10590	               SCIP_Real newub;
10591	
10592	               assert(SCIPsetIsLT(set, vubcoef, 1.0));
10593	
10594	               newub = vubconstant / (1.0 - vubcoef);
10595	
10596	               if( SCIPsetIsFeasLT(set, newub, lb) )
10597	               {
10598	                  *infeasible = TRUE;
10599	                  return SCIP_OKAY;
10600	               }
10601	               else if( SCIPsetIsFeasLT(set, newub, ub) )
10602	               {
10603	                  /* bound might be adjusted due to integrality condition */
10604	                  newub = adjustedUb(set, SCIPvarGetType(var), newub);
10605	
10606	                  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10607	                   * with the local bound, in this case we need to store the bound change as pending bound change
10608	                   */
10609	                  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10610	                  {
10611	                     assert(tree != NULL);
10612	                     assert(transprob != NULL);
10613	                     assert(SCIPprobIsTransformed(transprob));
10614	
10615	                     SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10616	                           tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10617	                  }
10618	                  else
10619	                  {
10620	                     SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
10621	                  }
10622	
10623	                  if( nbdchgs != NULL )
10624	                     (*nbdchgs)++;
10625	               }
10626	            }
10627	         }
10628	      }
10629	      else if( SCIPvarIsActive(vubvar) )
10630	      {
10631	         SCIP_Real xlb;
10632	         SCIP_Real xub;
10633	         SCIP_Real zlb;
10634	         SCIP_Real zub;
10635	         SCIP_Real minvub;
10636	         SCIP_Real maxvub;
10637	
10638	         assert(SCIPvarGetStatus(vubvar) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(vubvar) == SCIP_VARSTATUS_COLUMN);
10639	         assert(vubcoef != 0.0);
10640	
10641	         minvub = -SCIPsetInfinity(set);
10642	         maxvub = SCIPsetInfinity(set);
10643	
10644	         xlb = SCIPvarGetLbGlobal(var);
10645	         xub = SCIPvarGetUbGlobal(var);
10646	         zlb = SCIPvarGetLbGlobal(vubvar);
10647	         zub = SCIPvarGetUbGlobal(vubvar);
10648	
10649	         /* improve global bounds of vub variable, and calculate minimal and maximal value of variable bound */
10650	         if( vubcoef >= 0.0 )
10651	         {
10652	            SCIP_Real newzlb;
10653	
10654	            if( !SCIPsetIsInfinity(set, -xlb) )
10655	            {
10656	               /* x <= b*z + d  ->  z >= (x-d)/b */
10657	               newzlb = (xlb - vubconstant)/vubcoef;
10658	               if( SCIPsetIsFeasGT(set, newzlb, zub) )
10659	               {
10660	                  *infeasible = TRUE;
10661	                  return SCIP_OKAY;
10662	               }
10663	               if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10664	               {
10665	                  /* bound might be adjusted due to integrality condition */
10666	                  newzlb = adjustedLb(set, SCIPvarGetType(vubvar), newzlb);
10667	
10668	                  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10669	                   * with the local bound, in this case we need to store the bound change as pending bound change
10670	                   */
10671	                  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10672	                  {
10673	                     assert(tree != NULL);
10674	                     assert(transprob != NULL);
10675	                     assert(SCIPprobIsTransformed(transprob));
10676	
10677	                     SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10678	                           tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10679	                  }
10680	                  else
10681	                  {
10682	                     SCIP_CALL( SCIPvarChgLbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10683	                  }
10684	                  zlb = newzlb;
10685	
10686	                  if( nbdchgs != NULL )
10687	                     (*nbdchgs)++;
10688	               }
10689	               minvub = vubcoef * zlb + vubconstant;
10690	               if( !SCIPsetIsInfinity(set, zub) )
10691	                  maxvub = vubcoef * zub + vubconstant;
10692	            }
10693	            else
10694	            {
10695	               if( !SCIPsetIsInfinity(set, zub) )
10696	                  maxvub = vubcoef * zub + vubconstant;
10697	               if( !SCIPsetIsInfinity(set, -zlb) )
10698	                  minvub = vubcoef * zlb + vubconstant;
10699	            }
10700	         }
10701	         else
10702	         {
10703	            SCIP_Real newzub;
10704	
10705	            if( !SCIPsetIsInfinity(set, -xlb) )
10706	            {
10707	               /* x <= b*z + d  ->  z <= (x-d)/b */
10708	               newzub = (xlb - vubconstant)/vubcoef;
10709	               if( SCIPsetIsFeasLT(set, newzub, zlb) )
10710	               {
10711	                  *infeasible = TRUE;
10712	                  return SCIP_OKAY;
10713	               }
10714	               if( SCIPsetIsFeasLT(set, newzub, zub) )
10715	               {
10716	                  /* bound might be adjusted due to integrality condition */
10717	                  newzub = adjustedUb(set, SCIPvarGetType(vubvar), newzub);
10718	
10719	                  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10720	                   * with the local bound, in this case we need to store the bound change as pending bound change
10721	                   */
10722	                  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10723	                  {
10724	                     assert(tree != NULL);
10725	                     assert(transprob != NULL);
10726	                     assert(SCIPprobIsTransformed(transprob));
10727	
10728	                     SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10729	                           tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10730	                  }
10731	                  else
10732	                  {
10733	                     SCIP_CALL( SCIPvarChgUbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10734	                  }
10735	                  zub = newzub;
10736	
10737	                  if( nbdchgs != NULL )
10738	                     (*nbdchgs)++;
10739	               }
10740	               minvub = vubcoef * zub + vubconstant;
10741	               if( !SCIPsetIsInfinity(set, -zlb) )
10742	                  maxvub = vubcoef * zlb + vubconstant;
10743	            }
10744	            else
10745	            {
10746	               if( !SCIPsetIsInfinity(set, zub) )
10747	                  minvub = vubcoef * zub + vubconstant;
10748	               if( !SCIPsetIsInfinity(set, -zlb) )
10749	                  maxvub = vubcoef * zlb + vubconstant;
10750	            }
10751	         }
10752	         if( minvub > maxvub )
10753	            minvub = maxvub;
10754	
10755	         /* adjust bounds due to integrality of vub variable */
10756	         minvub = adjustedUb(set, SCIPvarGetType(var), minvub);
10757	         maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10758	
10759	         /* check bounds for feasibility */
10760	         if( SCIPsetIsFeasLT(set, maxvub, xlb) || (var == vubvar && SCIPsetIsEQ(set, vubcoef, 1.0) && SCIPsetIsFeasNegative(set, vubconstant))  )
10761	         {
10762	            *infeasible = TRUE;
10763	            return SCIP_OKAY;
10764	         }
10765	
10766	         /* improve global upper bound of variable */
10767	         if( SCIPsetIsFeasLT(set, maxvub, xub) )
10768	         {
10769	            /* bound might be adjusted due to integrality condition */
10770	            maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10771	
10772	            /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10773	             * with the local bound, in this case we need to store the bound change as pending bound change
10774	             */
10775	            if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10776	            {
10777	               assert(tree != NULL);
10778	               assert(transprob != NULL);
10779	               assert(SCIPprobIsTransformed(transprob));
10780	
10781	               SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10782	                     tree, reopt, lp, branchcand, eventqueue, cliquetable, var, maxvub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10783	            }
10784	            else
10785	            {
10786	               SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, maxvub) );
10787	            }
10788	            xub = maxvub;
10789	
10790	            if( nbdchgs != NULL )
10791	               (*nbdchgs)++;
10792	         }
10793	         maxvub = xub;
10794	
10795	         /* improve variable bound for binary z by moving the variable's global bound to the vub constant */
10796	         if( SCIPvarIsBinary(vubvar) )
10797	         {
10798	            /* b > 0: x <= (maxvub - minvub) * z + minvub
10799	             * b < 0: x <= (minvub - maxvub) * z + maxvub
10800	             */
10801	
10802	            assert(!SCIPsetIsInfinity(set, maxvub) && !SCIPsetIsInfinity(set, -minvub));
10803	
10804	            if( vubcoef >= 0.0 )
10805	            {
10806	               vubcoef = maxvub - minvub;
10807	               vubconstant = minvub;
10808	            }
10809	            else
10810	            {
10811	               vubcoef = minvub - maxvub;
10812	               vubconstant = maxvub;
10813	            }
10814	         }
10815	
10816	         /* add variable bound to the variable bounds list */
10817	         if( SCIPsetIsFeasLT(set, minvub, xub) )
10818	         {
10819	            assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10820	            assert(!SCIPsetIsZero(set, vubcoef));
10821	
10822	            /* if one of the variables is binary, add the corresponding implication to the variable's implication
10823	             * list, thereby also adding the variable bound (or implication) to the other variable
10824	             */
10825	            if( SCIPvarGetType(vubvar) == SCIP_VARTYPE_BINARY )
10826	            {
10827	               /* add corresponding implication:
10828	                *   b > 0, x <= b*z + d  <->  z == 0 -> x <= d
10829	                *   b < 0, x <= b*z + d  <->  z == 1 -> x <= b+d
10830	                */
10831	               SCIP_CALL( varAddTransitiveImplic(vubvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10832	                     cliquetable, branchcand, eventqueue, (vubcoef < 0.0), var, SCIP_BOUNDTYPE_UPPER, minvub, transitive,
10833	                     infeasible, nbdchgs) );
10834	            }
10835	            else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10836	            {
10837	               /* add corresponding implication:
10838	                *   b > 0, x <= b*z + d  <->  x == 1 -> z >= (1-d)/b
10839	                *   b < 0, x <= b*z + d  <->  x == 1 -> z <= (1-d)/b
10840	                */
10841	               SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10842	                     cliquetable, branchcand, eventqueue, TRUE, vubvar, (vubcoef >= 0.0 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER),
10843	                     (1.0-vubconstant)/vubcoef, transitive, infeasible, nbdchgs) );
10844	            }
10845	            else
10846	            {
10847	               SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, vubvar, vubcoef, vubconstant) );
10848	            }
10849	         }
10850	      }
10851	      break;
10852	
10853	   case SCIP_VARSTATUS_AGGREGATED:
10854	      /* x = a*y + c:  x <= b*z + d  <=>  a*y + c <= b*z + d  <=>  y <= b/a * z + (d-c)/a, if a > 0
10855	       *                                                           y >= b/a * z + (d-c)/a, if a < 0
10856	       */
10857	      assert(var->data.aggregate.var != NULL);
10858	      if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10859	      {
10860	         /* a > 0 -> add variable upper bound */
10861	         SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10862	               cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10863	               (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10864	      }
10865	      else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10866	      {
10867	         /* a < 0 -> add variable lower bound */
10868	         SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10869	               cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10870	               (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10871	      }
10872	      else
10873	      {
10874	         SCIPerrorMessage("scalar is zero in aggregation\n");
10875	         return SCIP_INVALIDDATA;
10876	      }
10877	      break;
10878	
10879	   case SCIP_VARSTATUS_MULTAGGR:
10880	      /* nothing to do here */
10881	      break;
10882	
10883	   case SCIP_VARSTATUS_NEGATED:
10884	      /* x = offset - x':  x <= b*z + d  <=>  offset - x' <= b*z + d  <=>  x' >= -b*z + (offset-d) */
10885	      assert(var->negatedvar != NULL);
10886	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
10887	      assert(var->negatedvar->negatedvar == var);
10888	      SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10889	            branchcand, eventqueue, vubvar, -vubcoef, var->data.negate.constant - vubconstant, transitive, infeasible,
10890	            nbdchgs) );
10891	      break;
10892	
10893	   default:
10894	      SCIPerrorMessage("unknown variable status\n");
10895	      return SCIP_INVALIDDATA;
10896	   }
10897	
10898	   return SCIP_OKAY;
10899	}
10900	
10901	/** informs binary variable x about a globally valid implication:  x == 0 or x == 1  ==>  y <= b  or  y >= b;
10902	 *  also adds the corresponding implication or variable bound to the implied variable;
10903	 *  if the implication is conflicting, the variable is fixed to the opposite value;
10904	 *  if the variable is already fixed to the given value, the implication is performed immediately;
10905	 *  if the implication is redundant with respect to the variables' global bounds, it is ignored
10906	 */
10907	SCIP_RETCODE SCIPvarAddImplic(
10908	   SCIP_VAR*             var,                /**< problem variable  */
10909	   BMS_BLKMEM*           blkmem,             /**< block memory */
10910	   SCIP_SET*             set,                /**< global SCIP settings */
10911	   SCIP_STAT*            stat,               /**< problem statistics */
10912	   SCIP_PROB*            transprob,          /**< transformed problem */
10913	   SCIP_PROB*            origprob,           /**< original problem */
10914	   SCIP_TREE*            tree,               /**< branch and bound tree if in solving stage */
10915	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
10916	   SCIP_LP*              lp,                 /**< current LP data */
10917	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
10918	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
10919	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
10920	   SCIP_Bool             varfixing,          /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
10921	   SCIP_VAR*             implvar,            /**< variable y in implication y <= b or y >= b */
10922	   SCIP_BOUNDTYPE        impltype,           /**< type       of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
10923	   SCIP_Real             implbound,          /**< bound b    in implication y <= b or y >= b */
10924	   SCIP_Bool             transitive,         /**< should transitive closure of implication also be added? */
10925	   SCIP_Bool*            infeasible,         /**< pointer to store whether an infeasibility was detected */
10926	   int*                  nbdchgs             /**< pointer to store the number of performed bound changes, or NULL */
10927	   )
10928	{
10929	   assert(var != NULL);
10930	   assert(set != NULL);
10931	   assert(var->scip == set->scip);
10932	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
10933	   assert(infeasible != NULL);
10934	
10935	   *infeasible = FALSE;
10936	   if( nbdchgs != NULL )
10937	      *nbdchgs = 0;
10938	
10939	   switch( SCIPvarGetStatus(var) )
10940	   {
10941	   case SCIP_VARSTATUS_ORIGINAL:
10942	      assert(var->data.original.transvar != NULL);
10943	      SCIP_CALL( SCIPvarAddImplic(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10944	            cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10945	            nbdchgs) );
10946	      break;
10947	
10948	   case SCIP_VARSTATUS_COLUMN:
10949	   case SCIP_VARSTATUS_LOOSE:
10950	      /* if the variable is fixed (although it has no FIXED status), and varfixing corresponds to the fixed value of
10951	       * the variable, the implication can be applied directly;
10952	       * otherwise, add implication to the implications list (and add inverse of implication to the implied variable)
10953	       */
10954	      if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
10955	      {
10956	         if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10957	         {
10958	            SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10959	                  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10960	         }
10961	      }
10962	      else
10963	      {
10964	         SCIP_CALL( SCIPvarGetProbvarBound(&implvar, &implbound, &impltype) );
10965	         SCIPvarAdjustBd(implvar, set, impltype, &implbound);
10966	         if( SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED )
10967	         {
10968	            SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10969	                  branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10970	         }
10971	      }
10972	      break;
10973	
10974	   case SCIP_VARSTATUS_FIXED:
10975	      /* if varfixing corresponds to the fixed value of the variable, the implication can be applied directly */
10976	      if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10977	      {
10978	         SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10979	               cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10980	      }
10981	      break;
10982	
10983	   case SCIP_VARSTATUS_AGGREGATED:
10984	      /* implication added for x == 1:
10985	       *   x == 1 && x =  1*z + 0  ==>  y <= b or y >= b    <==>    z >= 1  ==>  y <= b or y >= b 
10986	       *   x == 1 && x = -1*z + 1  ==>  y <= b or y >= b    <==>    z <= 0  ==>  y <= b or y >= b
10987	       * implication added for x == 0:
10988	       *   x == 0 && x =  1*z + 0  ==>  y <= b or y >= b    <==>    z <= 0  ==>  y <= b or y >= b
10989	       *   x == 0 && x = -1*z + 1  ==>  y <= b or y >= b    <==>    z >= 1  ==>  y <= b or y >= b
10990	       *
10991	       * use only binary variables z 
10992	       */
10993	      assert(var->data.aggregate.var != NULL);
10994	      if( SCIPvarIsBinary(var->data.aggregate.var) )
10995	      {
10996	         assert( (SCIPsetIsEQ(set, var->data.aggregate.scalar, 1.0) && SCIPsetIsZero(set, var->data.aggregate.constant))
10997	            || (SCIPsetIsEQ(set, var->data.aggregate.scalar, -1.0) && SCIPsetIsEQ(set, var->data.aggregate.constant, 1.0)) );
10998	
10999	         if( var->data.aggregate.scalar > 0 )
11000	         {
11001	            SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11002	                  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
11003	                  nbdchgs) );
11004	         }
11005	         else
11006	         {
11007	            SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11008	                  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible,
11009	                  nbdchgs) );
11010	         }
11011	      }
11012	      break;
11013	
11014	   case SCIP_VARSTATUS_MULTAGGR:
11015	      /* nothing to do here */
11016	      break;
11017	
11018	   case SCIP_VARSTATUS_NEGATED:
11019	      /* implication added for x == 1:
11020	       *   x == 1 && x = -1*z + 1  ==>  y <= b or y >= b    <==>    z <= 0  ==>  y <= b or y >= b
11021	       * implication added for x == 0:
11022	       *   x == 0 && x = -1*z + 1  ==>  y <= b or y >= b    <==>    z >= 1  ==>  y <= b or y >= b
11023	       */
11024	      assert(var->negatedvar != NULL);
11025	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
11026	      assert(var->negatedvar->negatedvar == var);
11027	      assert(SCIPvarIsBinary(var->negatedvar));
11028	
11029	      if( SCIPvarGetType(var->negatedvar) == SCIP_VARTYPE_BINARY )
11030	      {
11031	         SCIP_CALL( SCIPvarAddImplic(var->negatedvar, blkmem, set, stat,  transprob, origprob, tree, reopt, lp,
11032	               cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
11033	      }
11034	      /* in case one both variables are not of binary type we have to add the implication as variable bounds */
11035	      else
11036	      {
11037	         /* if the implied variable is of binary type exchange the variables */
11038	         if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
11039	         {
11040	            SCIP_CALL( SCIPvarAddImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11041	                  branchcand, eventqueue, (impltype == SCIP_BOUNDTYPE_UPPER) ? TRUE : FALSE, var->negatedvar,
11042	                  varfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER, varfixing ? 1.0 : 0.0, transitive,
11043	                  infeasible, nbdchgs) );
11044	         }
11045	         else
11046	         {
11047	            /* both variables are not of binary type but are implicit binary; in that case we can only add this
11048	             * implication as variable bounds
11049	             */
11050	
11051	            /* add variable lower bound on the negation of var */
11052	            if( varfixing )
11053	            {
11054	               /* (x = 1 => i) z = 0 ii) z = 1) <=> ( i) z = 1 ii) z = 0 => ~x = 1), this is done by adding ~x >= b*z + d
11055	                * as variable lower bound
11056	                */
11057	               SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11058	                     cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : -1.0,
11059	                     (impltype == SCIP_BOUNDTYPE_UPPER) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
11060	            }
11061	            else
11062	            {
11063	               /* (x = 0 => i) z = 0 ii) z = 1) <=> ( i) z = 1 ii) z = 0 => ~x = 0), this is done by adding ~x <= b*z + d
11064	                * as variable upper bound
11065	                */
11066	               SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11067	                     cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? -1.0 : 1.0,
11068	                     (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : 0.0, transitive, infeasible, nbdchgs) );
11069	            }
11070	
11071	            /* add variable bound on implvar */
11072	            if( impltype == SCIP_BOUNDTYPE_UPPER )
11073	            {
11074	               /* (z = 1 => i) x = 0 ii) x = 1) <=> ( i) ~x = 0 ii) ~x = 1 => z = 0), this is done by adding z <= b*~x + d
11075	                * as variable upper bound
11076	                */
11077	               SCIP_CALL( SCIPvarAddVub(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11078	                     branchcand, eventqueue, var->negatedvar, (varfixing) ? 1.0 : -1.0,
11079	                     (varfixing) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
11080	            }
11081	            else
11082	            {
11083	               /* (z = 0 => i) x = 0 ii) x = 1) <=> ( i) ~x = 0 ii) ~x = 1 => z = 1), this is done by adding z >= b*~x + d
11084	                * as variable upper bound
11085	                */
11086	               SCIP_CALL( SCIPvarAddVlb(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11087	                     branchcand, eventqueue, var->negatedvar, (varfixing) ? -1.0 : 1.0, (varfixing) ? 1.0 : 0.0,
11088	                     transitive, infeasible, nbdchgs) );
11089	            }
11090	         }
11091	      }
11092	      break;
11093	
11094	   default:
11095	      SCIPerrorMessage("unknown variable status\n");
11096	      return SCIP_INVALIDDATA;
11097	   }
11098	
11099	   return SCIP_OKAY;
11100	}
11101	
11102	/** returns whether there is an implication x == varfixing -> y <= b or y >= b in the implication graph;
11103	 *  implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
11104	 *  both variables must be active, variable x must be binary
11105	 */
11106	SCIP_Bool SCIPvarHasImplic(
11107	   SCIP_VAR*             var,                /**< problem variable x */
11108	   SCIP_Bool             varfixing,          /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
11109	   SCIP_VAR*             implvar,            /**< variable y to search for */
11110	   SCIP_BOUNDTYPE        impltype            /**< type of implication y <=/>= b to search for */
11111	   )
11112	{
11113	   assert(var != NULL);
11114	   assert(implvar != NULL);
11115	   assert(SCIPvarIsActive(var));
11116	   assert(SCIPvarIsActive(implvar));
11117	   assert(SCIPvarIsBinary(var));
11118	
11119	   return var->implics != NULL && SCIPimplicsContainsImpl(var->implics, varfixing, implvar, impltype);
11120	}
11121	
11122	/** returns whether there is an implication x == varfixing -> y == implvarfixing in the implication graph;
11123	 *  implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
11124	 *  both variables must be active binary variables
11125	 */
11126	SCIP_Bool SCIPvarHasBinaryImplic(
11127	   SCIP_VAR*             var,                /**< problem variable x */
11128	   SCIP_Bool             varfixing,          /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
11129	   SCIP_VAR*             implvar,            /**< variable y to search for */
11130	   SCIP_Bool             implvarfixing       /**< value of the implied variable to search for */
11131	   )
11132	{
11133	   assert(SCIPvarIsBinary(implvar));
11134	
11135	   return SCIPvarHasImplic(var, varfixing, implvar, implvarfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER);
11136	}
11137	
11138	/** gets the values of b in implications x == varfixing -> y <= b or y >= b in the implication graph;
11139	 *  the values are set to SCIP_INVALID if there is no implied bound
11140	 */
11141	void SCIPvarGetImplicVarBounds(
11142	   SCIP_VAR*             var,                /**< problem variable x */
11143	   SCIP_Bool             varfixing,          /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
11144	   SCIP_VAR*             implvar,            /**< variable y to search for */
11145	   SCIP_Real*            lb,                 /**< buffer to store the value of the implied lower bound */
11146	   SCIP_Real*            ub                  /**< buffer to store the value of the implied upper bound */
11147	   )
11148	{
11149	   int lowerpos;
11150	   int upperpos;
11151	   SCIP_Real* bounds;
11152	
11153	   assert(lb != NULL);
11154	   assert(ub != NULL);
11155	
11156	   *lb = SCIP_INVALID;
11157	   *ub = SCIP_INVALID;
11158	
11159	   if( var->implics == NULL )
11160	      return;
11161	
11162	   SCIPimplicsGetVarImplicPoss(var->implics, varfixing, implvar, &lowerpos, &upperpos);
11163	   bounds = SCIPvarGetImplBounds(var, varfixing);
11164	
11165	   if( bounds == NULL )
11166	      return;
11167	
11168	   if( lowerpos >= 0 )
11169	      *lb = bounds[lowerpos];
11170	
11171	   if( upperpos >= 0 )
11172	      *ub = bounds[upperpos];
11173	}
11174	
11175	
11176	/** fixes the bounds of a binary variable to the given value, counting bound changes and detecting infeasibility */
11177	SCIP_RETCODE SCIPvarFixBinary(
11178	   SCIP_VAR*             var,                /**< problem variable */
11179	   BMS_BLKMEM*           blkmem,             /**< block memory */
11180	   SCIP_SET*             set,                /**< global SCIP settings */
11181	   SCIP_STAT*            stat,               /**< problem statistics */
11182	   SCIP_PROB*            transprob,          /**< transformed problem */
11183	   SCIP_PROB*            origprob,           /**< original problem */
11184	   SCIP_TREE*            tree,               /**< branch and bound tree if in solving stage */
11185	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
11186	   SCIP_LP*              lp,                 /**< current LP data */
11187	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
11188	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
11189	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
11190	   SCIP_Bool             value,              /**< value to fix variable to */
11191	   SCIP_Bool*            infeasible,         /**< pointer to store whether an infeasibility was detected */
11192	   int*                  nbdchgs             /**< pointer to count the number of performed bound changes, or NULL */
11193	   )
11194	{
11195	   assert(var != NULL);
11196	   assert(set != NULL);
11197	   assert(var->scip == set->scip);
11198	   assert(infeasible != NULL);
11199	
11200	   *infeasible = FALSE;
11201	
11202	   if( value == FALSE )
11203	   {
11204	      if( var->glbdom.lb > 0.5 )
11205	         *infeasible = TRUE;
11206	      else if( var->glbdom.ub > 0.5 )
11207	      {
11208	         /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
11209	          * with the local bound, in this case we need to store the bound change as pending bound change
11210	          */
11211	         if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
11212	         {
11213	            assert(tree != NULL);
11214	            assert(transprob != NULL);
11215	            assert(SCIPprobIsTransformed(transprob));
11216	
11217	            SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
11218	                  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
11219	         }
11220	         else
11221	         {
11222	            SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
11223	         }
11224	
11225	         if( nbdchgs != NULL )
11226	            (*nbdchgs)++;
11227	      }
11228	   }
11229	   else
11230	   {
11231	      if( var->glbdom.ub < 0.5 )
11232	         *infeasible = TRUE;
11233	      else if( var->glbdom.lb < 0.5 )
11234	      {
11235	         /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
11236	          * with the local bound, in this case we need to store the bound change as pending bound change
11237	          */
11238	         if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
11239	         {
11240	            assert(tree != NULL);
11241	            assert(transprob != NULL);
11242	            assert(SCIPprobIsTransformed(transprob));
11243	
11244	            SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
11245	                  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
11246	         }
11247	         else
11248	         {
11249	            SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
11250	         }
11251	
11252	         if( nbdchgs != NULL )
11253	            (*nbdchgs)++;
11254	      }
11255	   }
11256	
11257	   /* during presolving, the variable should have been removed immediately from all its cliques */
11258	   assert(SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING || var->cliquelist == NULL);
11259	
11260	   return SCIP_OKAY;
11261	}
11262	
11263	/** adds the variable to the given clique and updates the list of cliques the binary variable is member of;
11264	 *  if the variable now appears twice in the clique with the same value, it is fixed to the opposite value;
11265	 *  if the variable now appears twice in the clique with opposite values, all other variables are fixed to
11266	 *  the opposite of the value they take in the clique
11267	 */
11268	SCIP_RETCODE SCIPvarAddClique(
11269	   SCIP_VAR*             var,                /**< problem variable  */
11270	   BMS_BLKMEM*           blkmem,             /**< block memory */
11271	   SCIP_SET*             set,                /**< global SCIP settings */
11272	   SCIP_STAT*            stat,               /**< problem statistics */
11273	   SCIP_PROB*            transprob,          /**< transformed problem */
11274	   SCIP_PROB*            origprob,           /**< original problem */
11275	   SCIP_TREE*            tree,               /**< branch and bound tree if in solving stage */
11276	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
11277	   SCIP_LP*              lp,                 /**< current LP data */
11278	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
11279	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
11280	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
11281	   SCIP_Bool             value,              /**< value of the variable in the clique */
11282	   SCIP_CLIQUE*          clique,             /**< clique the variable should be added to */
11283	   SCIP_Bool*            infeasible,         /**< pointer to store whether an infeasibility was detected */
11284	   int*                  nbdchgs             /**< pointer to count the number of performed bound changes, or NULL */
11285	   )
11286	{
11287	   assert(var != NULL);
11288	   assert(set != NULL);
11289	   assert(var->scip == set->scip);
11290	   assert(SCIPvarIsBinary(var));
11291	   assert(infeasible != NULL);
11292	
11293	   *infeasible = FALSE;
11294	
11295	   /* get corresponding active problem variable */
11296	   SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
11297	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
11298	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
11299	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED
11300	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
11301	   assert(SCIPvarIsBinary(var));
11302	
11303	   /* only column and loose variables may be member of a clique */
11304	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE )
11305	   {
11306	      SCIP_Bool doubleentry;
11307	      SCIP_Bool oppositeentry;
11308	
11309	      /* add variable to clique */
11310	      SCIP_CALL( SCIPcliqueAddVar(clique, blkmem, set, var, value, &doubleentry, &oppositeentry) );
11311	
11312	      /* add clique to variable's clique list */
11313	      SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
11314	
11315	      /* check consistency of cliquelist */
11316	      SCIPcliquelistCheck(var->cliquelist, var);
11317	
11318	      /* if the variable now appears twice with the same value in the clique, it can be fixed to the opposite value */
11319	      if( doubleentry )
11320	      {
11321	         SCIP_CALL( SCIPvarFixBinary(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
11322	               eventqueue, cliquetable, !value, infeasible, nbdchgs) );
11323	      }
11324	
11325	      /* if the variable appears with both values in the clique, all other variables of the clique can be fixed
11326	       * to the opposite of the value they take in the clique
11327	       */
11328	      if( oppositeentry )
11329	      {
11330	         SCIP_VAR** vars;
11331	         SCIP_Bool* values;
11332	         int nvars;
11333	         int i;
11334	
11335	         nvars = SCIPcliqueGetNVars(clique);
11336	         vars = SCIPcliqueGetVars(clique);
11337	         values = SCIPcliqueGetValues(clique);
11338	         for( i = 0; i < nvars && !(*infeasible); ++i )
11339	         {
11340	            if( vars[i] == var )
11341	               continue;
11342	
11343	            SCIP_CALL( SCIPvarFixBinary(vars[i], blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
11344	                  eventqueue, cliquetable, !values[i], infeasible, nbdchgs) );
11345	         }
11346	      }
11347	   }
11348	
11349	   return SCIP_OKAY;
11350	}
11351	
11352	/** adds a filled clique to the cliquelists of all corresponding variables */
11353	SCIP_RETCODE SCIPvarsAddClique(
11354	   SCIP_VAR**            vars,               /**< problem variables */
11355	   SCIP_Bool*            values,             /**< values of the variables in the clique */
11356	   int                   nvars,              /**< number of problem variables */
11357	   BMS_BLKMEM*           blkmem,             /**< block memory */
11358	   SCIP_SET*             set,                /**< global SCIP settings */
11359	   SCIP_CLIQUE*          clique              /**< clique that contains all given variables and values */
11360	   )
11361	{
11362	   SCIP_VAR* var;
11363	   int v;
11364	
11365	   assert(vars != NULL);
11366	   assert(values != NULL);
11367	   assert(nvars > 0);
11368	   assert(set != NULL);
11369	   assert(blkmem != NULL);
11370	   assert(clique != NULL);
11371	
11372	   for( v = nvars - 1; v >= 0; --v )
11373	   {
11374	      var = vars[v];
11375	      assert(SCIPvarIsBinary(var));
11376	      assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
11377	
11378	      /* add clique to variable's clique list */
11379	      SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, values[v], clique) );
11380	
11381	      /* check consistency of cliquelist */
11382	      SCIPcliquelistCheck(var->cliquelist, var);
11383	   }
11384	
11385	   return SCIP_OKAY;
11386	}
11387	
11388	/** adds a clique to the list of cliques of the given binary variable, but does not change the clique
11389	 *  itself
11390	 */
11391	SCIP_RETCODE SCIPvarAddCliqueToList(
11392	   SCIP_VAR*             var,                /**< problem variable  */
11393	   BMS_BLKMEM*           blkmem,             /**< block memory */
11394	   SCIP_SET*             set,                /**< global SCIP settings */
11395	   SCIP_Bool             value,              /**< value of the variable in the clique */
11396	   SCIP_CLIQUE*          clique              /**< clique that should be removed from the variable's clique list */
11397	   )
11398	{
11399	   assert(var != NULL);
11400	   assert(SCIPvarIsBinary(var));
11401	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
11402	
11403	   /* add clique to variable's clique list */
11404	   SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
11405	
11406	   return SCIP_OKAY;
11407	}
11408	
11409	
11410	/** deletes a clique from the list of cliques the binary variable is member of, but does not change the clique
11411	 *  itself
11412	 */
11413	SCIP_RETCODE SCIPvarDelCliqueFromList(
11414	   SCIP_VAR*             var,                /**< problem variable  */
11415	   BMS_BLKMEM*           blkmem,             /**< block memory */
11416	   SCIP_Bool             value,              /**< value of the variable in the clique */
11417	   SCIP_CLIQUE*          clique              /**< clique that should be removed from the variable's clique list */
11418	   )
11419	{
11420	   assert(var != NULL);
11421	   assert(SCIPvarIsBinary(var));
11422	
11423	   /* delete clique from variable's clique list */
11424	   SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
11425	
11426	   return SCIP_OKAY;
11427	}
11428	
11429	/** deletes the variable from the given clique and updates the list of cliques the binary variable is member of */
11430	SCIP_RETCODE SCIPvarDelClique(
11431	   SCIP_VAR*             var,                /**< problem variable  */
11432	   BMS_BLKMEM*           blkmem,             /**< block memory */
11433	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
11434	   SCIP_Bool             value,              /**< value of the variable in the clique */
11435	   SCIP_CLIQUE*          clique              /**< clique the variable should be removed from */
11436	   )
11437	{
11438	   assert(var != NULL);
11439	   assert(SCIPvarIsBinary(var));
11440	
11441	   /* get corresponding active problem variable */
11442	   SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
11443	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
11444	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
11445	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED
11446	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
11447	   assert(SCIPvarIsBinary(var));
11448	
11449	   /* only column and loose variables may be member of a clique */
11450	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE )
11451	   {
11452	      /* delete clique from variable's clique list */
11453	      SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
11454	
11455	      /* delete variable from clique */
11456	      SCIPcliqueDelVar(clique, cliquetable, var, value);
11457	
11458	      /* check consistency of cliquelist */
11459	      SCIPcliquelistCheck(var->cliquelist, var);
11460	   }
11461	
11462	   return SCIP_OKAY;
11463	}
11464	
11465	/** returns whether there is a clique that contains both given variable/value pairs;
11466	 *  the variables must be active binary variables;
11467	 *  if regardimplics is FALSE, only the cliques in the clique table are looked at;
11468	 *  if regardimplics is TRUE, both the cliques and the implications of the implication graph are regarded
11469	 *
11470	 *  @note a variable with it's negated variable are NOT! in a clique
11471	 *  @note a variable with itself are in a clique
11472	 */
11473	SCIP_Bool SCIPvarsHaveCommonClique(
11474	   SCIP_VAR*             var1,               /**< first variable */
11475	   SCIP_Bool             value1,             /**< value of first variable */
11476	   SCIP_VAR*             var2,               /**< second variable */
11477	   SCIP_Bool             value2,             /**< value of second variable */
11478	   SCIP_Bool             regardimplics       /**< should the implication graph also be searched for a clique? */
11479	   )
11480	{
11481	   assert(var1 != NULL);
11482	   assert(var2 != NULL);
11483	   assert(SCIPvarIsActive(var1));
11484	   assert(SCIPvarIsActive(var2));
11485	   assert(SCIPvarIsBinary(var1));
11486	   assert(SCIPvarIsBinary(var2));
11487	
11488	   return (SCIPcliquelistsHaveCommonClique(var1->cliquelist, value1, var2->cliquelist, value2)
11489	      || (regardimplics && SCIPvarHasImplic(var1, value1, var2, value2 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER)));
11490	}
11491	
11492	/** actually changes the branch factor of the variable and of all parent variables */
11493	static
11494	SCIP_RETCODE varProcessChgBranchFactor(
11495	   SCIP_VAR*             var,                /**< problem variable */
11496	   SCIP_SET*             set,                /**< global SCIP settings */
11497	   SCIP_Real             branchfactor        /**< factor to weigh variable's branching score with */
11498	   )
11499	{
11500	   SCIP_VAR* parentvar;
11501	   SCIP_Real eps;
11502	   int i;
11503	
11504	   assert(var != NULL);
11505	   assert(set != NULL);
11506	   assert(var->scip == set->scip);
11507	
11508	   /* only use positive values */
11509	   eps = SCIPsetEpsilon(set);
11510	   branchfactor = MAX(branchfactor, eps);
11511	
11512	   SCIPsetDebugMsg(set, "process changing branch factor of <%s> from %f to %f\n", var->name, var->branchfactor, branchfactor);
11513	
11514	   if( SCIPsetIsEQ(set, branchfactor, var->branchfactor) )
11515	      return SCIP_OKAY;
11516	
11517	   /* change the branch factor */
11518	   var->branchfactor = branchfactor;
11519	
11520	   /* process parent variables */
11521	   for( i = 0; i < var->nparentvars; ++i )
11522	   {
11523	      parentvar = var->parentvars[i];
11524	      assert(parentvar != NULL);
11525	
11526	      switch( SCIPvarGetStatus(parentvar) )
11527	      {
11528	      case SCIP_VARSTATUS_ORIGINAL:
11529	         /* do not change priorities across the border between transformed and original problem */
11530	         break;
11531	
11532	      case SCIP_VARSTATUS_COLUMN:
11533	      case SCIP_VARSTATUS_LOOSE:
11534	      case SCIP_VARSTATUS_FIXED:
11535	      case SCIP_VARSTATUS_MULTAGGR:
11536	         SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11537	         SCIPABORT();
11538	         return SCIP_INVALIDDATA; /*lint !e527*/
11539	
11540	      case SCIP_VARSTATUS_AGGREGATED:
11541	      case SCIP_VARSTATUS_NEGATED:
11542	         SCIP_CALL( varProcessChgBranchFactor(parentvar, set, branchfactor) );
11543	         break;
11544	
11545	      default:
11546	         SCIPerrorMessage("unknown variable status\n");
11547	         SCIPABORT();
11548	         return SCIP_ERROR; /*lint !e527*/
11549	      }
11550	   }
11551	
11552	   return SCIP_OKAY;
11553	}
11554	
11555	/** sets the branch factor of the variable; this value can be used in the branching methods to scale the score
11556	 *  values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
11557	 */
11558	SCIP_RETCODE SCIPvarChgBranchFactor(
11559	   SCIP_VAR*             var,                /**< problem variable */
11560	   SCIP_SET*             set,                /**< global SCIP settings */
11561	   SCIP_Real             branchfactor        /**< factor to weigh variable's branching score with */
11562	   )
11563	{
11564	   int v;
11565	
11566	   assert(var != NULL);
11567	   assert(set != NULL);
11568	   assert(var->scip == set->scip);
11569	   assert(branchfactor >= 0.0);
11570	
11571	   SCIPdebugMessage("changing branch factor of <%s> from %g to %g\n", var->name, var->branchfactor, branchfactor);
11572	
11573	   if( SCIPsetIsEQ(set, var->branchfactor, branchfactor) )
11574	      return SCIP_OKAY;
11575	
11576	   /* change priorities of attached variables */
11577	   switch( SCIPvarGetStatus(var) )
11578	   {
11579	   case SCIP_VARSTATUS_ORIGINAL:
11580	      if( var->data.original.transvar != NULL )
11581	      {
11582	         SCIP_CALL( SCIPvarChgBranchFactor(var->data.original.transvar, set, branchfactor) );
11583	      }
11584	      else
11585	      {
11586	         assert(set->stage == SCIP_STAGE_PROBLEM);
11587	         var->branchfactor = branchfactor;
11588	      }
11589	      break;
11590	
11591	   case SCIP_VARSTATUS_COLUMN:
11592	   case SCIP_VARSTATUS_LOOSE:
11593	   case SCIP_VARSTATUS_FIXED:
11594	      SCIP_CALL( varProcessChgBranchFactor(var, set, branchfactor) );
11595	      break;
11596	
11597	   case SCIP_VARSTATUS_AGGREGATED:
11598	      assert(!var->donotaggr);
11599	      assert(var->data.aggregate.var != NULL);
11600	      SCIP_CALL( SCIPvarChgBranchFactor(var->data.aggregate.var, set, branchfactor) );
11601	      break;
11602	
11603	   case SCIP_VARSTATUS_MULTAGGR:
11604	      assert(!var->donotmultaggr);
11605	      for( v = 0; v < var->data.multaggr.nvars; ++v )
11606	      {
11607	         SCIP_CALL( SCIPvarChgBranchFactor(var->data.multaggr.vars[v], set, branchfactor) );
11608	      }
11609	      break;
11610	
11611	   case SCIP_VARSTATUS_NEGATED:
11612	      assert(var->negatedvar != NULL);
11613	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
11614	      assert(var->negatedvar->negatedvar == var);
11615	      SCIP_CALL( SCIPvarChgBranchFactor(var->negatedvar, set, branchfactor) );
11616	      break;
11617	
11618	   default:
11619	      SCIPerrorMessage("unknown variable status\n");
11620	      SCIPABORT();
11621	      return SCIP_ERROR; /*lint !e527*/
11622	   }
11623	
11624	   return SCIP_OKAY;
11625	}
11626	
11627	/** actually changes the branch priority of the variable and of all parent variables */
11628	static
11629	SCIP_RETCODE varProcessChgBranchPriority(
11630	   SCIP_VAR*             var,                /**< problem variable */
11631	   int                   branchpriority      /**< branching priority of the variable */
11632	   )
11633	{
11634	   SCIP_VAR* parentvar;
11635	   int i;
11636	
11637	   assert(var != NULL);
11638	
11639	   SCIPdebugMessage("process changing branch priority of <%s> from %d to %d\n", 
11640	      var->name, var->branchpriority, branchpriority);
11641	
11642	   if( branchpriority == var->branchpriority )
11643	      return SCIP_OKAY;
11644	
11645	   /* change the branch priority */
11646	   var->branchpriority = branchpriority;
11647	
11648	   /* process parent variables */
11649	   for( i = 0; i < var->nparentvars; ++i )
11650	   {
11651	      parentvar = var->parentvars[i];
11652	      assert(parentvar != NULL);
11653	
11654	      switch( SCIPvarGetStatus(parentvar) )
11655	      {
11656	      case SCIP_VARSTATUS_ORIGINAL:
11657	         /* do not change priorities across the border between transformed and original problem */
11658	         break;
11659	
11660	      case SCIP_VARSTATUS_COLUMN:
11661	      case SCIP_VARSTATUS_LOOSE:
11662	      case SCIP_VARSTATUS_FIXED:
11663	      case SCIP_VARSTATUS_MULTAGGR:
11664	         SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11665	         SCIPABORT();
11666	         return SCIP_INVALIDDATA; /*lint !e527*/
11667	
11668	      case SCIP_VARSTATUS_AGGREGATED:
11669	      case SCIP_VARSTATUS_NEGATED:
11670	         SCIP_CALL( varProcessChgBranchPriority(parentvar, branchpriority) );
11671	         break;
11672	
11673	      default:
11674	         SCIPerrorMessage("unknown variable status\n");
11675	         return SCIP_ERROR;
11676	      }
11677	   }
11678	
11679	   return SCIP_OKAY;
11680	}
11681	
11682	/** sets the branch priority of the variable; variables with higher branch priority are always preferred to variables
11683	 *  with lower priority in selection of branching variable
11684	 */
11685	SCIP_RETCODE SCIPvarChgBranchPriority(
11686	   SCIP_VAR*             var,                /**< problem variable */
11687	   int                   branchpriority      /**< branching priority of the variable */
11688	   )
11689	{
11690	   int v;
11691	
11692	   assert(var != NULL);
11693	
11694	   SCIPdebugMessage("changing branch priority of <%s> from %d to %d\n", var->name, var->branchpriority, branchpriority);
11695	
11696	   if( var->branchpriority == branchpriority )
11697	      return SCIP_OKAY;
11698	
11699	   /* change priorities of attached variables */
11700	   switch( SCIPvarGetStatus(var) )
11701	   {
11702	   case SCIP_VARSTATUS_ORIGINAL:
11703	      if( var->data.original.transvar != NULL )
11704	      {
11705	         SCIP_CALL( SCIPvarChgBranchPriority(var->data.original.transvar, branchpriority) );
11706	      }
11707	      else
11708	         var->branchpriority = branchpriority;
11709	      break;
11710	
11711	   case SCIP_VARSTATUS_COLUMN:
11712	   case SCIP_VARSTATUS_LOOSE:
11713	   case SCIP_VARSTATUS_FIXED:
11714	      SCIP_CALL( varProcessChgBranchPriority(var, branchpriority) );
11715	      break;
11716	
11717	   case SCIP_VARSTATUS_AGGREGATED:
11718	      assert(!var->donotaggr);
11719	      assert(var->data.aggregate.var != NULL);
11720	      SCIP_CALL( SCIPvarChgBranchPriority(var->data.aggregate.var, branchpriority) );
11721	      break;
11722	
11723	   case SCIP_VARSTATUS_MULTAGGR:
11724	      assert(!var->donotmultaggr);
11725	      for( v = 0; v < var->data.multaggr.nvars; ++v )
11726	      {
11727	         SCIP_CALL( SCIPvarChgBranchPriority(var->data.multaggr.vars[v], branchpriority) );
11728	      }
11729	      break;
11730	
11731	   case SCIP_VARSTATUS_NEGATED:
11732	      assert(var->negatedvar != NULL);
11733	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
11734	      assert(var->negatedvar->negatedvar == var);
11735	      SCIP_CALL( SCIPvarChgBranchPriority(var->negatedvar, branchpriority) );
11736	      break;
11737	
11738	   default:
11739	      SCIPerrorMessage("unknown variable status\n");
11740	      SCIPABORT();
11741	      return SCIP_ERROR; /*lint !e527*/
11742	   }
11743	
11744	   return SCIP_OKAY;
11745	}
11746	
11747	/** actually changes the branch direction of the variable and of all parent variables */
11748	static
11749	SCIP_RETCODE varProcessChgBranchDirection(
11750	   SCIP_VAR*             var,                /**< problem variable */
11751	   SCIP_BRANCHDIR        branchdirection     /**< preferred branch direction of the variable (downwards, upwards, auto) */
11752	   )
11753	{
11754	   SCIP_VAR* parentvar;
11755	   int i;
11756	
11757	   assert(var != NULL);
11758	
11759	   SCIPdebugMessage("process changing branch direction of <%s> from %u to %d\n", 
11760	      var->name, var->branchdirection, branchdirection);
11761	
11762	   if( branchdirection == (SCIP_BRANCHDIR)var->branchdirection )
11763	      return SCIP_OKAY;
11764	
11765	   /* change the branch direction */
11766	   var->branchdirection = branchdirection; /*lint !e641*/
11767	
11768	   /* process parent variables */
11769	   for( i = 0; i < var->nparentvars; ++i )
11770	   {
11771	      parentvar = var->parentvars[i];
11772	      assert(parentvar != NULL);
11773	
11774	      switch( SCIPvarGetStatus(parentvar) )
11775	      {
11776	      case SCIP_VARSTATUS_ORIGINAL:
11777	         /* do not change directions across the border between transformed and original problem */
11778	         break;
11779	
11780	      case SCIP_VARSTATUS_COLUMN:
11781	      case SCIP_VARSTATUS_LOOSE:
11782	      case SCIP_VARSTATUS_FIXED:
11783	      case SCIP_VARSTATUS_MULTAGGR:
11784	         SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11785	         SCIPABORT();
11786	         return SCIP_INVALIDDATA; /*lint !e527*/
11787	
11788	      case SCIP_VARSTATUS_AGGREGATED:
11789	         if( parentvar->data.aggregate.scalar > 0.0 )
11790	         {
11791	            SCIP_CALL( varProcessChgBranchDirection(parentvar, branchdirection) );
11792	         }
11793	         else
11794	         {
11795	            SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11796	         }
11797	         break;
11798	
11799	      case SCIP_VARSTATUS_NEGATED:
11800	         SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11801	         break;
11802	
11803	      default:
11804	         SCIPerrorMessage("unknown variable status\n");
11805	         SCIPABORT();
11806	         return SCIP_ERROR; /*lint !e527*/
11807	      }
11808	   }
11809	
11810	   return SCIP_OKAY;
11811	}
11812	
11813	/** sets the branch direction of the variable; variables with higher branch direction are always preferred to variables
11814	 *  with lower direction in selection of branching variable
11815	 */
11816	SCIP_RETCODE SCIPvarChgBranchDirection(
11817	   SCIP_VAR*             var,                /**< problem variable */
11818	   SCIP_BRANCHDIR        branchdirection     /**< preferred branch direction of the variable (downwards, upwards, auto) */
11819	   )
11820	{
11821	   int v;
11822	
11823	   assert(var != NULL);
11824	
11825	   SCIPdebugMessage("changing branch direction of <%s> from %u to %d\n", var->name, var->branchdirection, branchdirection);
11826	
11827	   if( (SCIP_BRANCHDIR)var->branchdirection == branchdirection )
11828	      return SCIP_OKAY;
11829	
11830	   /* change directions of attached variables */
11831	   switch( SCIPvarGetStatus(var) )
11832	   {
11833	   case SCIP_VARSTATUS_ORIGINAL:
11834	      if( var->data.original.transvar != NULL )
11835	      {
11836	         SCIP_CALL( SCIPvarChgBranchDirection(var->data.original.transvar, branchdirection) );
11837	      }
11838	      else
11839	         var->branchdirection = branchdirection; /*lint !e641*/
11840	      break;
11841	
11842	   case SCIP_VARSTATUS_COLUMN:
11843	   case SCIP_VARSTATUS_LOOSE:
11844	   case SCIP_VARSTATUS_FIXED:
11845	      SCIP_CALL( varProcessChgBranchDirection(var, branchdirection) );
11846	      break;
11847	
11848	   case SCIP_VARSTATUS_AGGREGATED:
11849	      assert(!var->donotaggr);
11850	      assert(var->data.aggregate.var != NULL);
11851	      if( var->data.aggregate.scalar > 0.0 )
11852	      {
11853	         SCIP_CALL( SCIPvarChgBranchDirection(var->data.aggregate.var, branchdirection) );
11854	      }
11855	      else
11856	      {
11857	         SCIP_CALL( SCIPvarChgBranchDirection(var->data.aggregate.var, SCIPbranchdirOpposite(branchdirection)) );
11858	      }
11859	      break;
11860	
11861	   case SCIP_VARSTATUS_MULTAGGR:
11862	      assert(!var->donotmultaggr);
11863	      for( v = 0; v < var->data.multaggr.nvars; ++v )
11864	      {
11865	         /* only update branching direction of aggregation variables, if they don't have a preferred direction yet */
11866	         assert(var->data.multaggr.vars[v] != NULL);
11867	         if( (SCIP_BRANCHDIR)var->data.multaggr.vars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
11868	         {
11869	            if( var->data.multaggr.scalars[v] > 0.0 )
11870	            {
11871	               SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], branchdirection) );
11872	            }
11873	            else
11874	            {
11875	               SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], SCIPbranchdirOpposite(branchdirection)) );
11876	            }
11877	         }
11878	      }
11879	      break;
11880	
11881	   case SCIP_VARSTATUS_NEGATED:
11882	      assert(var->negatedvar != NULL);
11883	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
11884	      assert(var->negatedvar->negatedvar == var);
11885	      SCIP_CALL( SCIPvarChgBranchDirection(var->negatedvar, SCIPbranchdirOpposite(branchdirection)) );
11886	      break;
11887	
11888	   default:
11889	      SCIPerrorMessage("unknown variable status\n");
11890	      SCIPABORT();
11891	      return SCIP_ERROR; /*lint !e527*/
11892	   }
11893	
11894	   return SCIP_OKAY;
11895	}
11896	
11897	/** compares the index of two variables, only active, fixed or negated variables are allowed, if a variable
11898	 *  is negated then the index of the corresponding active variable is taken, returns -1 if first is
11899	 *  smaller than, and +1 if first is greater than second variable index; returns 0 if both indices
11900	 *  are equal, which means both variables are equal
11901	 */
11902	int SCIPvarCompareActiveAndNegated(
11903	   SCIP_VAR*             var1,               /**< first problem variable */
11904	   SCIP_VAR*             var2                /**< second problem variable */
11905	   )
11906	{
11907	   assert(var1 != NULL);
11908	   assert(var2 != NULL);
11909	   assert(SCIPvarIsActive(var1) || SCIPvarGetStatus(var1) == SCIP_VARSTATUS_NEGATED || SCIPvarGetStatus(var1) == SCIP_VARSTATUS_FIXED);
11910	   assert(SCIPvarIsActive(var2) || SCIPvarGetStatus(var2) == SCIP_VARSTATUS_NEGATED || SCIPvarGetStatus(var2) == SCIP_VARSTATUS_FIXED);
11911	
11912	   if( SCIPvarGetStatus(var1) == SCIP_VARSTATUS_NEGATED )
11913	      var1 = SCIPvarGetNegatedVar(var1);
11914	   if( SCIPvarGetStatus(var2) == SCIP_VARSTATUS_NEGATED )
11915	      var2 = SCIPvarGetNegatedVar(var2);
11916	
11917	   assert(var1 != NULL);
11918	   assert(var2 != NULL);
11919	
11920	   if( SCIPvarGetIndex(var1) < SCIPvarGetIndex(var2) )
11921	      return -1;
11922	   else if( SCIPvarGetIndex(var1) > SCIPvarGetIndex(var2) )
11923	      return +1;
11924	
11925	   assert(var1 == var2);
11926	   return 0;
11927	}
11928	
11929	/** comparison method for sorting active and negated variables by non-decreasing index, active and negated 
11930	 *  variables are handled as the same variables
11931	 */
11932	SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
11933	{
11934	   return SCIPvarCompareActiveAndNegated((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11935	}
11936	
11937	/** compares the index of two variables, returns -1 if first is smaller than, and +1 if first is greater than second
11938	 *  variable index; returns 0 if both indices are equal, which means both variables are equal
11939	 */
11940	int SCIPvarCompare(
11941	   SCIP_VAR*             var1,               /**< first problem variable */
11942	   SCIP_VAR*             var2                /**< second problem variable */
11943	   )
11944	{
11945	   assert(var1 != NULL);
11946	   assert(var2 != NULL);
11947	
11948	   if( var1->index < var2->index )
11949	      return -1;
11950	   else if( var1->index > var2->index )
11951	      return +1;
11952	   else
11953	   {
11954	      assert(var1 == var2);
11955	      return 0;
11956	   }
11957	}
11958	
11959	/** comparison method for sorting variables by non-decreasing index */
11960	SCIP_DECL_SORTPTRCOMP(SCIPvarComp)
11961	{
11962	   return SCIPvarCompare((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11963	}
11964	
11965	/** comparison method for sorting variables by non-decreasing objective coefficient */
11966	SCIP_DECL_SORTPTRCOMP(SCIPvarCompObj)
11967	{
11968	   SCIP_Real obj1;
11969	   SCIP_Real obj2;
11970	
11971	   obj1 = SCIPvarGetObj((SCIP_VAR*)elem1);
11972	   obj2 = SCIPvarGetObj((SCIP_VAR*)elem2);
11973	
11974	   if( obj1 < obj2 )
11975	      return -1;
11976	   else if( obj1 > obj2 )
11977	      return +1;
11978	   else
11979	      return 0;
11980	}
11981	
11982	/** hash key retrieval function for variables */
11983	SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
11984	{  /*lint --e{715}*/
11985	   return elem;
11986	}
11987	
11988	/** returns TRUE iff the indices of both variables are equal */
11989	SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
11990	{  /*lint --e{715}*/
11991	   if( key1 == key2 )
11992	      return TRUE;
11993	   return FALSE;
11994	}
11995	
11996	/** returns the hash value of the key */
11997	SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
11998	{  /*lint --e{715}*/
11999	   assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
12000	   return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
12001	}
12002	
12003	/** return for given variables all their active counterparts; all active variables will be pairwise different */
12004	SCIP_RETCODE SCIPvarsGetActiveVars(
12005	   SCIP_SET*             set,                /**< global SCIP settings */
12006	   SCIP_VAR**            vars,               /**< variable array with given variables and as output all active
12007						      *   variables, if enough slots exist
12008						      */
12009	   int*                  nvars,              /**< number of given variables, and as output number of active variables,
12010						      *   if enough slots exist
12011						      */
12012	   int                   varssize,           /**< available slots in vars array */
12013	   int*                  requiredsize        /**< pointer to store the required array size for the active variables */
12014	   )
12015	{
12016	   SCIP_VAR** activevars;
12017	   int nactivevars;
12018	   int activevarssize;
12019	
12020	   SCIP_VAR* var;
12021	   int v;
12022	
12023	   SCIP_VAR** tmpvars;
12024	   SCIP_VAR** multvars;
12025	   int tmpvarssize;
12026	   int ntmpvars;
12027	   int noldtmpvars;
12028	   int nmultvars;
12029	
12030	   assert(set != NULL);
12031	   assert(nvars != NULL);
12032	   assert(vars != NULL || *nvars == 0);
12033	   assert(varssize >= *nvars);
12034	   assert(requiredsize != NULL);
12035	
12036	   *requiredsize = 0;
12037	
12038	   if( *nvars == 0 )
12039	      return SCIP_OKAY;
12040	
12041	   nactivevars = 0;
12042	   activevarssize = *nvars;
12043	   ntmpvars = *nvars;
12044	   tmpvarssize = *nvars;
12045	
12046	   /* temporary memory */
12047	   SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
12048	   /* coverity[copy_paste_error] */
12049	   SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
12050	
12051	   noldtmpvars = ntmpvars;
12052	
12053	   /* sort all variables to combine equal variables easily */
12054	   SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12055	   for( v = ntmpvars - 1; v > 0; --v )
12056	   {
12057	      /* combine same variables */
12058	      if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
12059	      {
12060	         --ntmpvars;
12061	         tmpvars[v] = tmpvars[ntmpvars];
12062	      }
12063	   }
12064	   /* sort all variables again to combine equal variables later on */
12065	   if( noldtmpvars > ntmpvars )
12066	      SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12067	
12068	   /* collect for each variable the representation in active variables */
12069	   while( ntmpvars >= 1 )
12070	   {
12071	      --ntmpvars;
12072	      var = tmpvars[ntmpvars];
12073	      assert( var != NULL );
12074	
12075	      switch( SCIPvarGetStatus(var) )
12076	      {
12077	      case SCIP_VARSTATUS_ORIGINAL:
12078		 if( var->data.original.transvar == NULL )
12079		 {
12080		    SCIPerrorMessage("original variable has no transformed variable attached\n");
12081		    SCIPABORT();
12082		    return SCIP_INVALIDDATA; /*lint !e527*/
12083		 }
12084		 tmpvars[ntmpvars] = var->data.original.transvar;
12085		 ++ntmpvars;
12086		 break;
12087	
12088	      case SCIP_VARSTATUS_AGGREGATED:
12089		 tmpvars[ntmpvars] = var->data.aggregate.var;
12090		 ++ntmpvars;
12091		 break;
12092	
12093	      case SCIP_VARSTATUS_NEGATED:
12094		 tmpvars[ntmpvars] = var->negatedvar;
12095		 ++ntmpvars;
12096		 break;
12097	
12098	      case SCIP_VARSTATUS_LOOSE:
12099	      case SCIP_VARSTATUS_COLUMN:
12100		 /* check for space in temporary memory */
12101	         if( nactivevars >= activevarssize )
12102	         {
12103	            activevarssize *= 2;
12104	            SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
12105	            assert(nactivevars < activevarssize);
12106	         }
12107	         activevars[nactivevars] = var;
12108	         nactivevars++;
12109	         break;
12110	
12111	      case SCIP_VARSTATUS_MULTAGGR:
12112	         /* x = a_1*y_1 + ... + a_n*y_n + c */
12113	         nmultvars = var->data.multaggr.nvars;
12114	         multvars = var->data.multaggr.vars;
12115	
12116		 /* check for space in temporary memory */
12117	         if( nmultvars + ntmpvars > tmpvarssize )
12118	         {
12119	            while( nmultvars + ntmpvars > tmpvarssize )
12120	               tmpvarssize *= 2;
12121	            SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
12122	            assert(nmultvars + ntmpvars <= tmpvarssize);
12123	         }
12124	
12125		 /* copy all multi-aggregation variables into our working array */
12126		 BMScopyMemoryArray(&tmpvars[ntmpvars], multvars, nmultvars); /*lint !e866*/
12127	
12128		 /* get active, fixed or multi-aggregated corresponding variables for all new ones */
12129		 SCIPvarsGetProbvar(&tmpvars[ntmpvars], nmultvars);
12130	
12131		 ntmpvars += nmultvars;
12132		 noldtmpvars = ntmpvars;
12133	
12134		 /* sort all variables to combine equal variables easily */
12135		 SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12136		 for( v = ntmpvars - 1; v > 0; --v )
12137		 {
12138		    /* combine same variables */
12139		    if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
12140		    {
12141		       --ntmpvars;
12142		       tmpvars[v] = tmpvars[ntmpvars];
12143		    }
12144		 }
12145		 /* sort all variables again to combine equal variables later on */
12146		 if( noldtmpvars > ntmpvars )
12147		    SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12148	
12149	         break;
12150	
12151	      case SCIP_VARSTATUS_FIXED:
12152		 /* no need for memorizing fixed variables */
12153	         break;
12154	
12155	      default:
12156		 SCIPerrorMessage("unknown variable status\n");
12157	         SCIPABORT();
12158		 return SCIP_INVALIDDATA; /*lint !e527*/
12159	      }
12160	   }
12161	
12162	   /* sort variable array by variable index */
12163	   SCIPsortPtr((void**)activevars, SCIPvarComp, nactivevars);
12164	
12165	   /* eliminate duplicates and count required size */
12166	   v = nactivevars - 1;
12167	   while( v > 0 )
12168	   {
12169	      /* combine both variable since they are the same */
12170	      if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
12171	      {
12172		 --nactivevars;
12173		 activevars[v] = activevars[nactivevars];
12174	      }
12175	      --v;
12176	   }
12177	   *requiredsize = nactivevars;
12178	
12179	   if( varssize >= *requiredsize )
12180	   {
12181	      assert(vars != NULL);
12182	
12183	      *nvars = *requiredsize;
12184	      BMScopyMemoryArray(vars, activevars, nactivevars);
12185	   }
12186	
12187	   SCIPsetFreeBufferArray(set, &tmpvars);
12188	   SCIPsetFreeBufferArray(set, &activevars);
12189	
12190	   return SCIP_OKAY;
12191	}
12192	
12193	/** gets corresponding active, fixed, or multi-aggregated problem variables of given variables,
12194	 *  @note the content of the given array will/might change
12195	 */
12196	void SCIPvarsGetProbvar(
12197	   SCIP_VAR**            vars,               /**< array of problem variables */
12198	   int                   nvars               /**< number of variables */
12199	   )
12200	{
12201	   int v;
12202	
12203	   assert(vars != NULL || nvars == 0);
12204	
12205	   for( v = nvars - 1; v >= 0; --v )
12206	   {
12207	      assert(vars != NULL);
12208	      assert(vars[v] != NULL);
12209	
12210	      vars[v] = SCIPvarGetProbvar(vars[v]);
12211	      assert(vars[v] != NULL);
12212	   }
12213	}
12214	
12215	/** gets corresponding active, fixed, or multi-aggregated problem variable of a variable */
12216	SCIP_VAR* SCIPvarGetProbvar(
12217	   SCIP_VAR*             var                 /**< problem variable */
12218	   )
12219	{
12220	   SCIP_VAR* retvar;
12221	
12222	   assert(var != NULL);
12223	
12224	   retvar = var;
12225	
12226	   SCIPdebugMessage("get problem variable of <%s>\n", var->name);
12227	
12228	   while( TRUE ) /*lint !e716 */
12229	   {
12230	      assert(retvar != NULL);
12231	
12232	      switch( SCIPvarGetStatus(retvar) )
12233	      {
12234	      case SCIP_VARSTATUS_ORIGINAL:
12235		 if( retvar->data.original.transvar == NULL )
12236		 {
12237		    SCIPerrorMessage("original variable has no transformed variable attached\n");
12238		    SCIPABORT();
12239		    return NULL; /*lint !e527 */
12240		 }
12241		 retvar = retvar->data.original.transvar;
12242		 break;
12243	
12244	      case SCIP_VARSTATUS_LOOSE:
12245	      case SCIP_VARSTATUS_COLUMN:
12246	      case SCIP_VARSTATUS_FIXED:
12247		 return retvar;
12248	
12249	      case SCIP_VARSTATUS_MULTAGGR:
12250		 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12251		 if ( retvar->data.multaggr.nvars == 1 )
12252		    retvar = retvar->data.multaggr.vars[0];
12253		 else
12254		    return retvar;
12255		 break;
12256	
12257	      case SCIP_VARSTATUS_AGGREGATED:
12258		 retvar = retvar->data.aggregate.var;
12259		 break;
12260	
12261	      case SCIP_VARSTATUS_NEGATED:
12262		 retvar = retvar->negatedvar;
12263		 break;
12264	
12265	      default:
12266		 SCIPerrorMessage("unknown variable status\n");
12267		 SCIPABORT();
12268		 return NULL; /*lint !e527*/
12269	      }
12270	   }
12271	}
12272	
12273	/** gets corresponding active, fixed, or multi-aggregated problem variables of binary variables and updates the given
12274	 *  negation status of each variable
12275	 */
12276	SCIP_RETCODE SCIPvarsGetProbvarBinary(
12277	   SCIP_VAR***           vars,               /**< pointer to binary problem variables */
12278	   SCIP_Bool**           negatedarr,         /**< pointer to corresponding array to update the negation status */
12279	   int                   nvars               /**< number of variables and values in vars and negated array */
12280	   )
12281	{
12282	   SCIP_VAR** var;
12283	   SCIP_Bool* negated;
12284	   int v;
12285	
12286	   assert(vars != NULL);
12287	   assert(*vars != NULL || nvars == 0);
12288	   assert(negatedarr != NULL);
12289	   assert(*negatedarr != NULL || nvars == 0);
12290	
12291	   for( v = nvars - 1; v >= 0; --v )
12292	   {
12293	      var = &((*vars)[v]);
12294	      negated = &((*negatedarr)[v]);
12295	
12296	      /* get problem variable */
12297	      SCIP_CALL( SCIPvarGetProbvarBinary(var, negated) );
12298	   }
12299	
12300	   return SCIP_OKAY;
12301	}
12302	
12303	
12304	/** gets corresponding active, fixed, or multi-aggregated problem variable of a binary variable and updates the given
12305	 *  negation status (this means you have to assign a value to SCIP_Bool negated before calling this method, usually
12306	 *  FALSE is used)
12307	 */
12308	SCIP_RETCODE SCIPvarGetProbvarBinary(
12309	   SCIP_VAR**            var,                /**< pointer to binary problem variable */
12310	   SCIP_Bool*            negated             /**< pointer to update the negation status */
12311	   )
12312	{
12313	   SCIP_Bool active = FALSE;
12314	#ifndef NDEBUG
12315	   SCIP_Real constant = 0.0;
12316	   SCIP_Bool orignegated;
12317	#endif
12318	
12319	   assert(var != NULL);
12320	   assert(*var != NULL);
12321	   assert(negated != NULL);
12322	   assert(SCIPvarIsBinary(*var));
12323	
12324	#ifndef NDEBUG
12325	   orignegated = *negated;
12326	#endif
12327	
12328	   while( !active && *var != NULL )
12329	   {
12330	      switch( SCIPvarGetStatus(*var) )
12331	      {
12332	      case SCIP_VARSTATUS_ORIGINAL:
12333	         if( (*var)->data.original.transvar == NULL )
12334	            return SCIP_OKAY;
12335	         *var = (*var)->data.original.transvar;
12336	         break;
12337	
12338	      case SCIP_VARSTATUS_LOOSE:
12339	      case SCIP_VARSTATUS_COLUMN:
12340	      case SCIP_VARSTATUS_FIXED:
12341	         active = TRUE;
12342	         break;
12343	
12344	      case SCIP_VARSTATUS_MULTAGGR:
12345	         /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12346	         if ( (*var)->data.multaggr.nvars == 1 )
12347	         {
12348	            assert( (*var)->data.multaggr.vars != NULL );
12349	            assert( (*var)->data.multaggr.scalars != NULL );
12350	            assert( SCIPvarIsBinary((*var)->data.multaggr.vars[0]) );
12351	            assert(!EPSZ((*var)->data.multaggr.scalars[0], 1e-06));
12352	
12353	            /* if not all variables were fully propagated, it might happen that a variable is multi-aggregated to
12354	             * another variable which needs to be fixed
12355	             *
12356	             * e.g. x = y - 1 => (x = 0 && y = 1)
12357	             * e.g. x = y + 1 => (x = 1 && y = 0)
12358	             *
12359	             * is this special case we need to return the muti-aggregation
12360	             */
12361	            if( EPSEQ((*var)->data.multaggr.constant, -1.0, 1e-06) || (EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06) && EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06)) )
12362	            {
12363	               assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06));
12364	            }
12365	            else
12366	            {
12367	               /* @note due to fixations, a multi-aggregation can have a constant of zero and a negative scalar or even
12368	                *       a scalar in absolute value unequal to one, in this case this aggregation variable needs to be
12369	                *       fixed to zero, but this should be done by another enforcement; so not depending on the scalar,
12370	                *       we will return the aggregated variable;
12371	                */
12372	               if( !EPSEQ(REALABS((*var)->data.multaggr.scalars[0]), 1.0, 1e-06) )
12373	               {
12374	                  active = TRUE;
12375	                  break;
12376	               }
12377	
12378	               /* @note it may also happen that the constant is larger than 1 or smaller than 0, in that case the
12379	                *       aggregation variable needs to be fixed to one, but this should be done by another enforcement;
12380	                *       so if this is the case, we will return the aggregated variable
12381	                */
12382	               assert(EPSZ((*var)->data.multaggr.constant, 1e-06) || EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06)
12383	                  || EPSZ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1e-06)
12384	                  || EPSEQ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1.0, 1e-06));
12385	
12386	               if( !EPSZ((*var)->data.multaggr.constant, 1e-06) && !EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06) )
12387	               {
12388	                  active = TRUE;
12389	                  break;
12390	               }
12391	
12392	               assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06) || EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
12393	
12394	               if( EPSZ((*var)->data.multaggr.constant, 1e-06) )
12395	               {
12396	                  /* if the scalar is negative, either the aggregation variable is already fixed to zero or has at
12397	                   * least one uplock (that hopefully will enforce this fixation to zero); can it happen that this
12398	                   * variable itself is multi-aggregated again?
12399	                   */
12400	                  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06) ?
12401	                     ((SCIPvarGetUbGlobal((*var)->data.multaggr.vars[0]) < 0.5) ||
12402	                        SCIPvarGetNLocksUpType((*var)->data.multaggr.vars[0], SCIP_LOCKTYPE_MODEL) > 0) : TRUE);
12403	               }
12404	               else
12405	               {
12406	                  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
12407	#ifndef NDEBUG
12408	                  constant += (*negated) != orignegated ? -1.0 : 1.0;
12409	#endif
12410	
12411	                  *negated = !(*negated);
12412	               }
12413	               *var = (*var)->data.multaggr.vars[0];
12414	               break;
12415	            }
12416	         }
12417	         active = TRUE;  /*lint !e838*/
12418	         break;
12419	
12420	      case SCIP_VARSTATUS_AGGREGATED:  /* x = a'*x' + c'  =>  a*x + c == (a*a')*x' + (a*c' + c) */
12421	         assert((*var)->data.aggregate.var != NULL);
12422	         assert(EPSEQ((*var)->data.aggregate.scalar, 1.0, 1e-06) || EPSEQ((*var)->data.aggregate.scalar, -1.0, 1e-06));
12423	         assert(EPSLE((*var)->data.aggregate.var->glbdom.ub - (*var)->data.aggregate.var->glbdom.lb, 1.0, 1e-06));
12424	#ifndef NDEBUG
12425	         constant += (*negated) != orignegated ? -(*var)->data.aggregate.constant : (*var)->data.aggregate.constant;
12426	#endif
12427	
12428	         *negated = ((*var)->data.aggregate.scalar > 0.0) ? *negated : !(*negated);
12429	         *var = (*var)->data.aggregate.var;
12430	         break;
12431	
12432	      case SCIP_VARSTATUS_NEGATED:     /* x =  - x' + c'  =>  a*x + c ==   (-a)*x' + (a*c' + c) */
12433	         assert((*var)->negatedvar != NULL);
12434	#ifndef NDEBUG
12435	         constant += (*negated) != orignegated ? -1.0 : 1.0;
12436	#endif
12437	
12438	         *negated = !(*negated);
12439	         *var = (*var)->negatedvar;
12440	         break;
12441	
12442	      default:
12443	         SCIPerrorMessage("unknown variable status\n");
12444	         return SCIP_INVALIDDATA;
12445	      }
12446	   }
12447	   assert(active == (*var != NULL));
12448	
12449	   if( active )
12450	   {
12451	      assert(SCIPvarIsBinary(*var));
12452	      assert(EPSZ(constant, 1e-06) || EPSEQ(constant, 1.0, 1e-06));
12453	      assert(EPSZ(constant, 1e-06) == ((*negated) == orignegated));
12454	
12455	      return SCIP_OKAY;
12456	   }
12457	   else
12458	   {
12459	      SCIPerrorMessage("active variable path leads to NULL pointer\n");
12460	      return SCIP_INVALIDDATA;
12461	   }
12462	}
12463	
12464	/** transforms given variable, boundtype and bound to the corresponding active, fixed, or multi-aggregated variable
12465	 *  values
12466	 */
12467	SCIP_RETCODE SCIPvarGetProbvarBound(
12468	   SCIP_VAR**            var,                /**< pointer to problem variable */
12469	   SCIP_Real*            bound,              /**< pointer to bound value to transform */
12470	   SCIP_BOUNDTYPE*       boundtype           /**< pointer to type of bound: lower or upper bound */
12471	   )
12472	{
12473	   assert(var != NULL);
12474	   assert(*var != NULL);
12475	   assert(bound != NULL);
12476	   assert(boundtype != NULL);
12477	
12478	   SCIPdebugMessage("get probvar bound %g of type %d of variable <%s>\n", *bound, *boundtype, (*var)->name);
12479	
12480	   switch( SCIPvarGetStatus(*var) )
12481	   {
12482	   case SCIP_VARSTATUS_ORIGINAL:
12483	      if( (*var)->data.original.transvar == NULL )
12484	      {
12485	         SCIPerrorMessage("original variable has no transformed variable attached\n");
12486	         return SCIP_INVALIDDATA;
12487	      }
12488	      *var = (*var)->data.original.transvar;
12489	      SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12490	      break;
12491	
12492	   case SCIP_VARSTATUS_LOOSE:
12493	   case SCIP_VARSTATUS_COLUMN:
12494	   case SCIP_VARSTATUS_FIXED:
12495	      break;
12496	
12497	   case SCIP_VARSTATUS_MULTAGGR:
12498	      /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12499	      if ( (*var)->data.multaggr.nvars == 1 )
12500	      {
12501	         assert( (*var)->data.multaggr.vars != NULL );
12502	         assert( (*var)->data.multaggr.scalars != NULL );
12503	         assert( (*var)->data.multaggr.scalars[0] != 0.0 );
12504	
12505	         (*bound) /= (*var)->data.multaggr.scalars[0];
12506	         (*bound) -= (*var)->data.multaggr.constant/(*var)->data.multaggr.scalars[0];
12507	         if ( (*var)->data.multaggr.scalars[0] < 0.0 )
12508	         {
12509	            if ( *boundtype == SCIP_BOUNDTYPE_LOWER )
12510	               *boundtype = SCIP_BOUNDTYPE_UPPER;
12511	            else
12512	               *boundtype = SCIP_BOUNDTYPE_LOWER;
12513	         }
12514	         *var = (*var)->data.multaggr.vars[0];
12515	         SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12516	      }
12517	      break;
12518	
12519	   case SCIP_VARSTATUS_AGGREGATED:  /* x = a*y + c  ->  y = x/a - c/a */
12520	      assert((*var)->data.aggregate.var != NULL);
12521	      assert((*var)->data.aggregate.scalar != 0.0);
12522	
12523	      (*bound) /= (*var)->data.aggregate.scalar;
12524	      (*bound) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12525	      if( (*var)->data.aggregate.scalar < 0.0 )
12526	      {
12527	         if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12528	            *boundtype = SCIP_BOUNDTYPE_UPPER;
12529	         else
12530	            *boundtype = SCIP_BOUNDTYPE_LOWER;
12531	      }
12532	      *var = (*var)->data.aggregate.var;
12533	      SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12534	      break;
12535	
12536	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
12537	      assert((*var)->negatedvar != NULL);
12538	      assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12539	      assert((*var)->negatedvar->negatedvar == *var);
12540	      (*bound) = (*var)->data.negate.constant - *bound;
12541	      if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12542	         *boundtype = SCIP_BOUNDTYPE_UPPER;
12543	      else
12544	         *boundtype = SCIP_BOUNDTYPE_LOWER;
12545	      *var = (*var)->negatedvar;
12546	      SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12547	      break;
12548	
12549	   default:
12550	      SCIPerrorMessage("unknown variable status\n");
12551	      return SCIP_INVALIDDATA;
12552	   }
12553	
12554	   return SCIP_OKAY;
12555	}
12556	
12557	/** transforms given variable and domain hole to the corresponding active, fixed, or multi-aggregated variable
12558	 *  values
12559	 */
12560	SCIP_RETCODE SCIPvarGetProbvarHole(
12561	   SCIP_VAR**            var,                /**< pointer to problem variable */
12562	   SCIP_Real*            left,               /**< pointer to left bound of open interval in hole to transform */
12563	   SCIP_Real*            right               /**< pointer to right bound of open interval in hole to transform */
12564	   )
12565	{
12566	   assert(var != NULL);
12567	   assert(*var != NULL);
12568	   assert(left != NULL);
12569	   assert(right != NULL);
12570	
12571	   SCIPdebugMessage("get probvar hole (%g,%g) of variable <%s>\n", *left, *right, (*var)->name);
12572	
12573	   switch( SCIPvarGetStatus(*var) )
12574	   {
12575	   case SCIP_VARSTATUS_ORIGINAL:
12576	      if( (*var)->data.original.transvar == NULL )
12577	      {
12578	         SCIPerrorMessage("original variable has no transformed variable attached\n");
12579	         return SCIP_INVALIDDATA;
12580	      }
12581	      *var = (*var)->data.original.transvar;
12582	      SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12583	      break;
12584	
12585	   case SCIP_VARSTATUS_LOOSE:
12586	   case SCIP_VARSTATUS_COLUMN:
12587	   case SCIP_VARSTATUS_FIXED:
12588	   case SCIP_VARSTATUS_MULTAGGR:
12589	      break;
12590	
12591	   case SCIP_VARSTATUS_AGGREGATED:  /* x = a*y + c  ->  y = x/a - c/a */
12592	      assert((*var)->data.aggregate.var != NULL);
12593	      assert((*var)->data.aggregate.scalar != 0.0);
12594	
12595	      /* scale back */
12596	      (*left) /= (*var)->data.aggregate.scalar;
12597	      (*right) /= (*var)->data.aggregate.scalar;
12598	
12599	      /* shift back */
12600	      (*left) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12601	      (*right) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12602	
12603	      *var = (*var)->data.aggregate.var;
12604	
12605	      /* check if the  interval bounds have to swapped */
12606	      if( (*var)->data.aggregate.scalar < 0.0 )
12607	      {
12608	         SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12609	      }
12610	      else
12611	      {
12612	         SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12613	      }
12614	      break;
12615	
12616	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
12617	      assert((*var)->negatedvar != NULL);
12618	      assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12619	      assert((*var)->negatedvar->negatedvar == *var);
12620	
12621	      /* shift and scale back */
12622	      (*left) = (*var)->data.negate.constant - (*left);
12623	      (*right) = (*var)->data.negate.constant - (*right);
12624	
12625	      *var = (*var)->negatedvar;
12626	
12627	      /* through the negated variable the left and right interval bound have to swapped */
12628	      SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12629	      break;
12630	
12631	   default:
12632	      SCIPerrorMessage("unknown variable status\n");
12633	      return SCIP_INVALIDDATA;
12634	   }
12635	
12636	   return SCIP_OKAY;
12637	}
12638	
12639	/** transforms given variable, scalar and constant to the corresponding active, fixed, or
12640	 *  multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable,
12641	 *  "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation
12642	 *  with only one active variable (this can happen due to fixings after the multi-aggregation),
12643	 *  is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0
12644	 */
12645	SCIP_RETCODE SCIPvarGetProbvarSum(
12646	   SCIP_VAR**            var,                /**< pointer to problem variable x in sum a*x + c */
12647	   SCIP_SET*             set,                /**< global SCIP settings */
12648	   SCIP_Real*            scalar,             /**< pointer to scalar a in sum a*x + c */
12649	   SCIP_Real*            constant            /**< pointer to constant c in sum a*x + c */
12650	   )
12651	{
12652	   assert(var != NULL);
12653	   assert(scalar != NULL);
12654	   assert(constant != NULL);
12655	
12656	   while( *var != NULL )
12657	   {
12658	      switch( SCIPvarGetStatus(*var) )
12659	      {
12660	      case SCIP_VARSTATUS_ORIGINAL:
12661	         if( (*var)->data.original.transvar == NULL )
12662	         {
12663	            SCIPerrorMessage("original variable has no transformed variable attached\n");
12664	            return SCIP_INVALIDDATA;
12665	         }
12666	         *var = (*var)->data.original.transvar;
12667	         break;
12668	
12669	      case SCIP_VARSTATUS_LOOSE:
12670	      case SCIP_VARSTATUS_COLUMN:
12671	         return SCIP_OKAY;
12672	
12673	      case SCIP_VARSTATUS_FIXED:       /* x = c'          =>  a*x + c ==             (a*c' + c) */
12674	         if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12675	         {
12676	            if( SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)) )
12677	            {
12678	               assert(*scalar != 0.0);
12679	               if( (*scalar) * (*var)->glbdom.lb > 0.0 )
12680	                  (*constant) = SCIPsetInfinity(set);
12681	               else
12682	                  (*constant) = -SCIPsetInfinity(set);
12683	            }
12684	            else
12685	               (*constant) += *scalar * (*var)->glbdom.lb;
12686	         }
12687	#ifndef NDEBUG
12688	         else
12689	         {
12690	            assert(!SCIPsetIsInfinity(set, (*constant)) || !((*scalar) * (*var)->glbdom.lb < 0.0 &&
12691	                  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12692	            assert(!SCIPsetIsInfinity(set, -(*constant)) || !((*scalar) * (*var)->glbdom.lb > 0.0 &&
12693	                  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12694	         }
12695	#endif
12696	         *scalar = 0.0;
12697	         return SCIP_OKAY;
12698	
12699	      case SCIP_VARSTATUS_MULTAGGR:
12700	         /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12701	         if ( (*var)->data.multaggr.nvars == 1 )
12702	         {
12703	            assert((*var)->data.multaggr.vars != NULL);
12704	            assert((*var)->data.multaggr.scalars != NULL);
12705	            assert((*var)->data.multaggr.vars[0] != NULL);
12706	            if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12707	            {
12708	               /* the multi-aggregation constant can be infinite, if one of the multi-aggregation variables
12709	                * was fixed to +/-infinity; ensure that the constant is set to +/-infinity, too, and the scalar
12710	                * is set to 0.0, because the multi-aggregated variable can be seen as fixed, too
12711	                */
12712	               if( SCIPsetIsInfinity(set, (*var)->data.multaggr.constant)
12713	                  || SCIPsetIsInfinity(set, -((*var)->data.multaggr.constant)) )
12714	               {
12715	                  if( (*scalar) * (*var)->data.multaggr.constant > 0 )
12716	                  {
12717	                     assert(!SCIPsetIsInfinity(set, -(*constant)));
12718	                     (*constant) = SCIPsetInfinity(set);
12719	                  }
12720	                  else
12721	                  {
12722	                     assert(!SCIPsetIsInfinity(set, *constant));
12723	                     (*constant) = -SCIPsetInfinity(set);
12724	                  }
12725	                  (*scalar) = 0.0;
12726	               }
12727	               else
12728	                  (*constant) += *scalar * (*var)->data.multaggr.constant;
12729	            }
12730	            (*scalar) *= (*var)->data.multaggr.scalars[0];
12731	            *var = (*var)->data.multaggr.vars[0];
12732	            break;
12733	         }
12734	         return SCIP_OKAY;
12735	
12736	      case SCIP_VARSTATUS_AGGREGATED:  /* x = a'*x' + c'  =>  a*x + c == (a*a')*x' + (a*c' + c) */
12737	         assert((*var)->data.aggregate.var != NULL);
12738	         assert(!SCIPsetIsInfinity(set, (*var)->data.aggregate.constant)
12739	            && !SCIPsetIsInfinity(set, (*var)->data.aggregate.constant));
12740	         if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12741	            (*constant) += *scalar * (*var)->data.aggregate.constant;
12742	         (*scalar) *= (*var)->data.aggregate.scalar;
12743	         *var = (*var)->data.aggregate.var;
12744	         break;
12745	
12746	      case SCIP_VARSTATUS_NEGATED:     /* x =  - x' + c'  =>  a*x + c ==   (-a)*x' + (a*c' + c) */
12747	         assert((*var)->negatedvar != NULL);
12748	         assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12749	         assert((*var)->negatedvar->negatedvar == *var);
12750	         assert(!SCIPsetIsInfinity(set, (*var)->data.negate.constant)
12751	            && !SCIPsetIsInfinity(set, (*var)->data.negate.constant));
12752	         if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12753	            (*constant) += *scalar * (*var)->data.negate.constant;
12754	         (*scalar) *= -1.0;
12755	         *var = (*var)->negatedvar;
12756	         break;
12757	
12758	      default:
12759	         SCIPerrorMessage("unknown variable status\n");
12760		 SCIPABORT();
12761	         return SCIP_INVALIDDATA; /*lint !e527*/
12762	      }
12763	   }
12764	   *scalar = 0.0;
12765	
12766	   return SCIP_OKAY;
12767	}
12768	
12769	/** retransforms given variable, scalar and constant to the corresponding original variable, scalar
12770	 *  and constant, if possible; if the retransformation is impossible, NULL is returned as variable
12771	 */
12772	SCIP_RETCODE SCIPvarGetOrigvarSum(
12773	   SCIP_VAR**            var,                /**< pointer to problem variable x in sum a*x + c */
12774	   SCIP_Real*            scalar,             /**< pointer to scalar a in sum a*x + c */
12775	   SCIP_Real*            constant            /**< pointer to constant c in sum a*x + c */
12776	   )
12777	{
12778	   SCIP_VAR* parentvar;
12779	
12780	   assert(var != NULL);
12781	   assert(*var != NULL);
12782	   assert(scalar != NULL);
12783	   assert(constant != NULL);
12784	
12785	   while( !SCIPvarIsOriginal(*var) )
12786	   {
12787	      /* if the variable has no parent variables, it was generated during solving and has no corresponding original
12788	       * var
12789	       */
12790	      if( (*var)->nparentvars == 0 )
12791	      {
12792	         /* negated variables do not need to have a parent variables, and negated variables can exist in original
12793	          * space
12794	          */
12795	         if( SCIPvarGetStatus(*var) == SCIP_VARSTATUS_NEGATED &&
12796	            ((*var)->negatedvar->nparentvars == 0 || (*var)->negatedvar->parentvars[0] != *var) )
12797	         {
12798	            *scalar *= -1.0;
12799	            *constant -= (*var)->data.negate.constant * (*scalar);
12800	            *var = (*var)->negatedvar;
12801	
12802	            continue;
12803	         }
12804	         /* if the variables does not have any parent the variables was created during solving and has no original
12805	          * counterpart
12806	          */
12807	         else
12808	         {
12809	            *var = NULL;
12810	
12811	            return SCIP_OKAY;
12812	         }
12813	      }
12814	
12815	      /* follow the link to the first parent variable */
12816	      parentvar = (*var)->parentvars[0];
12817	      assert(parentvar != NULL);
12818	
12819	      switch( SCIPvarGetStatus(parentvar) )
12820	      {
12821	      case SCIP_VARSTATUS_ORIGINAL:
12822	         break;
12823	
12824	      case SCIP_VARSTATUS_COLUMN:
12825	      case SCIP_VARSTATUS_LOOSE:
12826	      case SCIP_VARSTATUS_FIXED:
12827	      case SCIP_VARSTATUS_MULTAGGR:
12828	         SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12829	         return SCIP_INVALIDDATA;
12830	
12831	      case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + b  ->  y = (x-b)/a,  s*y + c = (s/a)*x + c-b*s/a */
12832	         assert(parentvar->data.aggregate.var == *var);
12833	         assert(parentvar->data.aggregate.scalar != 0.0);
12834	         *scalar /= parentvar->data.aggregate.scalar;
12835	         *constant -= parentvar->data.aggregate.constant * (*scalar);
12836	         break;
12837	
12838	      case SCIP_VARSTATUS_NEGATED: /* x = b - y  ->  y = b - x,  s*y + c = -s*x + c+b*s */
12839	         assert(parentvar->negatedvar != NULL);
12840	         assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
12841	         assert(parentvar->negatedvar->negatedvar == parentvar);
12842	         *scalar *= -1.0;
12843	         *constant -= parentvar->data.negate.constant * (*scalar);
12844	         break;
12845	
12846	      default:
12847	         SCIPerrorMessage("unknown variable status\n");
12848	         return SCIP_INVALIDDATA;
12849	      }
12850	
12851	      assert( parentvar != NULL );
12852	      *var = parentvar;
12853	   }
12854	
12855	   return SCIP_OKAY;
12856	}
12857	
12858	/** returns whether the given variable is the direct counterpart of an original problem variable */
12859	SCIP_Bool SCIPvarIsTransformedOrigvar(
12860	   SCIP_VAR*             var                 /**< problem variable */
12861	   )
12862	{
12863	   SCIP_VAR* parentvar;
12864	   assert(var != NULL);
12865	
12866	   if( !SCIPvarIsTransformed(var) || var->nparentvars < 1 )
12867	      return FALSE;
12868	
12869	   assert(var->parentvars != NULL);
12870	   parentvar = var->parentvars[0];
12871	   assert(parentvar != NULL);
12872	
12873	   /* we follow the aggregation tree to the root unless an original variable has been found - the first entries in the parentlist are candidates */
12874	   while( parentvar->nparentvars >= 1 && SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL )
12875	      parentvar = parentvar->parentvars[0];
12876	   assert( parentvar != NULL );
12877	
12878	   return ( SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_ORIGINAL );
12879	}
12880	
12881	/** gets objective value of variable in current SCIP_LP; the value can be different from the objective value stored in
12882	 *  the variable's own data due to diving, that operate only on the LP without updating the variables
12883	 */
12884	SCIP_Real SCIPvarGetObjLP(
12885	   SCIP_VAR*             var                 /**< problem variable */
12886	   )
12887	{
12888	   assert(var != NULL);
12889	
12890	   /* get bounds of attached variables */
12891	   switch( SCIPvarGetStatus(var) )
12892	   {
12893	   case SCIP_VARSTATUS_ORIGINAL:
12894	      assert(var->data.original.transvar != NULL);
12895	      return SCIPvarGetObjLP(var->data.original.transvar);
12896	
12897	   case SCIP_VARSTATUS_COLUMN:
12898	      assert(var->data.col != NULL);
12899	      return SCIPcolGetObj(var->data.col);
12900	
12901	   case SCIP_VARSTATUS_LOOSE:
12902	   case SCIP_VARSTATUS_FIXED:
12903	      return var->obj;
12904	
12905	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
12906	      assert(var->data.aggregate.var != NULL);
12907	      return var->data.aggregate.scalar * SCIPvarGetObjLP(var->data.aggregate.var);
12908	
12909	   case SCIP_VARSTATUS_MULTAGGR:
12910	      SCIPerrorMessage("cannot get the objective value of a multiple aggregated variable\n");
12911	      SCIPABORT();
12912	      return 0.0; /*lint !e527*/
12913	
12914	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
12915	      assert(var->negatedvar != NULL);
12916	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
12917	      assert(var->negatedvar->negatedvar == var);
12918	      return -SCIPvarGetObjLP(var->negatedvar);
12919	
12920	   default:
12921	      SCIPerrorMessage("unknown variable status\n");
12922	      SCIPABORT();
12923	      return 0.0; /*lint !e527*/
12924	   }
12925	}
12926	
12927	/** gets lower bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12928	 *  data due to diving or conflict analysis, that operate only on the LP without updating the variables
12929	 */
12930	SCIP_Real SCIPvarGetLbLP(
12931	   SCIP_VAR*             var,                /**< problem variable */
12932	   SCIP_SET*             set                 /**< global SCIP settings */
12933	   )
12934	{
12935	   assert(var != NULL);
12936	   assert(set != NULL);
12937	   assert(var->scip == set->scip);
12938	
12939	   /* get bounds of attached variables */
12940	   switch( SCIPvarGetStatus(var) )
12941	   {
12942	   case SCIP_VARSTATUS_ORIGINAL:
12943	      assert(var->data.original.transvar != NULL);
12944	      return SCIPvarGetLbLP(var->data.original.transvar, set);
12945	
12946	   case SCIP_VARSTATUS_COLUMN:
12947	      assert(var->data.col != NULL);
12948	      return SCIPcolGetLb(var->data.col);
12949	
12950	   case SCIP_VARSTATUS_LOOSE:
12951	   case SCIP_VARSTATUS_FIXED:
12952	      return var->locdom.lb;
12953	
12954	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
12955	      assert(var->data.aggregate.var != NULL);
12956	      if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set)))
12957	         || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set))) )
12958	      {
12959	         return -SCIPsetInfinity(set);
12960	      }
12961	      else if( var->data.aggregate.scalar > 0.0 )
12962	      {
12963	         /* a > 0 -> get lower bound of y */
12964	         return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12965	      }
12966	      else if( var->data.aggregate.scalar < 0.0 )
12967	      {
12968	         /* a < 0 -> get upper bound of y */
12969	         return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12970	      }
12971	      else
12972	      {
12973	         SCIPerrorMessage("scalar is zero in aggregation\n");
12974	         SCIPABORT();
12975	         return SCIP_INVALID; /*lint !e527*/
12976	      }
12977	
12978	   case SCIP_VARSTATUS_MULTAGGR:
12979	      /**@todo get the sides of the corresponding linear constraint */
12980	      SCIPerrorMessage("getting the bounds of a multiple aggregated variable is not implemented yet\n");
12981	      SCIPABORT();
12982	      return SCIP_INVALID; /*lint !e527*/
12983	
12984	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
12985	      assert(var->negatedvar != NULL);
12986	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
12987	      assert(var->negatedvar->negatedvar == var);
12988	      return var->data.negate.constant - SCIPvarGetUbLP(var->negatedvar, set);
12989	
12990	   default:
12991	      SCIPerrorMessage("unknown variable status\n");
12992	      SCIPABORT();
12993	      return SCIP_INVALID; /*lint !e527*/
12994	   }
12995	}
12996	
12997	/** gets upper bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12998	 *  data due to diving or conflict analysis, that operate only on the LP without updating the variables
12999	 */
13000	SCIP_Real SCIPvarGetUbLP(
13001	   SCIP_VAR*             var,                /**< problem variable */
13002	   SCIP_SET*             set                 /**< global SCIP settings */
13003	   )
13004	{
13005	   assert(var != NULL);
13006	   assert(set != NULL);
13007	   assert(var->scip == set->scip);
13008	
13009	   /* get bounds of attached variables */
13010	   switch( SCIPvarGetStatus(var) )
13011	   {
13012	   case SCIP_VARSTATUS_ORIGINAL:
13013	      assert(var->data.original.transvar != NULL);
13014	      return SCIPvarGetUbLP(var->data.original.transvar, set);
13015	
13016	   case SCIP_VARSTATUS_COLUMN:
13017	      assert(var->data.col != NULL);
13018	      return SCIPcolGetUb(var->data.col);
13019	
13020	   case SCIP_VARSTATUS_LOOSE:
13021	   case SCIP_VARSTATUS_FIXED:
13022	      return var->locdom.ub;
13023	
13024	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
13025	      assert(var->data.aggregate.var != NULL);
13026	      if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set)))
13027	         || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set))) )
13028	      {
13029	         return SCIPsetInfinity(set);
13030	      }
13031	      if( var->data.aggregate.scalar > 0.0 )
13032	      {
13033	         /* a > 0 -> get upper bound of y */
13034	         return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
13035	      }
13036	      else if( var->data.aggregate.scalar < 0.0 )
13037	      {
13038	         /* a < 0 -> get lower bound of y */
13039	         return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
13040	      }
13041	      else
13042	      {
13043	         SCIPerrorMessage("scalar is zero in aggregation\n");
13044	         SCIPABORT();
13045	         return SCIP_INVALID; /*lint !e527*/
13046	      }
13047	
13048	   case SCIP_VARSTATUS_MULTAGGR:
13049	      SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
13050	      SCIPABORT();
13051	      return SCIP_INVALID; /*lint !e527*/
13052	
13053	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
13054	      assert(var->negatedvar != NULL);
13055	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
13056	      assert(var->negatedvar->negatedvar == var);
13057	      return var->data.negate.constant - SCIPvarGetLbLP(var->negatedvar, set);
13058	
13059	   default:
13060	      SCIPerrorMessage("unknown variable status\n");
13061	      SCIPABORT();
13062	      return SCIP_INVALID; /*lint !e527*/
13063	   }
13064	}
13065	
13066	/** gets primal LP solution value of variable */
13067	SCIP_Real SCIPvarGetLPSol_rec(
13068	   SCIP_VAR*             var                 /**< problem variable */
13069	   )
13070	{
13071	   assert(var != NULL);
13072	
13073	   switch( SCIPvarGetStatus(var) )
13074	   {
13075	   case SCIP_VARSTATUS_ORIGINAL:
13076	      if( var->data.original.transvar == NULL )
13077	         return SCIP_INVALID;
13078	      return SCIPvarGetLPSol(var->data.original.transvar);
13079	
13080	   case SCIP_VARSTATUS_LOOSE:
13081	      return SCIPvarGetBestBoundLocal(var);
13082	
13083	   case SCIP_VARSTATUS_COLUMN:
13084	      assert(var->data.col != NULL);
13085	      return SCIPcolGetPrimsol(var->data.col);
13086	
13087	   case SCIP_VARSTATUS_FIXED:
13088	      assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13089	      return var->locdom.lb;
13090	
13091	   case SCIP_VARSTATUS_AGGREGATED:
13092	   {
13093	      SCIP_Real lpsolval;
13094	
13095	      assert(!var->donotaggr);
13096	      assert(var->data.aggregate.var != NULL);
13097	      lpsolval = SCIPvarGetLPSol(var->data.aggregate.var);
13098	
13099	      /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13100	       * corresponding infinity value instead of performing an arithmetical transformation (compare method
13101	       * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13102	       * (or is called by) a public interface method; instead, we only assert that values are finite
13103	       * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13104	       * positives and negatives if the parameter <numerics/infinity> is modified by the user
13105	       */
13106	      assert(lpsolval > -SCIP_DEFAULT_INFINITY);
13107	      assert(lpsolval < +SCIP_DEFAULT_INFINITY);
13108	      return var->data.aggregate.scalar * lpsolval + var->data.aggregate.constant;
13109	   }
13110	   case SCIP_VARSTATUS_MULTAGGR:
13111	   {
13112	      SCIP_Real primsol;
13113	      int i;
13114	
13115	      assert(!var->donotmultaggr);
13116	      assert(var->data.multaggr.vars != NULL);
13117	      assert(var->data.multaggr.scalars != NULL);
13118	      /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13119	       * assert(var->data.multaggr.nvars >= 2); 
13120	       */
13121	      primsol = var->data.multaggr.constant;
13122	      for( i = 0; i < var->data.multaggr.nvars; ++i )
13123	         primsol += var->data.multaggr.scalars[i] * SCIPvarGetLPSol(var->data.multaggr.vars[i]);
13124	      return primsol;
13125	   }
13126	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
13127	      assert(var->negatedvar != NULL);
13128	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
13129	      assert(var->negatedvar->negatedvar == var);
13130	      return var->data.negate.constant - SCIPvarGetLPSol(var->negatedvar);
13131	
13132	   default:
13133	      SCIPerrorMessage("unknown variable status\n");
13134	      SCIPABORT();
13135	      return SCIP_INVALID; /*lint !e527*/
13136	   }
13137	}
13138	
13139	/** gets primal NLP solution value of variable */
13140	SCIP_Real SCIPvarGetNLPSol_rec(
13141	   SCIP_VAR*             var                 /**< problem variable */
13142	   )
13143	{
13144	   SCIP_Real solval;
13145	   int i;
13146	
13147	   assert(var != NULL);
13148	
13149	   /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13150	   switch( SCIPvarGetStatus(var) )
13151	   {
13152	   case SCIP_VARSTATUS_ORIGINAL:
13153	      return SCIPvarGetNLPSol(var->data.original.transvar);
13154	
13155	   case SCIP_VARSTATUS_LOOSE:
13156	   case SCIP_VARSTATUS_COLUMN:
13157	         return var->nlpsol;
13158	
13159	   case SCIP_VARSTATUS_FIXED:
13160	      assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var));  /*lint !e777*/
13161	      assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var));    /*lint !e777*/
13162	      assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var));   /*lint !e777*/
13163	      return SCIPvarGetLbGlobal(var);
13164	
13165	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  =>  y = (x-c)/a */
13166	      solval = SCIPvarGetNLPSol(var->data.aggregate.var);
13167	      return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13168	
13169	   case SCIP_VARSTATUS_MULTAGGR:
13170	      solval = var->data.multaggr.constant;
13171	      for( i = 0; i < var->data.multaggr.nvars; ++i )
13172	         solval += var->data.multaggr.scalars[i] * SCIPvarGetNLPSol(var->data.multaggr.vars[i]);
13173	      return solval;
13174	
13175	   case SCIP_VARSTATUS_NEGATED:
13176	      solval = SCIPvarGetNLPSol(var->negatedvar);
13177	      return var->data.negate.constant - solval;
13178	
13179	   default:
13180	      SCIPerrorMessage("unknown variable status\n");
13181	      SCIPABORT();
13182	      return SCIP_INVALID; /*lint !e527*/
13183	   }
13184	}
13185	
13186	/** gets pseudo solution value of variable at current node */
13187	static
13188	SCIP_Real SCIPvarGetPseudoSol_rec(
13189	   SCIP_VAR*             var                 /**< problem variable */
13190	   )
13191	{
13192	   SCIP_Real pseudosol;
13193	   int i;
13194	
13195	   assert(var != NULL);
13196	
13197	   switch( SCIPvarGetStatus(var) )
13198	   {
13199	   case SCIP_VARSTATUS_ORIGINAL:
13200	      if( var->data.original.transvar == NULL )
13201	         return SCIP_INVALID;
13202	      return SCIPvarGetPseudoSol(var->data.original.transvar);
13203	
13204	   case SCIP_VARSTATUS_LOOSE:
13205	   case SCIP_VARSTATUS_COLUMN:
13206	      return SCIPvarGetBestBoundLocal(var);
13207	
13208	   case SCIP_VARSTATUS_FIXED:
13209	      assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13210	      return var->locdom.lb;
13211	
13212	   case SCIP_VARSTATUS_AGGREGATED:
13213	   {
13214	      SCIP_Real pseudosolval;
13215	      assert(!var->donotaggr);
13216	      assert(var->data.aggregate.var != NULL);
13217	      /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13218	       * corresponding infinity value instead of performing an arithmetical transformation (compare method
13219	       * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13220	       * (or is called by) a public interface method; instead, we only assert that values are finite
13221	       * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13222	       * positives and negatives if the parameter <numerics/infinity> is modified by the user
13223	       */
13224	      pseudosolval = SCIPvarGetPseudoSol(var->data.aggregate.var);
13225	      assert(pseudosolval > -SCIP_DEFAULT_INFINITY);
13226	      assert(pseudosolval < +SCIP_DEFAULT_INFINITY);
13227	      return var->data.aggregate.scalar * pseudosolval + var->data.aggregate.constant;
13228	   }
13229	   case SCIP_VARSTATUS_MULTAGGR:
13230	      assert(!var->donotmultaggr);
13231	      assert(var->data.multaggr.vars != NULL);
13232	      assert(var->data.multaggr.scalars != NULL);
13233	      /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13234	       * assert(var->data.multaggr.nvars >= 2); 
13235	       */
13236	      pseudosol = var->data.multaggr.constant;
13237	      for( i = 0; i < var->data.multaggr.nvars; ++i )
13238	         pseudosol += var->data.multaggr.scalars[i] * SCIPvarGetPseudoSol(var->data.multaggr.vars[i]);
13239	      return pseudosol;
13240	
13241	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
13242	      assert(var->negatedvar != NULL);
13243	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
13244	      assert(var->negatedvar->negatedvar == var);
13245	      return var->data.negate.constant - SCIPvarGetPseudoSol(var->negatedvar);
13246	
13247	   default:
13248	      SCIPerrorMessage("unknown variable status\n");
13249	      SCIPABORT();
13250	      return SCIP_INVALID; /*lint !e527*/
13251	   }
13252	}
13253	
13254	/** gets current LP or pseudo solution value of variable */
13255	SCIP_Real SCIPvarGetSol(
13256	   SCIP_VAR*             var,                /**< problem variable */
13257	   SCIP_Bool             getlpval            /**< should the LP solution value be returned? */
13258	   )
13259	{
13260	   if( getlpval )
13261	      return SCIPvarGetLPSol(var);
13262	   else
13263	      return SCIPvarGetPseudoSol(var);
13264	}
13265	
13266	/** remembers the current solution as root solution in the problem variables */
13267	void SCIPvarStoreRootSol(
13268	   SCIP_VAR*             var,                /**< problem variable */
13269	   SCIP_Bool             roothaslp           /**< is the root solution from LP? */
13270	   )
13271	{
13272	   assert(var != NULL);
13273	
13274	   var->rootsol = SCIPvarGetSol(var, roothaslp);
13275	}
13276	
13277	/** updates the current solution as best root solution of the given variable if it is better */
13278	void SCIPvarUpdateBestRootSol(
13279	   SCIP_VAR*             var,                /**< problem variable */
13280	   SCIP_SET*             set,                /**< global SCIP settings */
13281	   SCIP_Real             rootsol,            /**< root solution value */
13282	   SCIP_Real             rootredcost,        /**< root reduced cost */
13283	   SCIP_Real             rootlpobjval        /**< objective value of the root LP */
13284	   )
13285	{
13286	   assert(var != NULL);
13287	   assert(set != NULL);
13288	   assert(var->scip == set->scip);
13289	
13290	   /* if reduced cost are zero nothing to update */
13291	   if( SCIPsetIsDualfeasZero(set, rootredcost) )
13292	      return;
13293	
13294	   /* check if we have already a best combination stored */
13295	   if( !SCIPsetIsDualfeasZero(set, var->bestrootredcost) )
13296	   {
13297	      SCIP_Real currcutoffbound;
13298	      SCIP_Real cutoffbound;
13299	      SCIP_Real bound;
13300	
13301	      /* compute the cutoff bound which would improve the corresponding bound with the current stored root solution,
13302	       * root reduced cost, and root LP objective value combination
13303	       */
13304	      if( var->bestrootredcost > 0.0 )
13305	         bound = SCIPvarGetUbGlobal(var);
13306	      else
13307	         bound = SCIPvarGetLbGlobal(var);
13308	
13309	      currcutoffbound = (bound - var->bestrootsol) * var->bestrootredcost + var->bestrootlpobjval;
13310	
13311	      /* compute the cutoff bound which would improve the corresponding bound with new root solution, root reduced
13312	       * cost, and root LP objective value combination
13313	       */
13314	      if( rootredcost > 0.0 )
13315	         bound = SCIPvarGetUbGlobal(var);
13316	      else
13317	         bound = SCIPvarGetLbGlobal(var);
13318	
13319	      cutoffbound = (bound - rootsol) * rootredcost + rootlpobjval;
13320	
13321	      /* check if an improving root solution, root reduced cost, and root LP objective value is at hand */
13322	      if( cutoffbound > currcutoffbound )
13323	      {
13324	         SCIPsetDebugMsg(set, "-> <%s> update potential cutoff bound <%g> -> <%g>\n",
13325	            SCIPvarGetName(var), currcutoffbound, cutoffbound);
13326	
13327	         var->bestrootsol = rootsol;
13328	         var->bestrootredcost = rootredcost;
13329	         var->bestrootlpobjval = rootlpobjval;
13330	      }
13331	   }
13332	   else
13333	   {
13334	      SCIPsetDebugMsg(set, "-> <%s> initialize best root reduced cost information\n", SCIPvarGetName(var));
13335	      SCIPsetDebugMsg(set, "   -> rootsol <%g>\n", rootsol);
13336	      SCIPsetDebugMsg(set, "   -> rootredcost <%g>\n", rootredcost);
13337	      SCIPsetDebugMsg(set, "   -> rootlpobjval <%g>\n", rootlpobjval);
13338	
13339	      var->bestrootsol = rootsol;
13340	      var->bestrootredcost = rootredcost;
13341	      var->bestrootlpobjval = rootlpobjval;
13342	   }
13343	}
13344	
13345	/** returns the solution of the variable in the last root node's relaxation, if the root relaxation is not yet
13346	 *  completely solved, zero is returned
13347	 */
13348	SCIP_Real SCIPvarGetRootSol(
13349	   SCIP_VAR*             var                 /**< problem variable */
13350	   )
13351	{
13352	   SCIP_Real rootsol;
13353	   int i;
13354	
13355	   assert(var != NULL);
13356	
13357	   switch( SCIPvarGetStatus(var) )
13358	   {
13359	   case SCIP_VARSTATUS_ORIGINAL:
13360	      if( var->data.original.transvar == NULL )
13361	         return 0.0;
13362	      return SCIPvarGetRootSol(var->data.original.transvar);
13363	
13364	   case SCIP_VARSTATUS_LOOSE:
13365	   case SCIP_VARSTATUS_COLUMN:
13366	      return var->rootsol;
13367	
13368	   case SCIP_VARSTATUS_FIXED:
13369	      assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13370	      return var->locdom.lb;
13371	
13372	   case SCIP_VARSTATUS_AGGREGATED:
13373	      assert(!var->donotaggr);
13374	      assert(var->data.aggregate.var != NULL);
13375	      /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13376	       * corresponding infinity value instead of performing an arithmetical transformation (compare method
13377	       * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13378	       * (or is called by) a public interface method; instead, we only assert that values are finite
13379	       * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13380	       * positives and negatives if the parameter <numerics/infinity> is modified by the user
13381	       */
13382	      assert(SCIPvarGetRootSol(var->data.aggregate.var) > -SCIP_DEFAULT_INFINITY);
13383	      assert(SCIPvarGetRootSol(var->data.aggregate.var) < +SCIP_DEFAULT_INFINITY);
13384	      return var->data.aggregate.scalar * SCIPvarGetRootSol(var->data.aggregate.var) + var->data.aggregate.constant;
13385	
13386	   case SCIP_VARSTATUS_MULTAGGR:
13387	      assert(!var->donotmultaggr);
13388	      assert(var->data.multaggr.vars != NULL);
13389	      assert(var->data.multaggr.scalars != NULL);
13390	      /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13391	       * assert(var->data.multaggr.nvars >= 2); 
13392	       */
13393	      rootsol = var->data.multaggr.constant;
13394	      for( i = 0; i < var->data.multaggr.nvars; ++i )
13395	         rootsol += var->data.multaggr.scalars[i] * SCIPvarGetRootSol(var->data.multaggr.vars[i]);
13396	      return rootsol;
13397	
13398	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
13399	      assert(var->negatedvar != NULL);
13400	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
13401	      assert(var->negatedvar->negatedvar == var);
13402	      return var->data.negate.constant - SCIPvarGetRootSol(var->negatedvar);
13403	
13404	   default:
13405	      SCIPerrorMessage("unknown variable status\n");
13406	      SCIPABORT();
13407	      return SCIP_INVALID; /*lint !e527*/
13408	   }
13409	}
13410	
13411	/** returns for given variable the reduced cost */
13412	static
13413	SCIP_Real getImplVarRedcost(
13414	   SCIP_VAR*             var,                /**< problem variable */
13415	   SCIP_SET*             set,                /**< global SCIP settings */
13416	   SCIP_Bool             varfixing,          /**< FALSE if for x == 0, TRUE for x == 1 */
13417	   SCIP_STAT*            stat,               /**< problem statistics */
13418	   SCIP_LP*              lp                  /**< current LP data */
13419	   )
13420	{
13421	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN )
13422	   {
13423	      SCIP_COL* col;
13424	      SCIP_Real primsol;
13425	      SCIP_BASESTAT basestat;
13426	      SCIP_Bool lpissolbasic;
13427	
13428	      col = SCIPvarGetCol(var);
13429	      assert(col != NULL);
13430	
13431	      basestat = SCIPcolGetBasisStatus(col);
13432	      lpissolbasic = SCIPlpIsSolBasic(lp);
13433	      primsol = SCIPcolGetPrimsol(col);
13434	
13435	      if( (lpissolbasic && (basestat == SCIP_BASESTAT_LOWER || basestat == SCIP_BASESTAT_UPPER)) ||
13436	         (!lpissolbasic && (SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol) || SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol))) )
13437	      {
13438	         SCIP_Real redcost = SCIPcolGetRedcost(col, stat, lp);
13439	
13440	         assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)) ||
13441	               (lpissolbasic && basestat == SCIP_BASESTAT_LOWER)) ? (!SCIPsetIsDualfeasNegative(set, redcost) ||
13442	                  SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var))) : TRUE);
13443	         assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)) ||
13444	               (lpissolbasic && basestat == SCIP_BASESTAT_UPPER)) ? (!SCIPsetIsDualfeasPositive(set, redcost) ||
13445	                  SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var))) : TRUE);
13446	
13447	         if( (varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_LOWER) ||
13448	                  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)))) ||
13449	            (!varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_UPPER) ||
13450	                  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)))) )
13451	            return redcost;
13452	         else
13453	            return 0.0;
13454	      }
13455	
13456	      return 0.0;
13457	   }
13458	
13459	   return 0.0;
13460	}
13461	
13462	#define MAX_CLIQUELENGTH 50
13463	/** returns for the given binary variable the reduced cost which are given by the variable itself and its implication if
13464	 *  the binary variable is fixed to the given value
13465	 */
13466	SCIP_Real SCIPvarGetImplRedcost(
13467	   SCIP_VAR*             var,                /**< problem variable */
13468	   SCIP_SET*             set,                /**< global SCIP settings */
13469	   SCIP_Bool             varfixing,          /**< FALSE if for x == 0, TRUE for x == 1 */
13470	   SCIP_STAT*            stat,               /**< problem statistics */
13471	   SCIP_PROB*            prob,               /**< transformed problem, or NULL */
13472	   SCIP_LP*              lp                  /**< current LP data */
13473	   )
13474	{
13475	   SCIP_Real implredcost;
13476	   int ncliques;
13477	   int nvars;
13478	
13479	   assert(SCIPvarIsBinary(var));
13480	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
13481	
13482	   /* get reduced cost of given variable */
13483	   implredcost = getImplVarRedcost(var, set, varfixing, stat, lp);
13484	
13485	#ifdef SCIP_MORE_DEBUG
13486	   SCIPsetDebugMsg(set, "variable <%s> itself has reduced cost of %g\n", SCIPvarGetName(var), implredcost);
13487	#endif
13488	
13489	   /* the following algorithm is expensive */
13490	   ncliques = SCIPvarGetNCliques(var, varfixing);
13491	
13492	   if( ncliques > 0 )
13493	   {
13494	      SCIP_CLIQUE** cliques;
13495	      SCIP_CLIQUE* clique;
13496	      SCIP_VAR** clqvars;
13497	      SCIP_VAR** probvars;
13498	      SCIP_VAR* clqvar;
13499	      SCIP_Bool* clqvalues;
13500	      int* entries;
13501	      int* ids;
13502	      SCIP_Real redcost;
13503	      SCIP_Bool cleanedup;
13504	      int nclqvars;
13505	      int nentries;
13506	      int nids;
13507	      int id;
13508	      int c;
13509	      int v;
13510	
13511	      assert(prob != NULL);
13512	      assert(SCIPprobIsTransformed(prob));
13513	
13514	      nentries = SCIPprobGetNVars(prob) - SCIPprobGetNContVars(prob) + 1;
13515	
13516	      SCIP_CALL_ABORT( SCIPsetAllocBufferArray(set, &ids, nentries) );
13517	      nids = 0;
13518	      SCIP_CALL_ABORT( SCIPsetAllocCleanBufferArray(set, &entries, nentries) );
13519	
13520	      cliques = SCIPvarGetCliques(var, varfixing);
13521	      assert(cliques != NULL);
13522	
13523	      for( c = ncliques - 1; c >= 0; --c )
13524	      {
13525	         clique = cliques[c];
13526	         assert(clique != NULL);
13527	         nclqvars = SCIPcliqueGetNVars(clique);
13528	         assert(nclqvars > 0);
13529	
13530	         if( nclqvars > MAX_CLIQUELENGTH )
13531	            continue;
13532	
13533	         clqvars = SCIPcliqueGetVars(clique);
13534	         clqvalues = SCIPcliqueGetValues(clique);
13535	         assert(clqvars != NULL);
13536	         assert(clqvalues != NULL);
13537	
13538	         cleanedup = SCIPcliqueIsCleanedUp(clique);
13539	
13540	         for( v = nclqvars - 1; v >= 0; --v )
13541	         {
13542	            clqvar = clqvars[v];
13543	            assert(clqvar != NULL);
13544	
13545	            /* ignore binary variable which are fixed */
13546	            if( clqvar != var && (cleanedup || SCIPvarIsActive(clqvar)) &&
13547	               (SCIPvarGetLbLocal(clqvar) < 0.5 && SCIPvarGetUbLocal(clqvar) > 0.5) )
13548	            {
13549	               int probindex = SCIPvarGetProbindex(clqvar) + 1;
13550	               assert(0 < probindex && probindex < nentries);
13551	
13552	#if 0
13553	               /* check that the variable was not yet visited or does not appear with two contradicting implications, ->
13554	                * can appear since there is no guarantee that all these infeasible bounds were found
13555	                */
13556	               assert(!entries[probindex] || entries[probindex] == (clqvalues[v] ? probindex : -probindex));
13557	#endif
13558	               if( entries[probindex] == 0 )
13559	               {
13560	                  ids[nids] = probindex;
13561	                  ++nids;
13562	
13563	                  /* mark variable as visited */
13564	                  entries[probindex] = (clqvalues[v] ? probindex : -probindex);
13565	               }
13566	            }
13567	         }
13568	      }
13569	
13570	      probvars = SCIPprobGetVars(prob);
13571	      assert(probvars != NULL);
13572	
13573	      /* add all implied reduced cost */
13574	      for( v = nids - 1; v >= 0; --v )
13575	      {
13576	         id = ids[v];
13577	         assert(0 < id && id < nentries);
13578	         assert(entries[id] != 0);
13579	         assert(probvars[id - 1] != NULL);
13580	         assert(SCIPvarIsActive(probvars[id - 1]));
13581	         assert(SCIPvarIsBinary(probvars[id - 1]));
13582	         assert(SCIPvarGetLbLocal(probvars[id - 1]) < 0.5 && SCIPvarGetUbLocal(probvars[id - 1]) > 0.5);
13583	
13584	         if( (entries[id] > 0) != varfixing )
13585	            redcost = getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13586	         else
13587	            redcost = -getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13588	
13589	         if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13590	            implredcost += redcost;
13591	
13592	         /* reset entries clear buffer array */
13593	         entries[id] = 0;
13594	      }
13595	
13596	      SCIPsetFreeCleanBufferArray(set, &entries);
13597	      SCIPsetFreeBufferArray(set, &ids);
13598	   }
13599	
13600	#ifdef SCIP_MORE_DEBUG
13601	   SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) has implied reduced cost of %g\n", SCIPvarGetName(var), ncliques,
13602	      implredcost);
13603	#endif
13604	
13605	   /* collect non-binary implication information */
13606	   nvars = SCIPimplicsGetNImpls(var->implics, varfixing);
13607	
13608	   if( nvars > 0 )
13609	   {
13610	      SCIP_VAR** vars;
13611	      SCIP_VAR* implvar;
13612	      SCIP_COL* col;
13613	      SCIP_Real* bounds;
13614	      SCIP_BOUNDTYPE* boundtypes;
13615	      SCIP_Real redcost;
13616	      SCIP_Real lb;
13617	      SCIP_Real ub;
13618	      SCIP_Bool lpissolbasic;
13619	      int v;
13620	
13621	      vars =  SCIPimplicsGetVars(var->implics, varfixing);
13622	      boundtypes = SCIPimplicsGetTypes(var->implics, varfixing);
13623	      bounds = SCIPimplicsGetBounds(var->implics, varfixing);
13624	      lpissolbasic = SCIPlpIsSolBasic(lp);
13625	
13626	      for( v = nvars - 1; v >= 0; --v )
13627	      {
13628	         implvar = vars[v];
13629	         assert(implvar != NULL);
13630	
13631	         lb = SCIPvarGetLbLocal(implvar);
13632	         ub = SCIPvarGetUbLocal(implvar);
13633	
13634	         /* ignore binary variable which are fixed or not of column status */
13635	         if( SCIPvarGetStatus(implvar) != SCIP_VARSTATUS_COLUMN || SCIPsetIsFeasEQ(set, lb, ub) )
13636	            continue;
13637	
13638	         col = SCIPvarGetCol(implvar);
13639	         assert(col != NULL);
13640	         redcost = 0.0;
13641	
13642	         /* solved lp with basis information or not? */
13643	         if( lpissolbasic )
13644	         {
13645	            SCIP_BASESTAT basestat = SCIPcolGetBasisStatus(col);
13646	
13647	            /* check if the implication is not not yet applied */
13648	            if( basestat == SCIP_BASESTAT_LOWER && boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, bounds[v], lb) )
13649	            {
13650	               redcost = SCIPcolGetRedcost(col, stat, lp);
13651	               assert(!SCIPsetIsDualfeasNegative(set, redcost));
13652	
13653	               if( !varfixing )
13654	                  redcost *= (lb - bounds[v]);
13655	               else
13656	                  redcost *= (bounds[v] - lb);
13657	            }
13658	            else if( basestat == SCIP_BASESTAT_UPPER && boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, bounds[v], ub) )
13659	            {
13660	               redcost = SCIPcolGetRedcost(col, stat, lp);
13661	               assert(!SCIPsetIsDualfeasPositive(set, redcost));
13662	
13663	               if( varfixing )
13664	                  redcost *= (bounds[v] - ub);
13665	               else
13666	                  redcost *= (ub - bounds[v]);
13667	            }
13668	         }
13669	         else
13670	         {
13671	            SCIP_Real primsol = SCIPcolGetPrimsol(col);
13672	
13673	            /* check if the implication is not not yet applied */
13674	            if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasEQ(set, lb, primsol) && SCIPsetIsFeasGT(set, bounds[v], lb) )
13675	            {
13676	               redcost = SCIPcolGetRedcost(col, stat, lp);
13677	               assert(!SCIPsetIsDualfeasNegative(set, redcost));
13678	
13679	               if( varfixing )
13680	                  redcost *= (lb - bounds[v]);
13681	               else
13682	                  redcost *= (bounds[v] - lb);
13683	            }
13684	            else if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasEQ(set, ub, primsol) && SCIPsetIsFeasLT(set, bounds[v], ub) )
13685	            {
13686	               redcost = SCIPcolGetRedcost(col, stat, lp);
13687	               assert(!SCIPsetIsDualfeasPositive(set, redcost));
13688	
13689	               if( varfixing )
13690	                  redcost *= (bounds[v] - ub);
13691	               else
13692	                  redcost *= (ub - bounds[v]);
13693	            }
13694	         }
13695	
13696	         /* improve implied reduced cost */
13697	         if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13698	            implredcost += redcost;
13699	      }
13700	   }
13701	
13702	#ifdef SCIP_MORE_DEBUG
13703	   SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) and implications (%d) has implied reduced cost of %g\n",
13704	      SCIPvarGetName(var), ncliques, nvars, implredcost);
13705	#endif
13706	
13707	   return implredcost;
13708	}
13709	
13710	/** returns the best solution (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation, if
13711	 *  the root relaxation is not yet completely solved, zero is returned
13712	 */
13713	SCIP_Real SCIPvarGetBestRootSol(
13714	   SCIP_VAR*             var                 /**< problem variable */
13715	   )
13716	{
13717	   SCIP_Real rootsol;
13718	   int i;
13719	
13720	   assert(var != NULL);
13721	
13722	   switch( SCIPvarGetStatus(var) )
13723	   {
13724	   case SCIP_VARSTATUS_ORIGINAL:
13725	      if( var->data.original.transvar == NULL )
13726	         return 0.0;
13727	      return SCIPvarGetBestRootSol(var->data.original.transvar);
13728	
13729	   case SCIP_VARSTATUS_LOOSE:
13730	   case SCIP_VARSTATUS_COLUMN:
13731	      return var->bestrootsol;
13732	
13733	   case SCIP_VARSTATUS_FIXED:
13734	      assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13735	      return var->locdom.lb;
13736	
13737	   case SCIP_VARSTATUS_AGGREGATED:
13738	      assert(!var->donotaggr);
13739	      assert(var->data.aggregate.var != NULL);
13740	      /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13741	       * corresponding infinity value instead of performing an arithmetical transformation (compare method
13742	       * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13743	       * (or is called by) a public interface method; instead, we only assert that values are finite
13744	       * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13745	       * positives and negatives if the parameter <numerics/infinity> is modified by the user
13746	       */
13747	      assert(SCIPvarGetBestRootSol(var->data.aggregate.var) > -SCIP_DEFAULT_INFINITY);
13748	      assert(SCIPvarGetBestRootSol(var->data.aggregate.var) < +SCIP_DEFAULT_INFINITY);
13749	      return var->data.aggregate.scalar * SCIPvarGetBestRootSol(var->data.aggregate.var) + var->data.aggregate.constant;
13750	
13751	   case SCIP_VARSTATUS_MULTAGGR:
13752	      assert(!var->donotmultaggr);
13753	      assert(var->data.multaggr.vars != NULL);
13754	      assert(var->data.multaggr.scalars != NULL);
13755	      /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13756	       * assert(var->data.multaggr.nvars >= 2);
13757	       */
13758	      rootsol = var->data.multaggr.constant;
13759	      for( i = 0; i < var->data.multaggr.nvars; ++i )
13760	         rootsol += var->data.multaggr.scalars[i] * SCIPvarGetBestRootSol(var->data.multaggr.vars[i]);
13761	      return rootsol;
13762	
13763	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
13764	      assert(var->negatedvar != NULL);
13765	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
13766	      assert(var->negatedvar->negatedvar == var);
13767	      return var->data.negate.constant - SCIPvarGetBestRootSol(var->negatedvar);
13768	
13769	   default:
13770	      SCIPerrorMessage("unknown variable status\n");
13771	      SCIPABORT();
13772	      return 0.0; /*lint !e527*/
13773	   }
13774	}
13775	
13776	/** returns the best reduced costs (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation,
13777	 *  if the root relaxation is not yet completely solved, or the variable was no column of the root LP, SCIP_INVALID is
13778	 *  returned
13779	 */
13780	SCIP_Real SCIPvarGetBestRootRedcost(
13781	   SCIP_VAR*             var                 /**< problem variable */
13782	   )
13783	{
13784	   assert(var != NULL);
13785	
13786	   switch( SCIPvarGetStatus(var) )
13787	   {
13788	   case SCIP_VARSTATUS_ORIGINAL:
13789	      if( var->data.original.transvar == NULL )
13790	         return SCIP_INVALID;
13791	      return SCIPvarGetBestRootRedcost(var->data.original.transvar);
13792	
13793	   case SCIP_VARSTATUS_LOOSE:
13794	   case SCIP_VARSTATUS_COLUMN:
13795	      return var->bestrootredcost;
13796	
13797	   case SCIP_VARSTATUS_FIXED:
13798	   case SCIP_VARSTATUS_AGGREGATED:
13799	   case SCIP_VARSTATUS_MULTAGGR:
13800	   case SCIP_VARSTATUS_NEGATED:
13801	      return 0.0;
13802	
13803	   default:
13804	      SCIPerrorMessage("unknown variable status\n");
13805	      SCIPABORT();
13806	      return 0.0; /*lint !e527*/
13807	   }
13808	}
13809	
13810	/** returns the best objective value (w.r.t. root reduced cost propagation) of the root LP which belongs the root
13811	 *  reduced cost which is accessible via SCIPvarGetRootRedcost() or the variable was no column of the root LP,
13812	 *  SCIP_INVALID is returned
13813	 */
13814	SCIP_Real SCIPvarGetBestRootLPObjval(
13815	   SCIP_VAR*             var                 /**< problem variable */
13816	   )
13817	{
13818	   assert(var != NULL);
13819	
13820	   switch( SCIPvarGetStatus(var) )
13821	   {
13822	   case SCIP_VARSTATUS_ORIGINAL:
13823	      if( var->data.original.transvar == NULL )
13824	         return SCIP_INVALID;
13825	      return SCIPvarGetBestRootLPObjval(var->data.original.transvar);
13826	
13827	   case SCIP_VARSTATUS_LOOSE:
13828	   case SCIP_VARSTATUS_COLUMN:
13829	      return var->bestrootlpobjval;
13830	
13831	   case SCIP_VARSTATUS_FIXED:
13832	   case SCIP_VARSTATUS_AGGREGATED:
13833	   case SCIP_VARSTATUS_MULTAGGR:
13834	   case SCIP_VARSTATUS_NEGATED:
13835	      return SCIP_INVALID;
13836	
13837	   default:
13838	      SCIPerrorMessage("unknown variable status\n");
13839	      SCIPABORT();
13840	      return SCIP_INVALID; /*lint !e527*/
13841	   }
13842	}
13843	
13844	/** set the given solution as the best root solution w.r.t. root reduced cost propagation in the variables */
13845	void SCIPvarSetBestRootSol(
13846	   SCIP_VAR*             var,                /**< problem variable */
13847	   SCIP_Real             rootsol,            /**< root solution value */
13848	   SCIP_Real             rootredcost,        /**< root reduced cost */
13849	   SCIP_Real             rootlpobjval        /**< objective value of the root LP */
13850	   )
13851	{
13852	   assert(var != NULL);
13853	
13854	   var->bestrootsol = rootsol;
13855	   var->bestrootredcost = rootredcost;
13856	   var->bestrootlpobjval = rootlpobjval;
13857	}
13858	
13859	/** stores the solution value as relaxation solution in the problem variable */
13860	SCIP_RETCODE SCIPvarSetRelaxSol(
13861	   SCIP_VAR*             var,                /**< problem variable */
13862	   SCIP_SET*             set,                /**< global SCIP settings */
13863	   SCIP_RELAXATION*      relaxation,         /**< global relaxation data */
13864	   SCIP_Real             solval,             /**< solution value in the current relaxation solution */
13865	   SCIP_Bool             updateobj           /**< should the objective value be updated? */
13866	   )
13867	{
13868	   assert(var != NULL);
13869	   assert(relaxation != NULL);
13870	   assert(set != NULL);
13871	   assert(var->scip == set->scip);
13872	
13873	   /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13874	   switch( SCIPvarGetStatus(var) )
13875	   {
13876	   case SCIP_VARSTATUS_ORIGINAL:
13877	      SCIP_CALL( SCIPvarSetRelaxSol(var->data.original.transvar, set, relaxation, solval, updateobj) );
13878	      break;
13879	
13880	   case SCIP_VARSTATUS_LOOSE:
13881	   case SCIP_VARSTATUS_COLUMN:
13882	      if( updateobj )
13883	         SCIPrelaxationSolObjAdd(relaxation, var->obj * (solval - var->relaxsol));
13884	      var->relaxsol = solval;
13885	      break;
13886	
13887	   case SCIP_VARSTATUS_FIXED:
13888	      if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13889	      {
13890	         SCIPerrorMessage("cannot set relaxation solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13891	            SCIPvarGetName(var), var->glbdom.lb, solval);
13892	         return SCIP_INVALIDDATA;
13893	      }
13894	      break;
13895	
13896	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  =>  y = (x-c)/a */
13897	      assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13898	      SCIP_CALL( SCIPvarSetRelaxSol(var->data.aggregate.var, set, relaxation, 
13899	            (solval - var->data.aggregate.constant)/var->data.aggregate.scalar, updateobj) );
13900	      break;
13901	   case SCIP_VARSTATUS_MULTAGGR:
13902	      SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13903	      return SCIP_INVALIDDATA;
13904	
13905	   case SCIP_VARSTATUS_NEGATED:
13906	      SCIP_CALL( SCIPvarSetRelaxSol(var->negatedvar, set, relaxation, var->data.negate.constant - solval, updateobj) );
13907	      break;
13908	
13909	   default:
13910	      SCIPerrorMessage("unknown variable status\n");
13911	      return SCIP_INVALIDDATA;
13912	   }
13913	
13914	   return SCIP_OKAY;
13915	}
13916	
13917	/** returns the solution value of the problem variable in the relaxation solution
13918	 *
13919	 *  @todo Inline this function - similar to SCIPvarGetLPSol_rec.
13920	 */
13921	SCIP_Real SCIPvarGetRelaxSol(
13922	   SCIP_VAR*             var,                /**< problem variable */
13923	   SCIP_SET*             set                 /**< global SCIP settings */
13924	   )
13925	{
13926	   SCIP_Real solvalsum;
13927	   SCIP_Real solval;
13928	   int i;
13929	
13930	   assert(var != NULL);
13931	   assert(set != NULL);
13932	   assert(var->scip == set->scip);
13933	
13934	   /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13935	   switch( SCIPvarGetStatus(var) )
13936	   {
13937	   case SCIP_VARSTATUS_ORIGINAL:
13938	      return SCIPvarGetRelaxSol(var->data.original.transvar, set);
13939	
13940	   case SCIP_VARSTATUS_LOOSE:
13941	   case SCIP_VARSTATUS_COLUMN:
13942	      return var->relaxsol;
13943	
13944	   case SCIP_VARSTATUS_FIXED:
13945	      assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var));  /*lint !e777*/
13946	      assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var));    /*lint !e777*/
13947	      assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var));   /*lint !e777*/
13948	      return SCIPvarGetLbGlobal(var);
13949	
13950	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  =>  y = (x-c)/a */
13951	      solval = SCIPvarGetRelaxSol(var->data.aggregate.var, set);
13952	      if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13953	      {
13954	         if( var->data.aggregate.scalar * solval > 0.0 )
13955	            return SCIPsetInfinity(set);
13956	         if( var->data.aggregate.scalar * solval < 0.0 )
13957	            return -SCIPsetInfinity(set);
13958	      }
13959	      return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13960	
13961	   case SCIP_VARSTATUS_MULTAGGR:
13962	      solvalsum = var->data.multaggr.constant;
13963	      for( i = 0; i < var->data.multaggr.nvars; ++i )
13964	      {
13965	         solval = SCIPvarGetRelaxSol(var->data.multaggr.vars[i], set);
13966	         if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13967	         {
13968	            if( var->data.multaggr.scalars[i] * solval > 0.0 )
13969	               return SCIPsetInfinity(set);
13970	            if( var->data.multaggr.scalars[i] * solval < 0.0 )
13971	               return -SCIPsetInfinity(set);
13972	         }
13973	         solvalsum += var->data.multaggr.scalars[i] * solval;
13974	      }
13975	      return solvalsum;
13976	
13977	   case SCIP_VARSTATUS_NEGATED:
13978	      solval = SCIPvarGetRelaxSol(var->negatedvar, set);
13979	      if( SCIPsetIsInfinity(set, solval) )
13980	         return -SCIPsetInfinity(set);
13981	      if( SCIPsetIsInfinity(set, -solval) )
13982	         return SCIPsetInfinity(set);
13983	      return var->data.negate.constant - solval;
13984	
13985	   default:
13986	      SCIPerrorMessage("unknown variable status\n");
13987	      SCIPABORT();
13988	      return SCIP_INVALID; /*lint !e527*/
13989	   }
13990	}
13991	
13992	/** returns the solution value of the transformed problem variable in the relaxation solution */
13993	SCIP_Real SCIPvarGetRelaxSolTransVar(
13994	   SCIP_VAR*             var                 /**< problem variable */
13995	   )
13996	{
13997	   assert(var != NULL);
13998	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
13999	
14000	   return var->relaxsol;
14001	}
14002	
14003	/** stores the solution value as NLP solution in the problem variable */
14004	SCIP_RETCODE SCIPvarSetNLPSol(
14005	   SCIP_VAR*             var,                /**< problem variable */
14006	   SCIP_SET*             set,                /**< global SCIP settings */
14007	   SCIP_Real             solval              /**< solution value in the current NLP solution */
14008	   )
14009	{
14010	   assert(var != NULL);
14011	   assert(set != NULL);
14012	   assert(var->scip == set->scip);
14013	
14014	   /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
14015	   switch( SCIPvarGetStatus(var) )
14016	   {
14017	   case SCIP_VARSTATUS_ORIGINAL:
14018	      SCIP_CALL( SCIPvarSetNLPSol(var->data.original.transvar, set, solval) );
14019	      break;
14020	
14021	   case SCIP_VARSTATUS_LOOSE:
14022	   case SCIP_VARSTATUS_COLUMN:
14023	      var->nlpsol = solval;
14024	      break;
14025	
14026	   case SCIP_VARSTATUS_FIXED:
14027	      if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
14028	      {
14029	         SCIPerrorMessage("cannot set NLP solution value for variable <%s> fixed to %.15g to different value %.15g\n",
14030	            SCIPvarGetName(var), var->glbdom.lb, solval);
14031	         SCIPABORT();
14032	         return SCIP_INVALIDCALL; /*lint !e527*/
14033	      }
14034	      break;
14035	
14036	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  =>  y = (x-c)/a */
14037	      assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
14038	      SCIP_CALL( SCIPvarSetNLPSol(var->data.aggregate.var, set, (solval - var->data.aggregate.constant)/var->data.aggregate.scalar) );
14039	      break;
14040	
14041	   case SCIP_VARSTATUS_MULTAGGR:
14042	      SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
14043	      SCIPABORT();
14044	      return SCIP_INVALIDCALL; /*lint !e527*/
14045	
14046	   case SCIP_VARSTATUS_NEGATED:
14047	      SCIP_CALL( SCIPvarSetNLPSol(var->negatedvar, set, var->data.negate.constant - solval) );
14048	      break;
14049	
14050	   default:
14051	      SCIPerrorMessage("unknown variable status\n");
14052	      SCIPABORT();
14053	      return SCIP_ERROR; /*lint !e527*/
14054	   }
14055	
14056	   return SCIP_OKAY;
14057	}
14058	
14059	/** returns a weighted average solution value of the variable in all feasible primal solutions found so far */
14060	SCIP_Real SCIPvarGetAvgSol(
14061	   SCIP_VAR*             var                 /**< problem variable */
14062	   )
14063	{
14064	   SCIP_Real avgsol;
14065	   int i;
14066	
14067	   assert(var != NULL);
14068	
14069	   switch( SCIPvarGetStatus(var) )
14070	   {
14071	   case SCIP_VARSTATUS_ORIGINAL:
14072	      if( var->data.original.transvar == NULL )
14073	         return 0.0;
14074	      return SCIPvarGetAvgSol(var->data.original.transvar);
14075	
14076	   case SCIP_VARSTATUS_LOOSE:
14077	   case SCIP_VARSTATUS_COLUMN:
14078	      avgsol = var->primsolavg;
14079	      avgsol = MAX(avgsol, var->glbdom.lb);
14080	      avgsol = MIN(avgsol, var->glbdom.ub);
14081	      return avgsol;
14082	
14083	   case SCIP_VARSTATUS_FIXED:
14084	      assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
14085	      return var->locdom.lb;
14086	
14087	   case SCIP_VARSTATUS_AGGREGATED:
14088	      assert(!var->donotaggr);
14089	      assert(var->data.aggregate.var != NULL);
14090	      return var->data.aggregate.scalar * SCIPvarGetAvgSol(var->data.aggregate.var)
14091	         + var->data.aggregate.constant;
14092	
14093	   case SCIP_VARSTATUS_MULTAGGR:
14094	      assert(!var->donotmultaggr);
14095	      assert(var->data.multaggr.vars != NULL);
14096	      assert(var->data.multaggr.scalars != NULL);
14097	      /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
14098	       * assert(var->data.multaggr.nvars >= 2); 
14099	       */
14100	      avgsol = var->data.multaggr.constant;
14101	      for( i = 0; i < var->data.multaggr.nvars; ++i )
14102	         avgsol += var->data.multaggr.scalars[i] * SCIPvarGetAvgSol(var->data.multaggr.vars[i]);
14103	      return avgsol;
14104	
14105	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
14106	      assert(var->negatedvar != NULL);
14107	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
14108	      assert(var->negatedvar->negatedvar == var);
14109	      return var->data.negate.constant - SCIPvarGetAvgSol(var->negatedvar);
14110	
14111	   default:
14112	      SCIPerrorMessage("unknown variable status\n");
14113	      SCIPABORT();
14114	      return 0.0; /*lint !e527*/
14115	   }
14116	}
14117	
14118	/** returns solution value and index of variable lower bound that is closest to the variable's value in the given primal solution
14119	 *  or current LP solution if no primal solution is given; returns an index of -1 if no variable lower bound is available
14120	 */
14121	void SCIPvarGetClosestVlb(
14122	   SCIP_VAR*             var,                /**< active problem variable */
14123	   SCIP_SOL*             sol,                /**< primal solution, or NULL for LP solution */
14124	   SCIP_SET*             set,                /**< global SCIP settings */
14125	   SCIP_STAT*            stat,               /**< problem statistics */
14126	   SCIP_Real*            closestvlb,         /**< pointer to store the value of the closest variable lower bound */
14127	   int*                  closestvlbidx       /**< pointer to store the index of the closest variable lower bound */
14128	   )
14129	{
14130	   int nvlbs;
14131	
14132	   assert(var != NULL);
14133	   assert(stat != NULL);
14134	   assert(set != NULL);
14135	   assert(var->scip == set->scip);
14136	   assert(closestvlb != NULL);
14137	   assert(closestvlbidx != NULL);
14138	
14139	   *closestvlbidx = -1;
14140	   *closestvlb = SCIP_REAL_MIN;
14141	
14142	   nvlbs = SCIPvarGetNVlbs(var);
14143	   if( nvlbs > 0 )
14144	   {
14145	      SCIP_VAR** vlbvars;
14146	      SCIP_Real* vlbcoefs;
14147	      SCIP_Real* vlbconsts;
14148	      int i;
14149	
14150	      vlbvars = SCIPvarGetVlbVars(var);
14151	      vlbcoefs = SCIPvarGetVlbCoefs(var);
14152	      vlbconsts = SCIPvarGetVlbConstants(var);
14153	
14154	      /* check for cached values */
14155	      if( var->closestvblpcount == stat->lpcount && var->closestvlbidx != -1 && sol == NULL)
14156	      {
14157	         i = var->closestvlbidx;
14158	         assert(0 <= i && i < nvlbs);
14159	         assert(SCIPvarIsActive(vlbvars[i]));
14160	         *closestvlbidx = i;
14161	         *closestvlb = vlbcoefs[i] * SCIPvarGetLPSol(vlbvars[i]) + vlbconsts[i];
14162	      }
14163	      else
14164	      {
14165	         /* search best VUB */
14166	         for( i = 0; i < nvlbs; i++ )
14167	         {
14168	            if( SCIPvarIsActive(vlbvars[i]) )
14169	            {
14170	               SCIP_Real vlbsol;
14171	
14172	               vlbsol = vlbcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vlbvars[i]) : SCIPsolGetVal(sol, set, stat, vlbvars[i])) + vlbconsts[i];
14173	               if( vlbsol > *closestvlb )
14174	               {
14175	                  *closestvlb = vlbsol;
14176	                  *closestvlbidx = i;
14177	               }
14178	            }
14179	         }
14180	
14181	         if( sol == NULL )
14182	         {
14183	            /* update cached value */
14184	            if( var->closestvblpcount != stat->lpcount )
14185	               var->closestvubidx = -1;
14186	            var->closestvlbidx = *closestvlbidx;
14187	            var->closestvblpcount = stat->lpcount;
14188	         }
14189	      }
14190	   }
14191	}
14192	
14193	/** returns solution value and index of variable upper bound that is closest to the variable's value in the given primal solution;
14194	 *  or current LP solution if no primal solution is given; returns an index of -1 if no variable upper bound is available
14195	 */
14196	void SCIPvarGetClosestVub(
14197	   SCIP_VAR*             var,                /**< active problem variable */
14198	   SCIP_SOL*             sol,                /**< primal solution, or NULL for LP solution */
14199	   SCIP_SET*             set,                /**< global SCIP settings */
14200	   SCIP_STAT*            stat,               /**< problem statistics */
14201	   SCIP_Real*            closestvub,         /**< pointer to store the value of the closest variable upper bound */
14202	   int*                  closestvubidx       /**< pointer to store the index of the closest variable upper bound */
14203	   )
14204	{
14205	   int nvubs;
14206	
14207	   assert(var != NULL);
14208	   assert(set != NULL);
14209	   assert(var->scip == set->scip);
14210	   assert(closestvub != NULL);
14211	   assert(closestvubidx != NULL);
14212	
14213	   *closestvubidx = -1;
14214	   *closestvub = SCIP_REAL_MAX;
14215	
14216	   nvubs = SCIPvarGetNVubs(var);
14217	   if( nvubs > 0 )
14218	   {
14219	      SCIP_VAR** vubvars;
14220	      SCIP_Real* vubcoefs;
14221	      SCIP_Real* vubconsts;
14222	      int i;
14223	
14224	      vubvars = SCIPvarGetVubVars(var);
14225	      vubcoefs = SCIPvarGetVubCoefs(var);
14226	      vubconsts = SCIPvarGetVubConstants(var);
14227	
14228	      /* check for cached values */
14229	      if( var->closestvblpcount == stat->lpcount && var->closestvubidx != -1 && sol == NULL)
14230	      {
14231	         i = var->closestvubidx;
14232	         assert(0 <= i && i < nvubs);
14233	         assert(SCIPvarIsActive(vubvars[i]));
14234	         *closestvubidx = i;
14235	         *closestvub = vubcoefs[i] * SCIPvarGetLPSol(vubvars[i]) + vubconsts[i];
14236	      }
14237	      else
14238	      {
14239	         /* search best VUB */
14240	         for( i = 0; i < nvubs; i++ )
14241	         {
14242	            if( SCIPvarIsActive(vubvars[i]) )
14243	            {
14244	               SCIP_Real vubsol;
14245	
14246	               vubsol = vubcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vubvars[i]) : SCIPsolGetVal(sol, set, stat, vubvars[i])) + vubconsts[i];
14247	               if( vubsol < *closestvub )
14248	               {
14249	                  *closestvub = vubsol;
14250	                  *closestvubidx = i;
14251	               }
14252	            }
14253	         }
14254	
14255	         if( sol == NULL )
14256	         {
14257	            /* update cached value */
14258	            if( var->closestvblpcount != stat->lpcount )
14259	               var->closestvlbidx = -1;
14260	            var->closestvubidx = *closestvubidx;
14261	            var->closestvblpcount = stat->lpcount;
14262	         }
14263	      }
14264	   }
14265	}
14266	
14267	/** resolves variable to columns and adds them with the coefficient to the row */
14268	SCIP_RETCODE SCIPvarAddToRow(
14269	   SCIP_VAR*             var,                /**< problem variable */
14270	   BMS_BLKMEM*           blkmem,             /**< block memory */
14271	   SCIP_SET*             set,                /**< global SCIP settings */
14272	   SCIP_STAT*            stat,               /**< problem statistics */
14273	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
14274	   SCIP_PROB*            prob,               /**< problem data */
14275	   SCIP_LP*              lp,                 /**< current LP data */
14276	   SCIP_ROW*             row,                /**< LP row */
14277	   SCIP_Real             val                 /**< value of coefficient */
14278	   )
14279	{
14280	   int i;
14281	
14282	   assert(var != NULL);
14283	   assert(set != NULL);
14284	   assert(var->scip == set->scip);
14285	   assert(row != NULL);
14286	   assert(!SCIPsetIsInfinity(set, REALABS(val)));
14287	
14288	   SCIPsetDebugMsg(set, "adding coefficient %g<%s> to row <%s>\n", val, var->name, row->name);
14289	
14290	   if ( SCIPsetIsZero(set, val) )
14291	      return SCIP_OKAY;
14292	
14293	   switch( SCIPvarGetStatus(var) )
14294	   {
14295	   case SCIP_VARSTATUS_ORIGINAL:
14296	      if( var->data.original.transvar == NULL )
14297	      {
14298	         SCIPerrorMessage("cannot add untransformed original variable <%s> to LP row <%s>\n", var->name, row->name);
14299	         return SCIP_INVALIDDATA;
14300	      }
14301	      SCIP_CALL( SCIPvarAddToRow(var->data.original.transvar, blkmem, set, stat, eventqueue, prob, lp, row, val) );
14302	      return SCIP_OKAY;
14303	
14304	   case SCIP_VARSTATUS_LOOSE:
14305	      /* add globally fixed variables as constant */
14306	      if( SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub) )
14307	      {
14308	         SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->glbdom.lb) );
14309	         return SCIP_OKAY;
14310	      }
14311	      /* convert loose variable into column */
14312	      SCIP_CALL( SCIPvarColumn(var, blkmem, set, stat, prob, lp) );
14313	      assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
14314	      /*lint -fallthrough*/
14315	
14316	   case SCIP_VARSTATUS_COLUMN:
14317	      assert(var->data.col != NULL);
14318	      assert(var->data.col->var == var);
14319	      SCIP_CALL( SCIProwIncCoef(row, blkmem, set, eventqueue, lp, var->data.col, val) );
14320	      return SCIP_OKAY;
14321	
14322	   case SCIP_VARSTATUS_FIXED:
14323	      assert(var->glbdom.lb == var->glbdom.ub); /*lint !e777*/
14324	      assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
14325	      assert(var->locdom.lb == var->glbdom.lb); /*lint !e777*/
14326	      assert(!SCIPsetIsInfinity(set, REALABS(var->locdom.lb)));
14327	      SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->locdom.lb) );
14328	      return SCIP_OKAY;
14329	
14330	   case SCIP_VARSTATUS_AGGREGATED:
14331	      assert(!var->donotaggr);
14332	      assert(var->data.aggregate.var != NULL);
14333	      SCIP_CALL( SCIPvarAddToRow(var->data.aggregate.var, blkmem, set, stat, eventqueue, prob, lp,
14334	            row, var->data.aggregate.scalar * val) );
14335	      SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.aggregate.constant * val) );
14336	      return SCIP_OKAY;
14337	
14338	   case SCIP_VARSTATUS_MULTAGGR:
14339	      assert(!var->donotmultaggr);
14340	      assert(var->data.multaggr.vars != NULL);
14341	      assert(var->data.multaggr.scalars != NULL);
14342	      /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
14343	       * assert(var->data.multaggr.nvars >= 2); 
14344	       */
14345	      for( i = 0; i < var->data.multaggr.nvars; ++i )
14346	      {
14347	         SCIP_CALL( SCIPvarAddToRow(var->data.multaggr.vars[i], blkmem, set, stat, eventqueue, prob, lp,
14348	               row, var->data.multaggr.scalars[i] * val) );
14349	      }
14350	      SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.multaggr.constant * val) );
14351	      return SCIP_OKAY;
14352	
14353	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
14354	      assert(var->negatedvar != NULL);
14355	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
14356	      assert(var->negatedvar->negatedvar == var);
14357	      SCIP_CALL( SCIPvarAddToRow(var->negatedvar, blkmem, set, stat, eventqueue, prob, lp, row, -val) );
14358	      SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.negate.constant * val) );
14359	      return SCIP_OKAY;
14360	
14361	   default:
14362	      SCIPerrorMessage("unknown variable status\n");
14363	      return SCIP_INVALIDDATA;
14364	   }
14365	}
14366	
14367	/* optionally, define this compiler flag to write complete variable histories to a file */
14368	#ifdef SCIP_HISTORYTOFILE
14369	SCIP_Longint counter = 0l;
14370	const char* historypath="."; /* allows for user-defined path; use '.' for calling directory of SCIP */
14371	#include "scip/scip.h"
14372	#endif
14373	
14374	/** updates the pseudo costs of the given variable and the global pseudo costs after a change of
14375	 *  "solvaldelta" in the variable's solution value and resulting change of "objdelta" in the in the LP's objective value
14376	 */
14377	SCIP_RETCODE SCIPvarUpdatePseudocost(
14378	   SCIP_VAR*             var,                /**< problem variable */
14379	   SCIP_SET*             set,                /**< global SCIP settings */
14380	   SCIP_STAT*            stat,               /**< problem statistics */
14381	   SCIP_Real             solvaldelta,        /**< difference of variable's new LP value - old LP value */
14382	   SCIP_Real             objdelta,           /**< difference of new LP's objective value - old LP's objective value */
14383	   SCIP_Real             weight              /**< weight in (0,1] of this update in pseudo cost sum */
14384	   )
14385	{
14386	   SCIP_Real oldrootpseudocosts;
14387	   assert(var != NULL);
14388	   assert(set != NULL);
14389	   assert(var->scip == set->scip);
14390	   assert(stat != NULL);
14391	
14392	   /* check if history statistics should be collected for a variable */
14393	   if( !stat->collectvarhistory )
14394	      return SCIP_OKAY;
14395	
14396	   switch( SCIPvarGetStatus(var) )
14397	   {
14398	   case SCIP_VARSTATUS_ORIGINAL:
14399	      if( var->data.original.transvar == NULL )
14400	      {
14401	         SCIPerrorMessage("cannot update pseudo costs of original untransformed variable\n");
14402	         return SCIP_INVALIDDATA;
14403	      }
14404	      SCIP_CALL( SCIPvarUpdatePseudocost(var->data.original.transvar, set, stat, solvaldelta, objdelta, weight) );
14405	      return SCIP_OKAY;
14406	
14407	   case SCIP_VARSTATUS_LOOSE:
14408	   case SCIP_VARSTATUS_COLUMN:
14409	      /* store old pseudo-costs for root LP best-estimate update */
14410	      oldrootpseudocosts = SCIPvarGetMinPseudocostScore(var, stat, set, SCIPvarGetRootSol(var));
14411	
14412	      /* update history */
14413	      SCIPhistoryUpdatePseudocost(var->history, set, solvaldelta, objdelta, weight);
14414	      SCIPhistoryUpdatePseudocost(var->historycrun, set, solvaldelta, objdelta, weight);
14415	      SCIPhistoryUpdatePseudocost(stat->glbhistory, set, solvaldelta, objdelta, weight);
14416	      SCIPhistoryUpdatePseudocost(stat->glbhistorycrun, set, solvaldelta, objdelta, weight);
14417	
14418	      /* update root LP best-estimate */
14419	      SCIP_CALL( SCIPstatUpdateVarRootLPBestEstimate(stat, set, var, oldrootpseudocosts) );
14420	
14421	      /* append history to file */
14422	#ifdef SCIP_HISTORYTOFILE
14423	   {
14424	      FILE* f;
14425	      char filename[256];
14426	      SCIP_NODE* currentnode;
14427	      SCIP_NODE* parentnode;
14428	      currentnode = SCIPgetFocusNode(set->scip);
14429	      parentnode = SCIPnodeGetParent(currentnode);
14430	
14431	      sprintf(filename, "%s/%s.pse", historypath, SCIPgetProbName(set->scip));
14432	      f = fopen(filename, "a");
14433	      if( NULL != f )
14434	      {
14435	         fprintf(f, "%lld %s \t %lld \t %lld \t %lld \t %d \t %15.9f \t %.3f\n",
14436	            ++counter,
14437	            SCIPvarGetName(var),
14438	            SCIPnodeGetNumber(currentnode),
14439	            parentnode != NULL ? SCIPnodeGetNumber(parentnode) : -1,
14440	            SCIPgetNLPIterations(set->scip),
14441	            SCIPgetDepth(set->scip),
14442	            objdelta,
14443	            solvaldelta);
14444	         fclose(f);
14445	      }
14446	   }
14447	#endif
14448	      return SCIP_OKAY;
14449	
14450	   case SCIP_VARSTATUS_FIXED:
14451	      SCIPerrorMessage("cannot update pseudo cost values of a fixed variable\n");
14452	      return SCIP_INVALIDDATA;
14453	
14454	   case SCIP_VARSTATUS_AGGREGATED:
14455	      assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
14456	      SCIP_CALL( SCIPvarUpdatePseudocost(var->data.aggregate.var, set, stat,
14457	            solvaldelta/var->data.aggregate.scalar, objdelta, weight) );
14458	      return SCIP_OKAY;
14459	
14460	   case SCIP_VARSTATUS_MULTAGGR:
14461	      SCIPerrorMessage("cannot update pseudo cost values of a multi-aggregated variable\n");
14462	      return SCIP_INVALIDDATA;
14463	
14464	   case SCIP_VARSTATUS_NEGATED:
14465	      SCIP_CALL( SCIPvarUpdatePseudocost(var->negatedvar, set, stat, -solvaldelta, objdelta, weight) );
14466	      return SCIP_OKAY;
14467	
14468	   default:
14469	      SCIPerrorMessage("unknown variable status\n");
14470	      return SCIP_INVALIDDATA;
14471	   }
14472	}
14473	
14474	/** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value */
14475	SCIP_Real SCIPvarGetPseudocost(
14476	   SCIP_VAR*             var,                /**< problem variable */
14477	   SCIP_STAT*            stat,               /**< problem statistics */
14478	   SCIP_Real             solvaldelta         /**< difference of variable's new LP value - old LP value */
14479	   )
14480	{
14481	   SCIP_BRANCHDIR dir;
14482	
14483	   assert(var != NULL);
14484	   assert(stat != NULL);
14485	
14486	   switch( SCIPvarGetStatus(var) )
14487	   {
14488	   case SCIP_VARSTATUS_ORIGINAL:
14489	      if( var->data.original.transvar == NULL )
14490	         return SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
14491	      else
14492	         return SCIPvarGetPseudocost(var->data.original.transvar, stat, solvaldelta);
14493	
14494	   case SCIP_VARSTATUS_LOOSE:
14495	   case SCIP_VARSTATUS_COLUMN:
14496	      dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
14497	
14498	      return SCIPhistoryGetPseudocostCount(var->history, dir) > 0.0
14499	         ? SCIPhistoryGetPseudocost(var->history, solvaldelta)
14500	         : SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
14501	
14502	   case SCIP_VARSTATUS_FIXED:
14503	      return 0.0;
14504	
14505	   case SCIP_VARSTATUS_AGGREGATED:
14506	      return SCIPvarGetPseudocost(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
14507	
14508	   case SCIP_VARSTATUS_MULTAGGR:
14509	      return 0.0;
14510	
14511	   case SCIP_VARSTATUS_NEGATED:
14512	      return SCIPvarGetPseudocost(var->negatedvar, stat, -solvaldelta);
14513	
14514	   default:
14515	      SCIPerrorMessage("unknown variable status\n");
14516	      SCIPABORT();
14517	      return 0.0; /*lint !e527*/
14518	   }
14519	}
14520	
14521	/** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value,
14522	 *  only using the pseudo cost information of the current run
14523	 */
14524	SCIP_Real SCIPvarGetPseudocostCurrentRun(
14525	   SCIP_VAR*             var,                /**< problem variable */
14526	   SCIP_STAT*            stat,               /**< problem statistics */
14527	   SCIP_Real             solvaldelta         /**< difference of variable's new LP value - old LP value */
14528	   )
14529	{
14530	   SCIP_BRANCHDIR dir;
14531	
14532	   assert(var != NULL);
14533	   assert(stat != NULL);
14534	
14535	   switch( SCIPvarGetStatus(var) )
14536	   {
14537	   case SCIP_VARSTATUS_ORIGINAL:
14538	      if( var->data.original.transvar == NULL )
14539	         return SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
14540	      else
14541	         return SCIPvarGetPseudocostCurrentRun(var->data.original.transvar, stat, solvaldelta);
14542	
14543	   case SCIP_VARSTATUS_LOOSE:
14544	   case SCIP_VARSTATUS_COLUMN:
14545	      dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
14546	
14547	      return SCIPhistoryGetPseudocostCount(var->historycrun, dir) > 0.0
14548	         ? SCIPhistoryGetPseudocost(var->historycrun, solvaldelta)
14549	         : SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
14550	
14551	   case SCIP_VARSTATUS_FIXED:
14552	      return 0.0;
14553	
14554	   case SCIP_VARSTATUS_AGGREGATED:
14555	      return SCIPvarGetPseudocostCurrentRun(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
14556	
14557	   case SCIP_VARSTATUS_MULTAGGR:
14558	      return 0.0;
14559	
14560	   case SCIP_VARSTATUS_NEGATED:
14561	      return SCIPvarGetPseudocostCurrentRun(var->negatedvar, stat, -solvaldelta);
14562	
14563	   default:
14564	      SCIPerrorMessage("unknown variable status\n");
14565	      SCIPABORT();
14566	      return 0.0; /*lint !e527*/
14567	   }
14568	}
14569	
14570	/** gets the variable's (possible fractional) number of pseudo cost updates for the given direction */
14571	SCIP_Real SCIPvarGetPseudocostCount(
14572	   SCIP_VAR*             var,                /**< problem variable */
14573	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
14574	   )
14575	{
14576	   assert(var != NULL);
14577	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14578	
14579	   switch( SCIPvarGetStatus(var) )
14580	   {
14581	   case SCIP_VARSTATUS_ORIGINAL:
14582	      if( var->data.original.transvar == NULL )
14583	         return 0.0;
14584	      else
14585	         return SCIPvarGetPseudocostCount(var->data.original.transvar, dir);
14586	
14587	   case SCIP_VARSTATUS_LOOSE:
14588	   case SCIP_VARSTATUS_COLUMN:
14589	      return SCIPhistoryGetPseudocostCount(var->history, dir);
14590	
14591	   case SCIP_VARSTATUS_FIXED:
14592	      return 0.0;
14593	
14594	   case SCIP_VARSTATUS_AGGREGATED:
14595	      if( var->data.aggregate.scalar > 0.0 )
14596	         return SCIPvarGetPseudocostCount(var->data.aggregate.var, dir);
14597	      else
14598	         return SCIPvarGetPseudocostCount(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
14599	
14600	   case SCIP_VARSTATUS_MULTAGGR:
14601	      return 0.0;
14602	
14603	   case SCIP_VARSTATUS_NEGATED:
14604	      return SCIPvarGetPseudocostCount(var->negatedvar, SCIPbranchdirOpposite(dir));
14605	
14606	   default:
14607	      SCIPerrorMessage("unknown variable status\n");
14608	      SCIPABORT();
14609	      return 0.0; /*lint !e527*/
14610	   }
14611	}
14612	
14613	/** gets the variable's (possible fractional) number of pseudo cost updates for the given direction,
14614	 *  only using the pseudo cost information of the current run
14615	 */
14616	SCIP_Real SCIPvarGetPseudocostCountCurrentRun(
14617	   SCIP_VAR*             var,                /**< problem variable */
14618	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
14619	   )
14620	{
14621	   assert(var != NULL);
14622	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14623	
14624	   switch( SCIPvarGetStatus(var) )
14625	   {
14626	   case SCIP_VARSTATUS_ORIGINAL:
14627	      if( var->data.original.transvar == NULL )
14628	         return 0.0;
14629	      else
14630	         return SCIPvarGetPseudocostCountCurrentRun(var->data.original.transvar, dir);
14631	
14632	   case SCIP_VARSTATUS_LOOSE:
14633	   case SCIP_VARSTATUS_COLUMN:
14634	      return SCIPhistoryGetPseudocostCount(var->historycrun, dir);
14635	
14636	   case SCIP_VARSTATUS_FIXED:
14637	      return 0.0;
14638	
14639	   case SCIP_VARSTATUS_AGGREGATED:
14640	      if( var->data.aggregate.scalar > 0.0 )
14641	         return SCIPvarGetPseudocostCountCurrentRun(var->data.aggregate.var, dir);
14642	      else
14643	         return SCIPvarGetPseudocostCountCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
14644	
14645	   case SCIP_VARSTATUS_MULTAGGR:
14646	      return 0.0;
14647	
14648	   case SCIP_VARSTATUS_NEGATED:
14649	      return SCIPvarGetPseudocostCountCurrentRun(var->negatedvar, SCIPbranchdirOpposite(dir));
14650	
14651	   default:
14652	      SCIPerrorMessage("unknown variable status\n");
14653	      SCIPABORT();
14654	      return 0.0; /*lint !e527*/
14655	   }
14656	}
14657	
14658	/** compares both possible directions for rounding the given solution value and returns the minimum pseudo-costs of the variable */
14659	SCIP_Real SCIPvarGetMinPseudocostScore(
14660	   SCIP_VAR*             var,                /**< problem variable */
14661	   SCIP_STAT*            stat,               /**< problem statistics */
14662	   SCIP_SET*             set,                /**< global SCIP settings */
14663	   SCIP_Real             solval              /**< solution value, e.g., LP solution value */
14664	   )
14665	{
14666	   SCIP_Real upscore;
14667	   SCIP_Real downscore;
14668	   SCIP_Real solvaldeltaup;
14669	   SCIP_Real solvaldeltadown;
14670	
14671	   /* LP root estimate only works for variables with fractional LP root solution */
14672	   if( SCIPsetIsFeasIntegral(set, solval) )
14673	      return 0.0;
14674	
14675	   /* no min pseudo-cost score is calculated as long as the variable was not initialized in a direction */
14676	   if( SCIPvarGetPseudocostCount(var, SCIP_BRANCHDIR_DOWNWARDS) < 1.0 || SCIPvarGetPseudocostCount(var, SCIP_BRANCHDIR_UPWARDS) < 1.0 )
14677	      return 0.0;
14678	
14679	   /* compute delta's to ceil and floor of root LP solution value */
14680	   solvaldeltaup = SCIPsetCeil(set, solval) - solval;
14681	   solvaldeltadown = SCIPsetFloor(set, solval) - solval;
14682	
14683	   upscore = SCIPvarGetPseudocost(var, stat, solvaldeltaup);
14684	   downscore = SCIPvarGetPseudocost(var, stat, solvaldeltadown);
14685	
14686	   return MIN(upscore, downscore);
14687	}
14688	
14689	/** gets the an estimate of the variable's pseudo cost variance in direction \p dir */
14690	SCIP_Real SCIPvarGetPseudocostVariance(
14691	   SCIP_VAR*             var,                /**< problem variable */
14692	   SCIP_BRANCHDIR        dir,                /**< branching direction (downwards, or upwards) */
14693	   SCIP_Bool             onlycurrentrun      /**< return pseudo cost variance only for current branch and bound run */
14694	   )
14695	{
14696	   assert(var != NULL);
14697	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14698	
14699	   switch( SCIPvarGetStatus(var) )
14700	   {
14701	   case SCIP_VARSTATUS_ORIGINAL:
14702	      if( var->data.original.transvar == NULL )
14703	         return 0.0;
14704	      else
14705	         return SCIPvarGetPseudocostVariance(var->data.original.transvar, dir, onlycurrentrun);
14706	
14707	   case SCIP_VARSTATUS_LOOSE:
14708	   case SCIP_VARSTATUS_COLUMN:
14709	      if( onlycurrentrun )
14710	         return SCIPhistoryGetPseudocostVariance(var->historycrun, dir);
14711	      else
14712	         return SCIPhistoryGetPseudocostVariance(var->history, dir);
14713	
14714	   case SCIP_VARSTATUS_FIXED:
14715	      return 0.0;
14716	
14717	   case SCIP_VARSTATUS_AGGREGATED:
14718	      if( var->data.aggregate.scalar > 0.0 )
14719	         return SCIPvarGetPseudocostVariance(var->data.aggregate.var, dir, onlycurrentrun);
14720	      else
14721	         return SCIPvarGetPseudocostVariance(var->data.aggregate.var, SCIPbranchdirOpposite(dir), onlycurrentrun);
14722	
14723	   case SCIP_VARSTATUS_MULTAGGR:
14724	      return 0.0;
14725	
14726	   case SCIP_VARSTATUS_NEGATED:
14727	      return SCIPvarGetPseudocostVariance(var->negatedvar, SCIPbranchdirOpposite(dir), onlycurrentrun);
14728	
14729	   default:
14730	      SCIPerrorMessage("unknown variable status\n");
14731	      SCIPABORT();
14732	      return 0.0; /*lint !e527*/
14733	   }
14734	}
14735	
14736	/** calculates a confidence bound for this variable under the assumption of normally distributed pseudo costs
14737	 *
14738	 *  The confidence bound \f$ \theta \geq 0\f$ denotes the interval borders \f$ [X - \theta, \ X + \theta]\f$, which contains
14739	 *  the true pseudo costs of the variable, i.e., the expected value of the normal distribution, with a probability
14740	 *  of 2 * clevel - 1.
14741	 *
14742	 *  @return value of confidence bound for this variable
14743	 */
14744	SCIP_Real SCIPvarCalcPscostConfidenceBound(
14745	   SCIP_VAR*             var,                /**< variable in question */
14746	   SCIP_SET*             set,                /**< global SCIP settings */
14747	   SCIP_BRANCHDIR        dir,                /**< the branching direction for the confidence bound */
14748	   SCIP_Bool             onlycurrentrun,     /**< should only the current run be taken into account */
14749	   SCIP_CONFIDENCELEVEL  clevel              /**< confidence level for the interval */
14750	   )
14751	{
14752	   SCIP_Real confidencebound;
14753	
14754	   confidencebound = SCIPvarGetPseudocostVariance(var, dir, onlycurrentrun);
14755	   if( SCIPsetIsFeasPositive(set, confidencebound) )
14756	   {
14757	      SCIP_Real count;
14758	
14759	      if( onlycurrentrun )
14760	         count = SCIPvarGetPseudocostCountCurrentRun(var, dir);
14761	      else
14762	         count = SCIPvarGetPseudocostCount(var, dir);
14763	      /* assertion is valid because variance is positive */
14764	      assert(count >= 1.9);
14765	
14766	      confidencebound /= count; /*lint !e414 division by zero can obviously not occur */
14767	      confidencebound = sqrt(confidencebound);
14768	
14769	      /* the actual, underlying distribution of the mean is a student-t-distribution with degrees of freedom equal to
14770	       * the number of pseudo cost evaluations of this variable in the respective direction. */
14771	      confidencebound *= SCIPstudentTGetCriticalValue(clevel, (int)SCIPsetFloor(set, count) - 1);
14772	   }
14773	   else
14774	      confidencebound = 0.0;
14775	
14776	   return confidencebound;
14777	}
14778	
14779	/** check if the current pseudo cost relative error in a direction violates the given threshold. The Relative
14780	 *  Error is calculated at a specific confidence level
14781	 */
14782	SCIP_Bool SCIPvarIsPscostRelerrorReliable(
14783	   SCIP_VAR*             var,                /**< variable in question */
14784	   SCIP_SET*             set,                /**< global SCIP settings */
14785	   SCIP_STAT*            stat,               /**< problem statistics */
14786	   SCIP_Real             threshold,          /**< threshold for relative errors to be considered reliable (enough) */
14787	   SCIP_CONFIDENCELEVEL  clevel              /**< a given confidence level */
14788	   )
14789	{
14790	   SCIP_Real downsize;
14791	   SCIP_Real upsize;
14792	   SCIP_Real size;
14793	   SCIP_Real relerrorup;
14794	   SCIP_Real relerrordown;
14795	   SCIP_Real relerror;
14796	
14797	   /* check, if the pseudo cost score of the variable is reliable */
14798	   downsize = SCIPvarGetPseudocostCountCurrentRun(var, SCIP_BRANCHDIR_DOWNWARDS);
14799	   upsize = SCIPvarGetPseudocostCountCurrentRun(var, SCIP_BRANCHDIR_UPWARDS);
14800	   size = MIN(downsize, upsize);
14801	
14802	   /* Pseudo costs relative error can only be reliable if both directions have been tried at least twice */
14803	   if( size <= 1.9 )
14804	      return FALSE;
14805	
14806	   /* use the relative error between the current mean pseudo cost value of the candidate and its upper
14807	    * confidence interval bound at confidence level of 95% for individual variable reliability.
14808	    * this is only possible if we have at least 2 measurements and therefore a valid variance estimate.
14809	    */
14810	   if( downsize >= 1.9 )
14811	   {
14812	      SCIP_Real normval;
14813	
14814	      relerrordown = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_DOWNWARDS, TRUE, clevel);
14815	      normval = SCIPvarGetPseudocostCurrentRun(var, stat, -1.0);
14816	      normval = MAX(1.0, normval);
14817	
14818	      relerrordown /= normval;
14819	   }
14820	   else
14821	      relerrordown = 0.0;
14822	
14823	   if( upsize >= 1.9 )
14824	   {
14825	      SCIP_Real normval;
14826	
14827	      relerrorup = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_UPWARDS, TRUE, clevel);
14828	      normval = SCIPvarGetPseudocostCurrentRun(var, stat, +1.0);
14829	      normval = MAX(1.0, normval);
14830	      relerrorup /= normval;
14831	   }
14832	   else
14833	      relerrorup = 0.0;
14834	
14835	   /* consider the relative error threshold violated, if it is violated in at least one branching direction */
14836	   relerror = MAX(relerrorup, relerrordown);
14837	
14838	   return (relerror <= threshold);
14839	}
14840	
14841	/** check if variable pseudo-costs have a significant difference in location. The significance depends on
14842	 *  the choice of \p clevel and on the kind of tested hypothesis. The one-sided hypothesis, which
14843	 *  should be rejected, is that fracy * mu_y >= fracx * mu_x, where mu_y and mu_x denote the
14844	 *  unknown location means of the underlying pseudo-cost distributions of x and y.
14845	 *
14846	 *  This method is applied best if variable x has a better pseudo-cost score than y. The method hypothesizes that y were actually
14847	 *  better than x (despite the current information), meaning that y can be expected to yield branching
14848	 *  decisions as least as good as x in the long run. If the method returns TRUE, the current history information is
14849	 *  sufficient to safely rely on the alternative hypothesis that x yields indeed a better branching score (on average)
14850	 *  than y.
14851	 *
14852	 *  @note The order of x and y matters for the one-sided hypothesis
14853	 *
14854	 *  @note set \p onesided to FALSE if you are not sure which variable is better. The hypothesis tested then reads
14855	 *        fracy * mu_y == fracx * mu_x vs the alternative hypothesis fracy * mu_y != fracx * mu_x.
14856	 *
14857	 *  @return TRUE if the hypothesis can be safely rejected at the given confidence level
14858	 */
14859	SCIP_Bool SCIPvarSignificantPscostDifference(
14860	   SCIP_SET*             set,                /**< global SCIP settings */
14861	   SCIP_STAT*            stat,               /**< problem statistics */
14862	   SCIP_VAR*             varx,               /**< variable x */
14863	   SCIP_Real             fracx,              /**< the fractionality of variable x */
14864	   SCIP_VAR*             vary,               /**< variable y */
14865	   SCIP_Real             fracy,              /**< the fractionality of variable y */
14866	   SCIP_BRANCHDIR        dir,                /**< branching direction */
14867	   SCIP_CONFIDENCELEVEL  clevel,             /**< confidence level for rejecting hypothesis */
14868	   SCIP_Bool             onesided            /**< should a one-sided hypothesis y >= x be tested? */
14869	   )
14870	{
14871	   SCIP_Real meanx;
14872	   SCIP_Real meany;
14873	   SCIP_Real variancex;
14874	   SCIP_Real variancey;
14875	   SCIP_Real countx;
14876	   SCIP_Real county;
14877	   SCIP_Real tresult;
14878	   SCIP_Real realdirection;
14879	
14880	   if( varx == vary )
14881	      return FALSE;
14882	
14883	   countx = SCIPvarGetPseudocostCount(varx, dir);
14884	   county = SCIPvarGetPseudocostCount(vary, dir);
14885	
14886	   /* if not at least 2 measurements were taken, return FALSE */
14887	   if( countx <= 1.9 || county <= 1.9 )
14888	      return FALSE;
14889	
14890	   realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14891	
14892	   meanx = fracx * SCIPvarGetPseudocost(varx, stat, realdirection);
14893	   meany = fracy * SCIPvarGetPseudocost(vary, stat, realdirection);
14894	
14895	   variancex = SQR(fracx) * SCIPvarGetPseudocostVariance(varx, dir, FALSE);
14896	   variancey = SQR(fracy) * SCIPvarGetPseudocostVariance(vary, dir, FALSE);
14897	
14898	   /* if there is no variance, the means are taken from a constant distribution */
14899	   if( SCIPsetIsFeasEQ(set, variancex + variancey, 0.0) )
14900	      return (onesided ? SCIPsetIsFeasGT(set, meanx, meany) : !SCIPsetIsFeasEQ(set, meanx, meany));
14901	
14902	   tresult = SCIPcomputeTwoSampleTTestValue(meanx, meany, variancex, variancey, countx, county);
14903	
14904	   /* for the two-sided hypothesis, just take the absolute of t */
14905	   if( !onesided )
14906	      tresult = REALABS(tresult);
14907	
14908	   return (tresult >= SCIPstudentTGetCriticalValue(clevel, (int)(countx + county - 2)));
14909	}
14910	
14911	/** tests at a given confidence level whether the variable pseudo-costs only have a small probability to
14912	 *  exceed a \p threshold. This is useful to determine if past observations provide enough evidence
14913	 *  to skip an expensive strong-branching step if there is already a candidate that has been proven to yield an improvement
14914	 *  of at least \p threshold.
14915	 *
14916	 *  @note use \p clevel to adjust the level of confidence. For SCIP_CONFIDENCELEVEL_MIN, the method returns TRUE if
14917	 *        the estimated probability to exceed \p threshold is less than 25 %.
14918	 *
14919	 *  @see  SCIP_Confidencelevel for a list of available levels. The used probability limits refer to the one-sided levels
14920	 *        of confidence.
14921	 *
14922	 *  @return TRUE if the variable pseudo-cost probabilistic model is likely to be smaller than \p threshold
14923	 *          at the given confidence level \p clevel.
14924	 */
14925	SCIP_Bool SCIPvarPscostThresholdProbabilityTest(
14926	   SCIP_SET*             set,                /**< global SCIP settings */
14927	   SCIP_STAT*            stat,               /**< problem statistics */
14928	   SCIP_VAR*             var,                /**< variable x */
14929	   SCIP_Real             frac,               /**< the fractionality of variable x */
14930	   SCIP_Real             threshold,          /**< the threshold to test against */
14931	   SCIP_BRANCHDIR        dir,                /**< branching direction */
14932	   SCIP_CONFIDENCELEVEL  clevel              /**< confidence level for rejecting hypothesis */
14933	   )
14934	{
14935	   SCIP_Real mean;
14936	   SCIP_Real variance;
14937	   SCIP_Real count;
14938	   SCIP_Real realdirection;
14939	   SCIP_Real probability;
14940	   SCIP_Real problimit;
14941	
14942	   count = SCIPvarGetPseudocostCount(var, dir);
14943	
14944	   /* if not at least 2 measurements were taken, return FALSE */
14945	   if( count <= 1.9 )
14946	      return FALSE;
14947	
14948	   realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14949	
14950	   mean = frac * SCIPvarGetPseudocost(var, stat, realdirection);
14951	   variance = SQR(frac) * SCIPvarGetPseudocostVariance(var, dir, FALSE);
14952	
14953	   /* if mean is at least threshold, it has at least a 50% probability to exceed threshold, we therefore return FALSE */
14954	   if( SCIPsetIsFeasGE(set, mean, threshold) )
14955	      return FALSE;
14956	
14957	   /* if there is no variance, the means are taken from a constant distribution */
14958	   if( SCIPsetIsFeasEQ(set, variance, 0.0) )
14959	      return SCIPsetIsFeasLT(set, mean, threshold);
14960	
14961	   /* obtain probability of a normally distributed random variable at given mean and variance to yield at most threshold */
14962	   probability = SCIPnormalCDF(mean, variance, threshold);
14963	
14964	   /* determine a probability limit corresponding to the given confidence level */
14965	   switch( clevel )
14966	   {
14967	      case SCIP_CONFIDENCELEVEL_MIN:
14968	         problimit = 0.75;
14969	         break;
14970	      case SCIP_CONFIDENCELEVEL_LOW:
14971	         problimit = 0.875;
14972	         break;
14973	      case SCIP_CONFIDENCELEVEL_MEDIUM:
14974	         problimit = 0.9;
14975	         break;
14976	      case SCIP_CONFIDENCELEVEL_HIGH:
14977	         problimit = 0.95;
14978	         break;
14979	      case SCIP_CONFIDENCELEVEL_MAX:
14980	         problimit = 0.975;
14981	         break;
14982	      default:
14983	         problimit = -1;
14984	         SCIPerrorMessage("Confidence level set to unknown value <%d>", (int)clevel);
14985	         SCIPABORT();
14986	         break;
14987	   }
14988	
14989	   return (probability >= problimit);
14990	}
14991	
14992	/** find the corresponding history entry if already existing, otherwise create new entry */
14993	static
14994	SCIP_RETCODE findValuehistoryEntry(
14995	   SCIP_VAR*             var,                /**< problem variable */
14996	   SCIP_Real             value,              /**< domain value, or SCIP_UNKNOWN */
14997	   BMS_BLKMEM*           blkmem,             /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14998	   SCIP_SET*             set,                /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14999	   SCIP_HISTORY**        history             /**< pointer to store the value based history, or NULL */
15000	   )
15001	{
15002	   assert(var != NULL);
15003	   assert(blkmem != NULL);
15004	   assert(set != NULL);
15005	   assert(history != NULL);
15006	
15007	   (*history) = NULL;
15008	
15009	   if( var->valuehistory == NULL )
15010	   {
15011	      SCIP_CALL( SCIPvaluehistoryCreate(&var->valuehistory, blkmem) );
15012	   }
15013	
15014	   SCIP_CALL( SCIPvaluehistoryFind(var->valuehistory, blkmem, set, value, history) );
15015	
15016	   return SCIP_OKAY;
15017	}
15018	
15019	/** check if value based history should be used */
15020	static
15021	SCIP_Bool useValuehistory(
15022	   SCIP_VAR*             var,                /**< problem variable */
15023	   SCIP_Real             value,              /**< domain value, or SCIP_UNKNOWN */
15024	   SCIP_SET*             set                 /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15025	   )
15026	{
15027	   /* check if the domain value is unknown (not specific) */
15028	   if( value == SCIP_UNKNOWN ) /*lint !e777*/
15029	      return FALSE;
15030	
15031	   assert(set != NULL);
15032	
15033	   /* check if value based history should be collected */
15034	   if( !set->history_valuebased )
15035	      return FALSE;
15036	
15037	   /* value based history is not collected for binary variable since the standard history already contains all information */
15038	   if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
15039	      return FALSE;
15040	
15041	   /* value based history is not collected for continuous variables */
15042	   if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS )
15043	      return FALSE;
15044	
15045	   return TRUE;
15046	}
15047	
15048	/** increases VSIDS of the variable by the given weight */
15049	SCIP_RETCODE SCIPvarIncVSIDS(
15050	   SCIP_VAR*             var,                /**< problem variable */
15051	   BMS_BLKMEM*           blkmem,             /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15052	   SCIP_SET*             set,                /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15053	   SCIP_STAT*            stat,               /**< problem statistics */
15054	   SCIP_BRANCHDIR        dir,                /**< branching direction */
15055	   SCIP_Real             value,              /**< domain value, or SCIP_UNKNOWN */
15056	   SCIP_Real             weight              /**< weight of this update in VSIDS */
15057	   )
15058	{
15059	   assert(var != NULL);
15060	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15061	
15062	   /* check if history statistics should be collected for a variable */
15063	   if( !stat->collectvarhistory )
15064	      return SCIP_OKAY;
15065	
15066	   if( SCIPsetIsZero(set, weight) )
15067	      return SCIP_OKAY;
15068	
15069	   switch( SCIPvarGetStatus(var) )
15070	   {
15071	   case SCIP_VARSTATUS_ORIGINAL:
15072	      if( var->data.original.transvar == NULL )
15073	      {
15074	         SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
15075	         return SCIP_INVALIDDATA;
15076	      }
15077	      SCIP_CALL( SCIPvarIncVSIDS(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15078	      return SCIP_OKAY;
15079	
15080	   case SCIP_VARSTATUS_LOOSE:
15081	   case SCIP_VARSTATUS_COLUMN:
15082	   {
15083	      SCIPhistoryIncVSIDS(var->history, dir, weight);
15084	      SCIPhistoryIncVSIDS(var->historycrun, dir, weight);
15085	
15086	      if( useValuehistory(var, value, set) )
15087	      {
15088	         SCIP_HISTORY* history;
15089	
15090	         SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15091	         assert(history != NULL);
15092	
15093	         SCIPhistoryIncVSIDS(history, dir, weight);
15094	         SCIPsetDebugMsg(set, "variable (<%s> %s %g) + <%g> = <%g>\n", SCIPvarGetName(var), dir == SCIP_BRANCHDIR_UPWARDS ? ">=" : "<=",
15095	            value, weight, SCIPhistoryGetVSIDS(history, dir));
15096	      }
15097	
15098	      return SCIP_OKAY;
15099	   }
15100	   case SCIP_VARSTATUS_FIXED:
15101	      SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
15102	      return SCIP_INVALIDDATA;
15103	
15104	   case SCIP_VARSTATUS_AGGREGATED:
15105	      value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15106	
15107	      if( var->data.aggregate.scalar > 0.0 )
15108	      {
15109	         SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15110	      }
15111	      else
15112	      {
15113	         assert(var->data.aggregate.scalar < 0.0);
15114	         SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15115	      }
15116	      return SCIP_OKAY;
15117	
15118	   case SCIP_VARSTATUS_MULTAGGR:
15119	      SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
15120	      return SCIP_INVALIDDATA;
15121	
15122	   case SCIP_VARSTATUS_NEGATED:
15123	      value = 1.0 - value;
15124	
15125	      SCIP_CALL( SCIPvarIncVSIDS(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15126	      return SCIP_OKAY;
15127	
15128	   default:
15129	      SCIPerrorMessage("unknown variable status\n");
15130	      return SCIP_INVALIDDATA;
15131	   }
15132	}
15133	
15134	/** scales the VSIDS of the variable by the given scalar */
15135	SCIP_RETCODE SCIPvarScaleVSIDS(
15136	   SCIP_VAR*             var,                /**< problem variable */
15137	   SCIP_Real             scalar              /**< scalar to multiply the VSIDSs with */
15138	   )
15139	{
15140	   assert(var != NULL);
15141	
15142	   switch( SCIPvarGetStatus(var) )
15143	   {
15144	   case SCIP_VARSTATUS_ORIGINAL:
15145	      if( var->data.original.transvar == NULL )
15146	      {
15147	         SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
15148	         return SCIP_INVALIDDATA;
15149	      }
15150	      SCIP_CALL( SCIPvarScaleVSIDS(var->data.original.transvar, scalar) );
15151	      return SCIP_OKAY;
15152	
15153	   case SCIP_VARSTATUS_LOOSE:
15154	   case SCIP_VARSTATUS_COLUMN:
15155	   {
15156	      SCIPhistoryScaleVSIDS(var->history, scalar);
15157	      SCIPhistoryScaleVSIDS(var->historycrun, scalar);
15158	      SCIPvaluehistoryScaleVSIDS(var->valuehistory, scalar);
15159	
15160	      return SCIP_OKAY;
15161	   }
15162	   case SCIP_VARSTATUS_FIXED:
15163	      SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
15164	      return SCIP_INVALIDDATA;
15165	
15166	   case SCIP_VARSTATUS_AGGREGATED:
15167	      SCIP_CALL( SCIPvarScaleVSIDS(var->data.aggregate.var, scalar) );
15168	      return SCIP_OKAY;
15169	
15170	   case SCIP_VARSTATUS_MULTAGGR:
15171	      SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
15172	      return SCIP_INVALIDDATA;
15173	
15174	   case SCIP_VARSTATUS_NEGATED:
15175	      SCIP_CALL( SCIPvarScaleVSIDS(var->negatedvar, scalar) );
15176	      return SCIP_OKAY;
15177	
15178	   default:
15179	      SCIPerrorMessage("unknown variable status\n");
15180	      return SCIP_INVALIDDATA;
15181	   }
15182	}
15183	
15184	/** increases the number of active conflicts by one and the overall length of the variable by the given length */
15185	SCIP_RETCODE SCIPvarIncNActiveConflicts(
15186	   SCIP_VAR*             var,                /**< problem variable */
15187	   BMS_BLKMEM*           blkmem,             /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15188	   SCIP_SET*             set,                /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15189	   SCIP_STAT*            stat,               /**< problem statistics */
15190	   SCIP_BRANCHDIR        dir,                /**< branching direction */
15191	   SCIP_Real             value,              /**< domain value, or SCIP_UNKNOWN */
15192	   SCIP_Real             length              /**< length of the conflict */
15193	   )
15194	{
15195	   assert(var != NULL);
15196	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15197	
15198	   /* check if history statistics should be collected for a variable */
15199	   if( !stat->collectvarhistory )
15200	      return SCIP_OKAY;
15201	
15202	   switch( SCIPvarGetStatus(var) )
15203	   {
15204	   case SCIP_VARSTATUS_ORIGINAL:
15205	      if( var->data.original.transvar == NULL )
15206	      {
15207	         SCIPerrorMessage("cannot update conflict score of original untransformed variable\n");
15208	         return SCIP_INVALIDDATA;
15209	      }
15210	      SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.original.transvar, blkmem, set, stat, dir, value, length) );
15211	      return SCIP_OKAY;
15212	
15213	   case SCIP_VARSTATUS_LOOSE:
15214	   case SCIP_VARSTATUS_COLUMN:
15215	   {
15216	      SCIPhistoryIncNActiveConflicts(var->history, dir, length);
15217	      SCIPhistoryIncNActiveConflicts(var->historycrun, dir, length);
15218	
15219	      if( useValuehistory(var, value, set) )
15220	      {
15221	         SCIP_HISTORY* history;
15222	
15223	         SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15224	         assert(history != NULL);
15225	
15226	         SCIPhistoryIncNActiveConflicts(history, dir, length);
15227	      }
15228	
15229	      return SCIP_OKAY;
15230	   }
15231	   case SCIP_VARSTATUS_FIXED:
15232	      SCIPerrorMessage("cannot update conflict score of a fixed variable\n");
15233	      return SCIP_INVALIDDATA;
15234	
15235	   case SCIP_VARSTATUS_AGGREGATED:
15236	      value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15237	
15238	      if( var->data.aggregate.scalar > 0.0 )
15239	      {
15240	         SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, dir, value, length) );
15241	      }
15242	      else
15243	      {
15244	         assert(var->data.aggregate.scalar < 0.0);
15245	         SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
15246	      }
15247	      return SCIP_OKAY;
15248	
15249	   case SCIP_VARSTATUS_MULTAGGR:
15250	      SCIPerrorMessage("cannot update conflict score of a multi-aggregated variable\n");
15251	      return SCIP_INVALIDDATA;
15252	
15253	   case SCIP_VARSTATUS_NEGATED:
15254	      value = 1.0 - value;
15255	
15256	      SCIP_CALL( SCIPvarIncNActiveConflicts(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
15257	      return SCIP_OKAY;
15258	
15259	   default:
15260	      SCIPerrorMessage("unknown variable status\n");
15261	      return SCIP_INVALIDDATA;
15262	   }
15263	}
15264	
15265	/** gets the number of active conflicts containing this variable in given direction */
15266	SCIP_Longint SCIPvarGetNActiveConflicts(
15267	   SCIP_VAR*             var,                /**< problem variable */
15268	   SCIP_STAT*            stat,               /**< problem statistics */
15269	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
15270	   )
15271	{
15272	   assert(var != NULL);
15273	   assert(stat != NULL);
15274	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15275	
15276	   switch( SCIPvarGetStatus(var) )
15277	   {
15278	   case SCIP_VARSTATUS_ORIGINAL:
15279	      if( var->data.original.transvar == NULL )
15280	         return 0;
15281	      else
15282	         return SCIPvarGetNActiveConflicts(var->data.original.transvar, stat, dir);
15283	
15284	   case SCIP_VARSTATUS_LOOSE:
15285	   case SCIP_VARSTATUS_COLUMN:
15286	      return SCIPhistoryGetNActiveConflicts(var->history, dir);
15287	
15288	   case SCIP_VARSTATUS_FIXED:
15289	      return 0;
15290	
15291	   case SCIP_VARSTATUS_AGGREGATED:
15292	      if( var->data.aggregate.scalar > 0.0 )
15293	         return SCIPvarGetNActiveConflicts(var->data.aggregate.var, stat, dir);
15294	      else
15295	         return SCIPvarGetNActiveConflicts(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15296	
15297	   case SCIP_VARSTATUS_MULTAGGR:
15298	      return 0;
15299	
15300	   case SCIP_VARSTATUS_NEGATED:
15301	      return SCIPvarGetNActiveConflicts(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15302	
15303	   default:
15304	      SCIPerrorMessage("unknown variable status\n");
15305	      SCIPABORT();
15306	      return 0; /*lint !e527*/
15307	   }
15308	}
15309	
15310	/** gets the number of active conflicts containing this variable in given direction
15311	 *  in the current run
15312	 */
15313	SCIP_Longint SCIPvarGetNActiveConflictsCurrentRun(
15314	   SCIP_VAR*             var,                /**< problem variable */
15315	   SCIP_STAT*            stat,               /**< problem statistics */
15316	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
15317	   )
15318	{
15319	   assert(var != NULL);
15320	   assert(stat != NULL);
15321	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15322	
15323	   switch( SCIPvarGetStatus(var) )
15324	   {
15325	   case SCIP_VARSTATUS_ORIGINAL:
15326	      if( var->data.original.transvar == NULL )
15327	         return 0;
15328	      else
15329	         return SCIPvarGetNActiveConflictsCurrentRun(var->data.original.transvar, stat, dir);
15330	
15331	   case SCIP_VARSTATUS_LOOSE:
15332	   case SCIP_VARSTATUS_COLUMN:
15333	      return SCIPhistoryGetNActiveConflicts(var->historycrun, dir);
15334	
15335	   case SCIP_VARSTATUS_FIXED:
15336	      return 0;
15337	
15338	   case SCIP_VARSTATUS_AGGREGATED:
15339	      if( var->data.aggregate.scalar > 0.0 )
15340	         return SCIPvarGetNActiveConflictsCurrentRun(var->data.aggregate.var, stat, dir);
15341	      else
15342	         return SCIPvarGetNActiveConflictsCurrentRun(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15343	
15344	   case SCIP_VARSTATUS_MULTAGGR:
15345	      return 0;
15346	
15347	   case SCIP_VARSTATUS_NEGATED:
15348	      return SCIPvarGetNActiveConflictsCurrentRun(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15349	
15350	   default:
15351	      SCIPerrorMessage("unknown variable status\n");
15352	      SCIPABORT();
15353	      return 0; /*lint !e527*/
15354	   }
15355	}
15356	
15357	/** gets the average conflict length in given direction due to branching on the variable */
15358	SCIP_Real SCIPvarGetAvgConflictlength(
15359	   SCIP_VAR*             var,                /**< problem variable */
15360	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
15361	   )
15362	{
15363	   assert(var != NULL);
15364	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15365	
15366	   switch( SCIPvarGetStatus(var) )
15367	   {
15368	   case SCIP_VARSTATUS_ORIGINAL:
15369	      if( var->data.original.transvar == NULL )
15370	         return 0.0;
15371	      else
15372	         return SCIPvarGetAvgConflictlength(var->data.original.transvar, dir);
15373	
15374	   case SCIP_VARSTATUS_LOOSE:
15375	   case SCIP_VARSTATUS_COLUMN:
15376	         return SCIPhistoryGetAvgConflictlength(var->history, dir);
15377	   case SCIP_VARSTATUS_FIXED:
15378	      return 0.0;
15379	
15380	   case SCIP_VARSTATUS_AGGREGATED:
15381	      if( var->data.aggregate.scalar > 0.0 )
15382	         return SCIPvarGetAvgConflictlength(var->data.aggregate.var, dir);
15383	      else
15384	         return SCIPvarGetAvgConflictlength(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
15385	
15386	   case SCIP_VARSTATUS_MULTAGGR:
15387	      return 0.0;
15388	
15389	   case SCIP_VARSTATUS_NEGATED:
15390	      return SCIPvarGetAvgConflictlength(var->negatedvar, SCIPbranchdirOpposite(dir));
15391	
15392	   default:
15393	      SCIPerrorMessage("unknown variable status\n");
15394	      SCIPABORT();
15395	      return 0.0; /*lint !e527*/
15396	   }
15397	}
15398	
15399	/**  gets the average conflict length in given direction due to branching on the variable
15400	 *   in the current run
15401	 */
15402	SCIP_Real SCIPvarGetAvgConflictlengthCurrentRun(
15403	   SCIP_VAR*             var,                /**< problem variable */
15404	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
15405	   )
15406	{
15407	   assert(var != NULL);
15408	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15409	
15410	   switch( SCIPvarGetStatus(var) )
15411	   {
15412	   case SCIP_VARSTATUS_ORIGINAL:
15413	      if( var->data.original.transvar == NULL )
15414	         return 0.0;
15415	      else
15416	         return SCIPvarGetAvgConflictlengthCurrentRun(var->data.original.transvar, dir);
15417	
15418	   case SCIP_VARSTATUS_LOOSE:
15419	   case SCIP_VARSTATUS_COLUMN:
15420	      return  SCIPhistoryGetAvgConflictlength(var->historycrun, dir);
15421	
15422	   case SCIP_VARSTATUS_FIXED:
15423	      return 0.0;
15424	
15425	   case SCIP_VARSTATUS_AGGREGATED:
15426	      if( var->data.aggregate.scalar > 0.0 )
15427	         return SCIPvarGetAvgConflictlengthCurrentRun(var->data.aggregate.var, dir);
15428	      else
15429	         return SCIPvarGetAvgConflictlengthCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
15430	
15431	   case SCIP_VARSTATUS_MULTAGGR:
15432	      return 0.0;
15433	
15434	   case SCIP_VARSTATUS_NEGATED:
15435	      return SCIPvarGetAvgConflictlengthCurrentRun(var->negatedvar, SCIPbranchdirOpposite(dir));
15436	
15437	   default:
15438	      SCIPerrorMessage("unknown variable status\n");
15439	      SCIPABORT();
15440	      return 0.0; /*lint !e527*/
15441	   }
15442	}
15443	
15444	/** increases the number of branchings counter of the variable */
15445	SCIP_RETCODE SCIPvarIncNBranchings(
15446	   SCIP_VAR*             var,                /**< problem variable */
15447	   BMS_BLKMEM*           blkmem,             /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15448	   SCIP_SET*             set,                /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15449	   SCIP_STAT*            stat,               /**< problem statistics */
15450	   SCIP_BRANCHDIR        dir,                /**< branching direction (downwards, or upwards) */
15451	   SCIP_Real             value,              /**< domain value, or SCIP_UNKNOWN */
15452	   int                   depth               /**< depth at which the bound change took place */
15453	   )
15454	{
15455	   assert(var != NULL);
15456	   assert(stat != NULL);
15457	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15458	
15459	   /* check if history statistics should be collected for a variable */
15460	   if( !stat->collectvarhistory )
15461	      return SCIP_OKAY;
15462	
15463	   switch( SCIPvarGetStatus(var) )
15464	   {
15465	   case SCIP_VARSTATUS_ORIGINAL:
15466	      if( var->data.original.transvar == NULL )
15467	      {
15468	         SCIPerrorMessage("cannot update branching counter of original untransformed variable\n");
15469	         return SCIP_INVALIDDATA;
15470	      }
15471	      SCIP_CALL( SCIPvarIncNBranchings(var->data.original.transvar, blkmem, set, stat, dir, value, depth) );
15472	      return SCIP_OKAY;
15473	
15474	   case SCIP_VARSTATUS_LOOSE:
15475	   case SCIP_VARSTATUS_COLUMN:
15476	   {
15477	      SCIPhistoryIncNBranchings(var->history, dir, depth);
15478	      SCIPhistoryIncNBranchings(var->historycrun, dir, depth);
15479	      SCIPhistoryIncNBranchings(stat->glbhistory, dir, depth);
15480	      SCIPhistoryIncNBranchings(stat->glbhistorycrun, dir, depth);
15481	
15482	      if( useValuehistory(var, value, set) )
15483	      {
15484	         SCIP_HISTORY* history;
15485	
15486	         SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15487	         assert(history != NULL);
15488	
15489	         SCIPhistoryIncNBranchings(history, dir, depth);
15490	      }
15491	
15492	      return SCIP_OKAY;
15493	   }
15494	   case SCIP_VARSTATUS_FIXED:
15495	      SCIPerrorMessage("cannot update branching counter of a fixed variable\n");
15496	      return SCIP_INVALIDDATA;
15497	
15498	   case SCIP_VARSTATUS_AGGREGATED:
15499	      value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15500	
15501	      if( var->data.aggregate.scalar > 0.0 )
15502	      {
15503	         SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, dir, value, depth) );
15504	      }
15505	      else
15506	      {
15507	         assert(var->data.aggregate.scalar < 0.0);
15508	         SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
15509	      }
15510	      return SCIP_OKAY;
15511	
15512	   case SCIP_VARSTATUS_MULTAGGR:
15513	      SCIPerrorMessage("cannot update branching counter of a multi-aggregated variable\n");
15514	      return SCIP_INVALIDDATA;
15515	
15516	   case SCIP_VARSTATUS_NEGATED:
15517	      value = 1.0 - value;
15518	
15519	      SCIP_CALL( SCIPvarIncNBranchings(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
15520	      return SCIP_OKAY;
15521	
15522	   default:
15523	      SCIPerrorMessage("unknown variable status\n");
15524	      return SCIP_INVALIDDATA;
15525	   }
15526	}
15527	
15528	/** increases the inference sum of the variable by the given weight */
15529	SCIP_RETCODE SCIPvarIncInferenceSum(
15530	   SCIP_VAR*             var,                /**< problem variable */
15531	   BMS_BLKMEM*           blkmem,             /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15532	   SCIP_SET*             set,                /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15533	   SCIP_STAT*            stat,               /**< problem statistics */
15534	   SCIP_BRANCHDIR        dir,                /**< branching direction (downwards, or upwards) */
15535	   SCIP_Real             value,              /**< domain value, or SCIP_UNKNOWN */
15536	   SCIP_Real             weight              /**< weight of this update in inference score */
15537	   )
15538	{
15539	   assert(var != NULL);
15540	   assert(stat != NULL);
15541	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15542	
15543	   /* check if history statistics should be collected for a variable */
15544	   if( !stat->collectvarhistory )
15545	      return SCIP_OKAY;
15546	
15547	   switch( SCIPvarGetStatus(var) )
15548	   {
15549	   case SCIP_VARSTATUS_ORIGINAL:
15550	      if( var->data.original.transvar == NULL )
15551	      {
15552	         SCIPerrorMessage("cannot update inference counter of original untransformed variable\n");
15553	         return SCIP_INVALIDDATA;
15554	      }
15555	      SCIP_CALL( SCIPvarIncInferenceSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15556	      return SCIP_OKAY;
15557	
15558	   case SCIP_VARSTATUS_LOOSE:
15559	   case SCIP_VARSTATUS_COLUMN:
15560	   {
15561	      SCIPhistoryIncInferenceSum(var->history, dir, weight);
15562	      SCIPhistoryIncInferenceSum(var->historycrun, dir, weight);
15563	      SCIPhistoryIncInferenceSum(stat->glbhistory, dir, weight);
15564	      SCIPhistoryIncInferenceSum(stat->glbhistorycrun, dir, weight);
15565	
15566	      if( useValuehistory(var, value, set) )
15567	      {
15568	         SCIP_HISTORY* history;
15569	
15570	         SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15571	         assert(history != NULL);
15572	
15573	         SCIPhistoryIncInferenceSum(history, dir, weight);
15574	      }
15575	
15576	      return SCIP_OKAY;
15577	   }
15578	   case SCIP_VARSTATUS_FIXED:
15579	      SCIPerrorMessage("cannot update inference counter of a fixed variable\n");
15580	      return SCIP_INVALIDDATA;
15581	
15582	   case SCIP_VARSTATUS_AGGREGATED:
15583	      value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15584	
15585	      if( var->data.aggregate.scalar > 0.0 )
15586	      {
15587	         SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15588	      }
15589	      else
15590	      {
15591	         assert(var->data.aggregate.scalar < 0.0);
15592	         SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15593	      }
15594	      return SCIP_OKAY;
15595	
15596	   case SCIP_VARSTATUS_MULTAGGR:
15597	      SCIPerrorMessage("cannot update inference counter of a multi-aggregated variable\n");
15598	      return SCIP_INVALIDDATA;
15599	
15600	   case SCIP_VARSTATUS_NEGATED:
15601	      value = 1.0 - value;
15602	
15603	      SCIP_CALL( SCIPvarIncInferenceSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15604	      return SCIP_OKAY;
15605	
15606	   default:
15607	      SCIPerrorMessage("unknown variable status\n");
15608	      return SCIP_INVALIDDATA;
15609	   }
15610	}
15611	
15612	/** increases the cutoff sum of the variable by the given weight */
15613	SCIP_RETCODE SCIPvarIncCutoffSum(
15614	   SCIP_VAR*             var,                /**< problem variable */
15615	   BMS_BLKMEM*           blkmem,             /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15616	   SCIP_SET*             set,                /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15617	   SCIP_STAT*            stat,               /**< problem statistics */
15618	   SCIP_BRANCHDIR        dir,                /**< branching direction (downwards, or upwards) */
15619	   SCIP_Real             value,              /**< domain value, or SCIP_UNKNOWN */
15620	   SCIP_Real             weight              /**< weight of this update in cutoff score */
15621	   )
15622	{
15623	   assert(var != NULL);
15624	   assert(stat != NULL);
15625	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15626	
15627	   /* check if history statistics should be collected for a variable */
15628	   if( !stat->collectvarhistory )
15629	      return SCIP_OKAY;
15630	
15631	   switch( SCIPvarGetStatus(var) )
15632	   {
15633	   case SCIP_VARSTATUS_ORIGINAL:
15634	      if( var->data.original.transvar == NULL )
15635	      {
15636	         SCIPerrorMessage("cannot update cutoff sum of original untransformed variable\n");
15637	         return SCIP_INVALIDDATA;
15638	      }
15639	      SCIP_CALL( SCIPvarIncCutoffSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15640	      return SCIP_OKAY;
15641	
15642	   case SCIP_VARSTATUS_LOOSE:
15643	   case SCIP_VARSTATUS_COLUMN:
15644	   {
15645	      SCIPhistoryIncCutoffSum(var->history, dir, weight);
15646	      SCIPhistoryIncCutoffSum(var->historycrun, dir, weight);
15647	      SCIPhistoryIncCutoffSum(stat->glbhistory, dir, weight);
15648	      SCIPhistoryIncCutoffSum(stat->glbhistorycrun, dir, weight);
15649	
15650	      if( useValuehistory(var, value, set) )
15651	      {
15652	         SCIP_HISTORY* history;
15653	
15654	         SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15655	         assert(history != NULL);
15656	
15657	         SCIPhistoryIncCutoffSum(history, dir, weight);
15658	      }
15659	
15660	      return SCIP_OKAY;
15661	   }
15662	   case SCIP_VARSTATUS_FIXED:
15663	      SCIPerrorMessage("cannot update cutoff sum of a fixed variable\n");
15664	      return SCIP_INVALIDDATA;
15665	
15666	   case SCIP_VARSTATUS_AGGREGATED:
15667	      value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15668	
15669	      if( var->data.aggregate.scalar > 0.0 )
15670	      {
15671	         SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15672	      }
15673	      else
15674	      {
15675	         assert(var->data.aggregate.scalar < 0.0);
15676	         SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15677	      }
15678	      return SCIP_OKAY;
15679	
15680	   case SCIP_VARSTATUS_MULTAGGR:
15681	      SCIPerrorMessage("cannot update cutoff sum of a multi-aggregated variable\n");
15682	      return SCIP_INVALIDDATA;
15683	
15684	   case SCIP_VARSTATUS_NEGATED:
15685	      value = 1.0 - value;
15686	
15687	      SCIP_CALL( SCIPvarIncCutoffSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15688	      return SCIP_OKAY;
15689	
15690	   default:
15691	      SCIPerrorMessage("unknown variable status\n");
15692	      return SCIP_INVALIDDATA;
15693	   }
15694	}
15695	
15696	/** returns the number of times, a bound of the variable was changed in given direction due to branching */
15697	SCIP_Longint SCIPvarGetNBranchings(
15698	   SCIP_VAR*             var,                /**< problem variable */
15699	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
15700	   )
15701	{
15702	   assert(var != NULL);
15703	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15704	
15705	   switch( SCIPvarGetStatus(var) )
15706	   {
15707	   case SCIP_VARSTATUS_ORIGINAL:
15708	      if( var->data.original.transvar == NULL )
15709	         return 0;
15710	      else
15711	         return SCIPvarGetNBranchings(var->data.original.transvar, dir);
15712	
15713	   case SCIP_VARSTATUS_LOOSE:
15714	   case SCIP_VARSTATUS_COLUMN:
15715	      return SCIPhistoryGetNBranchings(var->history, dir);
15716	
15717	   case SCIP_VARSTATUS_FIXED:
15718	      return 0;
15719	
15720	   case SCIP_VARSTATUS_AGGREGATED:
15721	      if( var->data.aggregate.scalar > 0.0 )
15722	         return SCIPvarGetNBranchings(var->data.aggregate.var, dir);
15723	      else
15724	         return SCIPvarGetNBranchings(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
15725	
15726	   case SCIP_VARSTATUS_MULTAGGR:
15727	      return 0;
15728	
15729	   case SCIP_VARSTATUS_NEGATED:
15730	      return SCIPvarGetNBranchings(var->negatedvar, SCIPbranchdirOpposite(dir));
15731	
15732	   default:
15733	      SCIPerrorMessage("unknown variable status\n");
15734	      SCIPABORT();
15735	      return 0; /*lint !e527*/
15736	   }
15737	}
15738	
15739	/** returns the number of times, a bound of the variable was changed in given direction due to branching 
15740	 *  in the current run
15741	 */
15742	SCIP_Longint SCIPvarGetNBranchingsCurrentRun(
15743	   SCIP_VAR*             var,                /**< problem variable */
15744	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
15745	   )
15746	{
15747	   assert(var != NULL);
15748	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15749	
15750	   switch( SCIPvarGetStatus(var) )
15751	   {
15752	   case SCIP_VARSTATUS_ORIGINAL:
15753	      if( var->data.original.transvar == NULL )
15754	         return 0;
15755	      else
15756	         return SCIPvarGetNBranchingsCurrentRun(var->data.original.transvar, dir);
15757	
15758	   case SCIP_VARSTATUS_LOOSE:
15759	   case SCIP_VARSTATUS_COLUMN:
15760	      return SCIPhistoryGetNBranchings(var->historycrun, dir);
15761	
15762	   case SCIP_VARSTATUS_FIXED:
15763	      return 0;
15764	
15765	   case SCIP_VARSTATUS_AGGREGATED:
15766	      if( var->data.aggregate.scalar > 0.0 )
15767	         return SCIPvarGetNBranchingsCurrentRun(var->data.aggregate.var, dir);
15768	      else
15769	         return SCIPvarGetNBranchingsCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
15770	
15771	   case SCIP_VARSTATUS_MULTAGGR:
15772	      return 0;
15773	
15774	   case SCIP_VARSTATUS_NEGATED:
15775	      return SCIPvarGetNBranchingsCurrentRun(var->negatedvar, SCIPbranchdirOpposite(dir));
15776	
15777	   default:
15778	      SCIPerrorMessage("unknown variable status\n");
15779	      SCIPABORT();
15780	      return 0; /*lint !e527*/
15781	   }
15782	}
15783	
15784	/** returns the average depth of bound changes in given direction due to branching on the variable */
15785	SCIP_Real SCIPvarGetAvgBranchdepth(
15786	   SCIP_VAR*             var,                /**< problem variable */
15787	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
15788	   )
15789	{
15790	   assert(var != NULL);
15791	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15792	
15793	   switch( SCIPvarGetStatus(var) )
15794	   {
15795	   case SCIP_VARSTATUS_ORIGINAL:
15796	      if( var->data.original.transvar == NULL )
15797	         return 0.0;
15798	      else
15799	         return SCIPvarGetAvgBranchdepth(var->data.original.transvar, dir);
15800	
15801	   case SCIP_VARSTATUS_LOOSE:
15802	   case SCIP_VARSTATUS_COLUMN:
15803	      return  SCIPhistoryGetAvgBranchdepth(var->history, dir);
15804	
15805	   case SCIP_VARSTATUS_FIXED:
15806	      return 0.0;
15807	
15808	   case SCIP_VARSTATUS_AGGREGATED:
15809	      if( var->data.aggregate.scalar > 0.0 )
15810	         return SCIPvarGetAvgBranchdepth(var->data.aggregate.var, dir);
15811	      else
15812	         return SCIPvarGetAvgBranchdepth(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
15813	
15814	   case SCIP_VARSTATUS_MULTAGGR:
15815	      return 0.0;
15816	
15817	   case SCIP_VARSTATUS_NEGATED:
15818	      return SCIPvarGetAvgBranchdepth(var->negatedvar, SCIPbranchdirOpposite(dir));
15819	
15820	   default:
15821	      SCIPerrorMessage("unknown variable status\n");
15822	      SCIPABORT();
15823	      return 0.0; /*lint !e527*/
15824	   }
15825	}
15826	
15827	/** returns the average depth of bound changes in given direction due to branching on the variable
15828	 *  in the current run
15829	 */
15830	SCIP_Real SCIPvarGetAvgBranchdepthCurrentRun(
15831	   SCIP_VAR*             var,                /**< problem variable */
15832	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
15833	   )
15834	{
15835	   assert(var != NULL);
15836	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15837	
15838	   switch( SCIPvarGetStatus(var) )
15839	   {
15840	   case SCIP_VARSTATUS_ORIGINAL:
15841	      if( var->data.original.transvar == NULL )
15842	         return 0.0;
15843	      else
15844	         return SCIPvarGetAvgBranchdepthCurrentRun(var->data.original.transvar, dir);
15845	
15846	   case SCIP_VARSTATUS_LOOSE:
15847	   case SCIP_VARSTATUS_COLUMN:
15848	      return  SCIPhistoryGetAvgBranchdepth(var->historycrun, dir);
15849	
15850	   case SCIP_VARSTATUS_FIXED:
15851	      return 0.0;
15852	
15853	   case SCIP_VARSTATUS_AGGREGATED:
15854	      if( var->data.aggregate.scalar > 0.0 )
15855	         return SCIPvarGetAvgBranchdepthCurrentRun(var->data.aggregate.var, dir);
15856	      else
15857	         return SCIPvarGetAvgBranchdepthCurrentRun(var->data.aggregate.var,
15858	            dir == SCIP_BRANCHDIR_DOWNWARDS ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
15859	
15860	   case SCIP_VARSTATUS_MULTAGGR:
15861	      return 0.0;
15862	
15863	   case SCIP_VARSTATUS_NEGATED:
15864	      return SCIPvarGetAvgBranchdepthCurrentRun(var->negatedvar,
15865	         dir == SCIP_BRANCHDIR_DOWNWARDS ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
15866	
15867	   default:
15868	      SCIPerrorMessage("unknown variable status\n");
15869	      SCIPABORT();
15870	      return 0.0; /*lint !e527*/
15871	   }
15872	}
15873	
15874	/** returns the variable's VSIDS score */
15875	SCIP_Real SCIPvarGetVSIDS_rec(
15876	   SCIP_VAR*             var,                /**< problem variable */
15877	   SCIP_STAT*            stat,               /**< problem statistics */
15878	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
15879	   )
15880	{
15881	   assert(var != NULL);
15882	   assert(stat != NULL);
15883	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15884	
15885	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN )
15886	      return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15887	
15888	   switch( SCIPvarGetStatus(var) )
15889	   {
15890	   case SCIP_VARSTATUS_ORIGINAL:
15891	      if( var->data.original.transvar == NULL )
15892	         return 0.0;
15893	      else
15894	         return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15895	
15896	   case SCIP_VARSTATUS_LOOSE:
15897	   case SCIP_VARSTATUS_COLUMN:
15898	      assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE); /* column case already handled in if condition above */
15899	      return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
15900	
15901	   case SCIP_VARSTATUS_FIXED:
15902	      return 0.0;
15903	
15904	   case SCIP_VARSTATUS_AGGREGATED:
15905	      if( var->data.aggregate.scalar > 0.0 )
15906	         return SCIPvarGetVSIDS(var->data.aggregate.var, stat, dir);
15907	      else
15908	         /* coverity[overrun-local] */
15909	         return SCIPvarGetVSIDS(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15910	
15911	   case SCIP_VARSTATUS_MULTAGGR:
15912	      return 0.0;
15913	
15914	   case SCIP_VARSTATUS_NEGATED:
15915	      /* coverity[overrun-local] */
15916	      return SCIPvarGetVSIDS(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15917	
15918	   default:
15919	      SCIPerrorMessage("unknown variable status\n");
15920	      SCIPABORT();
15921	      return 0.0; /*lint !e527*/
15922	   }
15923	}
15924	
15925	/** returns the variable's VSIDS score only using conflicts of the current run */
15926	SCIP_Real SCIPvarGetVSIDSCurrentRun(
15927	   SCIP_VAR*             var,                /**< problem variable */
15928	   SCIP_STAT*            stat,               /**< problem statistics */
15929	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
15930	   )
15931	{
15932	   assert(var != NULL);
15933	   assert(stat != NULL);
15934	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15935	
15936	   if( dir != SCIP_BRANCHDIR_DOWNWARDS && dir != SCIP_BRANCHDIR_UPWARDS )
15937	   {
15938	      SCIPerrorMessage("invalid branching direction %d when asking for VSIDS value\n", dir);
15939	      return SCIP_INVALID;
15940	   }
15941	
15942	   switch( SCIPvarGetStatus(var) )
15943	   {
15944	   case SCIP_VARSTATUS_ORIGINAL:
15945	      if( var->data.original.transvar == NULL )
15946	         return 0.0;
15947	      else
15948	         return SCIPvarGetVSIDSCurrentRun(var->data.original.transvar, stat, dir);
15949	
15950	   case SCIP_VARSTATUS_LOOSE:
15951	   case SCIP_VARSTATUS_COLUMN:
15952	      return SCIPhistoryGetVSIDS(var->historycrun, dir)/stat->vsidsweight;
15953	
15954	   case SCIP_VARSTATUS_FIXED:
15955	      return 0.0;
15956	
15957	   case SCIP_VARSTATUS_AGGREGATED:
15958	      if( var->data.aggregate.scalar > 0.0 )
15959	         return SCIPvarGetVSIDSCurrentRun(var->data.aggregate.var, stat, dir);
15960	      else
15961	         return SCIPvarGetVSIDSCurrentRun(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15962	
15963	   case SCIP_VARSTATUS_MULTAGGR:
15964	      return 0.0;
15965	
15966	   case SCIP_VARSTATUS_NEGATED:
15967	      return SCIPvarGetVSIDSCurrentRun(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15968	
15969	   default:
15970	      SCIPerrorMessage("unknown variable status\n");
15971	      SCIPABORT();
15972	      return 0.0; /*lint !e527*/
15973	   }
15974	}
15975	
15976	/** returns the number of inferences branching on this variable in given direction triggered */
15977	SCIP_Real SCIPvarGetInferenceSum(
15978	   SCIP_VAR*             var,                /**< problem variable */
15979	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
15980	   )
15981	{
15982	   assert(var != NULL);
15983	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15984	
15985	   switch( SCIPvarGetStatus(var) )
15986	   {
15987	   case SCIP_VARSTATUS_ORIGINAL:
15988	      if( var->data.original.transvar == NULL )
15989	         return 0.0;
15990	      else
15991	         return SCIPvarGetInferenceSum(var->data.original.transvar, dir);
15992	
15993	   case SCIP_VARSTATUS_LOOSE:
15994	   case SCIP_VARSTATUS_COLUMN:
15995	      return SCIPhistoryGetInferenceSum(var->history, dir);
15996	
15997	   case SCIP_VARSTATUS_FIXED:
15998	      return 0.0;
15999	
16000	   case SCIP_VARSTATUS_AGGREGATED:
16001	      if( var->data.aggregate.scalar > 0.0 )
16002	         return SCIPvarGetInferenceSum(var->data.aggregate.var, dir);
16003	      else
16004	         return SCIPvarGetInferenceSum(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
16005	
16006	   case SCIP_VARSTATUS_MULTAGGR:
16007	      return 0.0;
16008	
16009	   case SCIP_VARSTATUS_NEGATED:
16010	      return SCIPvarGetInferenceSum(var->negatedvar, SCIPbranchdirOpposite(dir));
16011	
16012	   default:
16013	      SCIPerrorMessage("unknown variable status\n");
16014	      SCIPABORT();
16015	      return 0.0; /*lint !e527*/
16016	   }
16017	}
16018	
16019	/** returns the number of inferences branching on this variable in given direction triggered
16020	 *  in the current run
16021	 */
16022	SCIP_Real SCIPvarGetInferenceSumCurrentRun(
16023	   SCIP_VAR*             var,                /**< problem variable */
16024	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
16025	   )
16026	{
16027	   assert(var != NULL);
16028	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16029	
16030	   switch( SCIPvarGetStatus(var) )
16031	   {
16032	   case SCIP_VARSTATUS_ORIGINAL:
16033	      if( var->data.original.transvar == NULL )
16034	         return 0.0;
16035	      else
16036	         return SCIPvarGetInferenceSumCurrentRun(var->data.original.transvar, dir);
16037	
16038	   case SCIP_VARSTATUS_LOOSE:
16039	   case SCIP_VARSTATUS_COLUMN:
16040	      return SCIPhistoryGetInferenceSum(var->historycrun, dir);
16041	
16042	   case SCIP_VARSTATUS_FIXED:
16043	      return 0.0;
16044	
16045	   case SCIP_VARSTATUS_AGGREGATED:
16046	      if( var->data.aggregate.scalar > 0.0 )
16047	         return SCIPvarGetInferenceSumCurrentRun(var->data.aggregate.var, dir);
16048	      else
16049	         return SCIPvarGetInferenceSumCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
16050	
16051	   case SCIP_VARSTATUS_MULTAGGR:
16052	      return 0.0;
16053	
16054	   case SCIP_VARSTATUS_NEGATED:
16055	      return SCIPvarGetInferenceSumCurrentRun(var->negatedvar, SCIPbranchdirOpposite(dir));
16056	
16057	   default:
16058	      SCIPerrorMessage("unknown variable status\n");
16059	      SCIPABORT();
16060	      return 0.0; /*lint !e527*/
16061	   }
16062	}
16063	
16064	/** returns the average number of inferences found after branching on the variable in given direction */
16065	SCIP_Real SCIPvarGetAvgInferences(
16066	   SCIP_VAR*             var,                /**< problem variable */
16067	   SCIP_STAT*            stat,               /**< problem statistics */
16068	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
16069	   )
16070	{
16071	   assert(var != NULL);
16072	   assert(stat != NULL);
16073	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16074	
16075	   switch( SCIPvarGetStatus(var) )
16076	   {
16077	   case SCIP_VARSTATUS_ORIGINAL:
16078	      if( var->data.original.transvar == NULL )
16079	         return SCIPhistoryGetAvgInferences(stat->glbhistory, dir);
16080	      else
16081	         return SCIPvarGetAvgInferences(var->data.original.transvar, stat, dir);
16082	
16083	   case SCIP_VARSTATUS_LOOSE:
16084	   case SCIP_VARSTATUS_COLUMN:
16085	      if( SCIPhistoryGetNBranchings(var->history, dir) > 0 )
16086	         return SCIPhistoryGetAvgInferences(var->history, dir);
16087	      else
16088	      {
16089	         int nimpls;
16090	         int ncliques;
16091	
16092	         nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
16093	         ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
16094	         return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistory, dir);  /*lint !e790*/
16095	      }
16096	
16097	   case SCIP_VARSTATUS_FIXED:
16098	      return 0.0;
16099	
16100	   case SCIP_VARSTATUS_AGGREGATED:
16101	      if( var->data.aggregate.scalar > 0.0 )
16102	         return SCIPvarGetAvgInferences(var->data.aggregate.var, stat, dir);
16103	      else
16104	         return SCIPvarGetAvgInferences(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
16105	
16106	   case SCIP_VARSTATUS_MULTAGGR:
16107	      return 0.0;
16108	
16109	   case SCIP_VARSTATUS_NEGATED:
16110	      return SCIPvarGetAvgInferences(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
16111	
16112	   default:
16113	      SCIPerrorMessage("unknown variable status\n");
16114	      SCIPABORT();
16115	      return 0.0; /*lint !e527*/
16116	   }
16117	}
16118	
16119	/** returns the average number of inferences found after branching on the variable in given direction
16120	 *  in the current run
16121	 */
16122	SCIP_Real SCIPvarGetAvgInferencesCurrentRun(
16123	   SCIP_VAR*             var,                /**< problem variable */
16124	   SCIP_STAT*            stat,               /**< problem statistics */
16125	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
16126	   )
16127	{
16128	   assert(var != NULL);
16129	   assert(stat != NULL);
16130	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16131	
16132	   switch( SCIPvarGetStatus(var) )
16133	   {
16134	   case SCIP_VARSTATUS_ORIGINAL:
16135	      if( var->data.original.transvar == NULL )
16136	         return SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir);
16137	      else
16138	         return SCIPvarGetAvgInferencesCurrentRun(var->data.original.transvar, stat, dir);
16139	
16140	   case SCIP_VARSTATUS_LOOSE:
16141	   case SCIP_VARSTATUS_COLUMN:
16142	      if( SCIPhistoryGetNBranchings(var->historycrun, dir) > 0 )
16143	         return SCIPhistoryGetAvgInferences(var->historycrun, dir);
16144	      else
16145	      {
16146	         int nimpls;
16147	         int ncliques;
16148	
16149	         nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
16150	         ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
16151	         return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir);  /*lint !e790*/
16152	      }
16153	
16154	   case SCIP_VARSTATUS_FIXED:
16155	      return 0.0;
16156	
16157	   case SCIP_VARSTATUS_AGGREGATED:
16158	      if( var->data.aggregate.scalar > 0.0 )
16159	         return SCIPvarGetAvgInferencesCurrentRun(var->data.aggregate.var, stat, dir);
16160	      else
16161	         return SCIPvarGetAvgInferencesCurrentRun(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
16162	
16163	   case SCIP_VARSTATUS_MULTAGGR:
16164	      return 0.0;
16165	
16166	   case SCIP_VARSTATUS_NEGATED:
16167	      return SCIPvarGetAvgInferencesCurrentRun(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
16168	
16169	   default:
16170	      SCIPerrorMessage("unknown variable status\n");
16171	      SCIPABORT();
16172	      return 0.0; /*lint !e527*/
16173	   }
16174	}
16175	
16176	/** returns the number of cutoffs branching on this variable in given direction produced */
16177	SCIP_Real SCIPvarGetCutoffSum(
16178	   SCIP_VAR*             var,                /**< problem variable */
16179	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
16180	   )
16181	{
16182	   assert(var != NULL);
16183	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16184	
16185	   switch( SCIPvarGetStatus(var) )
16186	   {
16187	   case SCIP_VARSTATUS_ORIGINAL:
16188	      if( var->data.original.transvar == NULL )
16189	         return 0;
16190	      else
16191	         return SCIPvarGetCutoffSum(var->data.original.transvar, dir);
16192	
16193	   case SCIP_VARSTATUS_LOOSE:
16194	   case SCIP_VARSTATUS_COLUMN:
16195	      return SCIPhistoryGetCutoffSum(var->history, dir);
16196	
16197	   case SCIP_VARSTATUS_FIXED:
16198	      return 0;
16199	
16200	   case SCIP_VARSTATUS_AGGREGATED:
16201	      if( var->data.aggregate.scalar > 0.0 )
16202	         return SCIPvarGetCutoffSum(var->data.aggregate.var, dir);
16203	      else
16204	         return SCIPvarGetCutoffSum(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
16205	
16206	   case SCIP_VARSTATUS_MULTAGGR:
16207	      return 0;
16208	
16209	   case SCIP_VARSTATUS_NEGATED:
16210	      return SCIPvarGetCutoffSum(var->negatedvar, SCIPbranchdirOpposite(dir));
16211	
16212	   default:
16213	      SCIPerrorMessage("unknown variable status\n");
16214	      SCIPABORT();
16215	      return 0; /*lint !e527*/
16216	   }
16217	}
16218	
16219	/** returns the number of cutoffs branching on this variable in given direction produced in the current run */
16220	SCIP_Real SCIPvarGetCutoffSumCurrentRun(
16221	   SCIP_VAR*             var,                /**< problem variable */
16222	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
16223	   )
16224	{
16225	   assert(var != NULL);
16226	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16227	
16228	   switch( SCIPvarGetStatus(var) )
16229	   {
16230	   case SCIP_VARSTATUS_ORIGINAL:
16231	      if( var->data.original.transvar == NULL )
16232	         return 0;
16233	      else
16234	         return SCIPvarGetCutoffSumCurrentRun(var->data.original.transvar, dir);
16235	
16236	   case SCIP_VARSTATUS_LOOSE:
16237	   case SCIP_VARSTATUS_COLUMN:
16238	      return SCIPhistoryGetCutoffSum(var->historycrun, dir);
16239	
16240	   case SCIP_VARSTATUS_FIXED:
16241	      return 0;
16242	
16243	   case SCIP_VARSTATUS_AGGREGATED:
16244	      if( var->data.aggregate.scalar > 0.0 )
16245	         return SCIPvarGetCutoffSumCurrentRun(var->data.aggregate.var, dir);
16246	      else
16247	         return SCIPvarGetCutoffSumCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
16248	
16249	   case SCIP_VARSTATUS_MULTAGGR:
16250	      return 0;
16251	
16252	   case SCIP_VARSTATUS_NEGATED:
16253	      return SCIPvarGetCutoffSumCurrentRun(var->negatedvar, SCIPbranchdirOpposite(dir));
16254	
16255	   default:
16256	      SCIPerrorMessage("unknown variable status\n");
16257	      SCIPABORT();
16258	      return 0; /*lint !e527*/
16259	   }
16260	}
16261	
16262	/** returns the average number of cutoffs found after branching on the variable in given direction */
16263	SCIP_Real SCIPvarGetAvgCutoffs(
16264	   SCIP_VAR*             var,                /**< problem variable */
16265	   SCIP_STAT*            stat,               /**< problem statistics */
16266	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
16267	   )
16268	{
16269	   assert(var != NULL);
16270	   assert(stat != NULL);
16271	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16272	
16273	   switch( SCIPvarGetStatus(var) )
16274	   {
16275	   case SCIP_VARSTATUS_ORIGINAL:
16276	      if( var->data.original.transvar == NULL )
16277	         return SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
16278	      else
16279	         return SCIPvarGetAvgCutoffs(var->data.original.transvar, stat, dir);
16280	
16281	   case SCIP_VARSTATUS_LOOSE:
16282	   case SCIP_VARSTATUS_COLUMN:
16283	      return SCIPhistoryGetNBranchings(var->history, dir) > 0
16284	         ? SCIPhistoryGetAvgCutoffs(var->history, dir)
16285	         : SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
16286	
16287	   case SCIP_VARSTATUS_FIXED:
16288	      return 0.0;
16289	
16290	   case SCIP_VARSTATUS_AGGREGATED:
16291	      if( var->data.aggregate.scalar > 0.0 )
16292	         return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, dir);
16293	      else
16294	         return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
16295	
16296	   case SCIP_VARSTATUS_MULTAGGR:
16297	      return 0.0;
16298	
16299	   case SCIP_VARSTATUS_NEGATED:
16300	      return SCIPvarGetAvgCutoffs(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
16301	
16302	   default:
16303	      SCIPerrorMessage("unknown variable status\n");
16304	      SCIPABORT();
16305	      return 0.0; /*lint !e527*/
16306	   }
16307	}
16308	
16309	/** returns the average number of cutoffs found after branching on the variable in given direction in the current run */
16310	SCIP_Real SCIPvarGetAvgCutoffsCurrentRun(
16311	   SCIP_VAR*             var,                /**< problem variable */
16312	   SCIP_STAT*            stat,               /**< problem statistics */
16313	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
16314	   )
16315	{
16316	   assert(var != NULL);
16317	   assert(stat != NULL);
16318	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16319	
16320	   switch( SCIPvarGetStatus(var) )
16321	   {
16322	   case SCIP_VARSTATUS_ORIGINAL:
16323	      if( var->data.original.transvar == NULL )
16324	         return SCIPhistoryGetAvgCutoffs(stat->glbhistorycrun, dir);
16325	      else
16326	         return SCIPvarGetAvgCutoffsCurrentRun(var->data.original.transvar, stat, dir);
16327	
16328	   case SCIP_VARSTATUS_LOOSE:
16329	   case SCIP_VARSTATUS_COLUMN:
16330	      return SCIPhistoryGetNBranchings(var->historycrun, dir) > 0
16331	         ? SCIPhistoryGetAvgCutoffs(var->historycrun, dir)
16332	         : SCIPhistoryGetAvgCutoffs(stat->glbhistorycrun, dir);
16333	
16334	   case SCIP_VARSTATUS_FIXED:
16335	      return 0.0;
16336	
16337	   case SCIP_VARSTATUS_AGGREGATED:
16338	      if( var->data.aggregate.scalar > 0.0 )
16339	         return SCIPvarGetAvgCutoffsCurrentRun(var->data.aggregate.var, stat, dir);
16340	      else
16341	         return SCIPvarGetAvgCutoffsCurrentRun(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
16342	
16343	   case SCIP_VARSTATUS_MULTAGGR:
16344	      return 0.0;
16345	
16346	   case SCIP_VARSTATUS_NEGATED:
16347	      return SCIPvarGetAvgCutoffsCurrentRun(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
16348	
16349	   default:
16350	      SCIPerrorMessage("unknown variable status\n");
16351	      SCIPABORT();
16352	      return 0.0; /*lint !e527*/
16353	   }
16354	}
16355	
16356	
16357	
16358	
16359	/*
16360	 * information methods for bound changes
16361	 */
16362	
16363	/** creates an artificial bound change information object with depth = INT_MAX and pos = -1 */
16364	SCIP_RETCODE SCIPbdchginfoCreate(
16365	   SCIP_BDCHGINFO**      bdchginfo,          /**< pointer to store bound change information */
16366	   BMS_BLKMEM*           blkmem,             /**< block memory */
16367	   SCIP_VAR*             var,                /**< active variable that changed the bounds */
16368	   SCIP_BOUNDTYPE        boundtype,          /**< type of bound for var: lower or upper bound */
16369	   SCIP_Real             oldbound,           /**< old value for bound */
16370	   SCIP_Real             newbound            /**< new value for bound */
16371	   )
16372	{
16373	   assert(bdchginfo != NULL);
16374	
16375	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, bdchginfo) );
16376	   (*bdchginfo)->oldbound = oldbound;
16377	   (*bdchginfo)->newbound = newbound;
16378	   (*bdchginfo)->var = var;
16379	   (*bdchginfo)->inferencedata.var = var;
16380	   (*bdchginfo)->inferencedata.reason.prop = NULL;
16381	   (*bdchginfo)->inferencedata.info = 0;
16382	   (*bdchginfo)->bdchgidx.depth = INT_MAX;
16383	   (*bdchginfo)->bdchgidx.pos = -1;
16384	   (*bdchginfo)->pos = 0;
16385	   (*bdchginfo)->boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
16386	   (*bdchginfo)->boundtype = boundtype; /*lint !e641*/
16387	   (*bdchginfo)->inferboundtype = boundtype; /*lint !e641*/
16388	   (*bdchginfo)->redundant = FALSE;
16389	
16390	   return SCIP_OKAY;
16391	}
16392	
16393	/** frees a bound change information object */
16394	void SCIPbdchginfoFree(
16395	   SCIP_BDCHGINFO**      bdchginfo,          /**< pointer to store bound change information */
16396	   BMS_BLKMEM*           blkmem              /**< block memory */
16397	   )
16398	{
16399	   assert(bdchginfo != NULL);
16400	
16401	   BMSfreeBlockMemory(blkmem, bdchginfo);
16402	}
16403	
16404	/** returns the bound change information for the last lower bound change on given active problem variable before or
16405	 *  after the bound change with the given index was applied;
16406	 *  returns NULL, if no change to the lower bound was applied up to this point of time
16407	 */
16408	SCIP_BDCHGINFO* SCIPvarGetLbchgInfo(
16409	   SCIP_VAR*             var,                /**< active problem variable */
16410	   SCIP_BDCHGIDX*        bdchgidx,           /**< bound change index representing time on path to current node */
16411	   SCIP_Bool             after               /**< should the bound change with given index be included? */
16412	   )
16413	{
16414	   int i;
16415	
16416	   assert(var != NULL);
16417	   assert(SCIPvarIsActive(var));
16418	
16419	   /* search the correct bound change information for the given bound change index */
16420	   if( after )
16421	   {
16422	      for( i = var->nlbchginfos-1; i >= 0; --i )
16423	      {
16424	         assert(var->lbchginfos[i].var == var);
16425	         assert((SCIP_BOUNDTYPE)var->lbchginfos[i].boundtype == SCIP_BOUNDTYPE_LOWER);
16426	         assert(var->lbchginfos[i].pos == i);
16427	
16428	         /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16429	         if( var->lbchginfos[i].redundant )
16430	            return NULL;
16431	         assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
16432	
16433	         /* if we reached the bound change index, return the current bound change info */
16434	         if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->lbchginfos[i].bdchgidx) )
16435	            return &var->lbchginfos[i];
16436	      }
16437	   }
16438	   else
16439	   {
16440	      for( i = var->nlbchginfos-1; i >= 0; --i )
16441	      {
16442	         assert(var->lbchginfos[i].var == var);
16443	         assert((SCIP_BOUNDTYPE)var->lbchginfos[i].boundtype == SCIP_BOUNDTYPE_LOWER);
16444	         assert(var->lbchginfos[i].pos == i);
16445	
16446	         /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16447	         if( var->lbchginfos[i].redundant )
16448	            return NULL;
16449	         assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
16450	
16451	         /* if we reached the bound change index, return the current bound change info */
16452	         if( SCIPbdchgidxIsEarlier(&var->lbchginfos[i].bdchgidx, bdchgidx) )
16453	            return &var->lbchginfos[i];
16454	      }
16455	   }
16456	
16457	   return NULL;
16458	}
16459	
16460	/** returns the bound change information for the last upper bound change on given active problem variable before or
16461	 *  after the bound change with the given index was applied;
16462	 *  returns NULL, if no change to the upper bound was applied up to this point of time
16463	 */
16464	SCIP_BDCHGINFO* SCIPvarGetUbchgInfo(
16465	   SCIP_VAR*             var,                /**< active problem variable */
16466	   SCIP_BDCHGIDX*        bdchgidx,           /**< bound change index representing time on path to current node */
16467	   SCIP_Bool             after               /**< should the bound change with given index be included? */
16468	   )
16469	{
16470	   int i;
16471	
16472	   assert(var != NULL);
16473	   assert(SCIPvarIsActive(var));
16474	
16475	   /* search the correct bound change information for the given bound change index */
16476	   if( after )
16477	   {
16478	      for( i = var->nubchginfos-1; i >= 0; --i )
16479	      {
16480	         assert(var->ubchginfos[i].var == var);
16481	         assert((SCIP_BOUNDTYPE)var->ubchginfos[i].boundtype == SCIP_BOUNDTYPE_UPPER);
16482	         assert(var->ubchginfos[i].pos == i);
16483	
16484	         /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16485	         if( var->ubchginfos[i].redundant )
16486	            return NULL;
16487	         assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
16488	
16489	         /* if we reached the bound change index, return the current bound change info */
16490	         if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->ubchginfos[i].bdchgidx) )
16491	            return &var->ubchginfos[i];
16492	      }
16493	   }
16494	   else
16495	   {
16496	      for( i = var->nubchginfos-1; i >= 0; --i )
16497	      {
16498	         assert(var->ubchginfos[i].var == var);
16499	         assert((SCIP_BOUNDTYPE)var->ubchginfos[i].boundtype == SCIP_BOUNDTYPE_UPPER);
16500	         assert(var->ubchginfos[i].pos == i);
16501	
16502	         /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16503	         if( var->ubchginfos[i].redundant )
16504	            return NULL;
16505	         assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
16506	
16507	         /* if we reached the bound change index, return the current bound change info */
16508	         if( SCIPbdchgidxIsEarlier(&var->ubchginfos[i].bdchgidx, bdchgidx) )
16509	            return &var->ubchginfos[i];
16510	      }
16511	   }
16512	
16513	   return NULL;
16514	}
16515	
16516	/** returns the bound change information for the last lower or upper bound change on given active problem variable
16517	 *  before or after the bound change with the given index was applied;
16518	 *  returns NULL, if no change to the lower/upper bound was applied up to this point of time
16519	 */
16520	SCIP_BDCHGINFO* SCIPvarGetBdchgInfo(
16521	   SCIP_VAR*             var,                /**< active problem variable */
16522	   SCIP_BOUNDTYPE        boundtype,          /**< type of bound: lower or upper bound */
16523	   SCIP_BDCHGIDX*        bdchgidx,           /**< bound change index representing time on path to current node */
16524	   SCIP_Bool             after               /**< should the bound change with given index be included? */
16525	   )
16526	{
16527	   if( boundtype == SCIP_BOUNDTYPE_LOWER )
16528	      return SCIPvarGetLbchgInfo(var, bdchgidx, after);
16529	   else
16530	   {
16531	      assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16532	      return SCIPvarGetUbchgInfo(var, bdchgidx, after);
16533	   }
16534	}
16535	
16536	/** returns lower bound of variable directly before or after the bound change given by the bound change index
16537	 *  was applied
16538	 *
16539	 *  @deprecated Please use SCIPgetVarLbAtIndex()
16540	 */
16541	SCIP_Real SCIPvarGetLbAtIndex(
16542	   SCIP_VAR*             var,                /**< problem variable */
16543	   SCIP_BDCHGIDX*        bdchgidx,           /**< bound change index representing time on path to current node */
16544	   SCIP_Bool             after               /**< should the bound change with given index be included? */
16545	   )
16546	{
16547	   SCIP_VARSTATUS varstatus;
16548	   assert(var != NULL);
16549	
16550	   varstatus = SCIPvarGetStatus(var);
16551	
16552	   /* get bounds of attached variables */
16553	   switch( varstatus )
16554	   {
16555	   case SCIP_VARSTATUS_ORIGINAL:
16556	      assert(var->data.original.transvar != NULL);
16557	      return SCIPvarGetLbAtIndex(var->data.original.transvar, bdchgidx, after);
16558	
16559	   case SCIP_VARSTATUS_LOOSE:
16560	   case SCIP_VARSTATUS_COLUMN:
16561	      if( bdchgidx == NULL )
16562	         return SCIPvarGetLbLocal(var);
16563	      else
16564	      {
16565	         SCIP_BDCHGINFO* bdchginfo;
16566	
16567	         bdchginfo = SCIPvarGetLbchgInfo(var, bdchgidx, after);
16568	         if( bdchginfo != NULL )
16569	            return SCIPbdchginfoGetNewbound(bdchginfo);
16570	         else
16571	            return var->glbdom.lb;
16572	      }
16573	   case SCIP_VARSTATUS_FIXED:
16574	      return var->glbdom.lb;
16575	
16576	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
16577	      assert(var->data.aggregate.var != NULL);
16578	      /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16579	       * corresponding infinity value instead of performing an arithmetical transformation (compare method
16580	       * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16581	       * (or is called by) a public interface method; instead, we only assert that values are finite
16582	       * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16583	       * positives and negatives if the parameter <numerics/infinity> is modified by the user
16584	       */
16585	      if( var->data.aggregate.scalar > 0.0 )
16586	      {
16587	         /* a > 0 -> get lower bound of y */
16588	         assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16589	         assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16590	         return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16591	            + var->data.aggregate.constant;
16592	      }
16593	      else if( var->data.aggregate.scalar < 0.0 )
16594	      {
16595	         /* a < 0 -> get upper bound of y */
16596	         assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16597	         assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16598	         return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16599	            + var->data.aggregate.constant;
16600	      }
16601	      else
16602	      {
16603	         SCIPerrorMessage("scalar is zero in aggregation\n");
16604	         SCIPABORT();
16605	         return SCIP_INVALID; /*lint !e527*/
16606	      }
16607	
16608	   case SCIP_VARSTATUS_MULTAGGR:
16609	      /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16610	      if ( var->data.multaggr.nvars == 1 )
16611	      {
16612	         assert(var->data.multaggr.vars != NULL);
16613	         assert(var->data.multaggr.scalars != NULL);
16614	         assert(var->data.multaggr.vars[0] != NULL);
16615	
16616	         if( var->data.multaggr.scalars[0] > 0.0 )
16617	         {
16618	            /* a > 0 -> get lower bound of y */
16619	            assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16620	            assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16621	            return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16622	               + var->data.multaggr.constant;
16623	         }
16624	         else if( var->data.multaggr.scalars[0] < 0.0 )
16625	         {
16626	            /* a < 0 -> get upper bound of y */
16627	            assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16628	            assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16629	            return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16630	               + var->data.multaggr.constant;
16631	         }
16632	         else
16633	         {
16634	            SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16635	            SCIPABORT();
16636	            return SCIP_INVALID; /*lint !e527*/
16637	         }
16638	      }
16639	      SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
16640	      SCIPABORT();
16641	      return SCIP_INVALID; /*lint !e527*/
16642	
16643	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
16644	      assert(var->negatedvar != NULL);
16645	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
16646	      assert(var->negatedvar->negatedvar == var);
16647	      return var->data.negate.constant - SCIPvarGetUbAtIndex(var->negatedvar, bdchgidx, after);
16648	   default:
16649	      SCIPerrorMessage("unknown variable status\n");
16650	      SCIPABORT();
16651	      return SCIP_INVALID; /*lint !e527*/
16652	   }
16653	}
16654	
16655	/** returns upper bound of variable directly before or after the bound change given by the bound change index
16656	 *  was applied
16657	 *
16658	 *  @deprecated Please use SCIPgetVarUbAtIndex()
16659	 */
16660	SCIP_Real SCIPvarGetUbAtIndex(
16661	   SCIP_VAR*             var,                /**< problem variable */
16662	   SCIP_BDCHGIDX*        bdchgidx,           /**< bound change index representing time on path to current node */
16663	   SCIP_Bool             after               /**< should the bound change with given index be included? */
16664	   )
16665	{
16666	   SCIP_VARSTATUS varstatus;
16667	   assert(var != NULL);
16668	
16669	   varstatus = SCIPvarGetStatus(var);
16670	
16671	   /* get bounds of attached variables */
16672	   switch( varstatus )
16673	   {
16674	   case SCIP_VARSTATUS_ORIGINAL:
16675	      assert(var->data.original.transvar != NULL);
16676	      return SCIPvarGetUbAtIndex(var->data.original.transvar, bdchgidx, after);
16677	
16678	   case SCIP_VARSTATUS_COLUMN:
16679	   case SCIP_VARSTATUS_LOOSE:
16680	      if( bdchgidx == NULL )
16681	         return SCIPvarGetUbLocal(var);
16682	      else
16683	      {
16684	         SCIP_BDCHGINFO* bdchginfo;
16685	
16686	         bdchginfo = SCIPvarGetUbchgInfo(var, bdchgidx, after);
16687	         if( bdchginfo != NULL )
16688	            return SCIPbdchginfoGetNewbound(bdchginfo);
16689	         else
16690	            return var->glbdom.ub;
16691	      }
16692	
16693	   case SCIP_VARSTATUS_FIXED:
16694	      return var->glbdom.ub;
16695	
16696	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
16697	      assert(var->data.aggregate.var != NULL);
16698	      /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16699	       * corresponding infinity value instead of performing an arithmetical transformation (compare method
16700	       * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16701	       * (or is called by) a public interface method; instead, we only assert that values are finite
16702	       * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16703	       * positives and negatives if the parameter <numerics/infinity> is modified by the user
16704	       */
16705	      if( var->data.aggregate.scalar > 0.0 )
16706	      {
16707	         /* a > 0 -> get lower bound of y */
16708	         assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16709	         assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16710	         return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16711	            + var->data.aggregate.constant;
16712	      }
16713	      else if( var->data.aggregate.scalar < 0.0 )
16714	      {
16715	         /* a < 0 -> get upper bound of y */
16716	         assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16717	         assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16718	         return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16719	            + var->data.aggregate.constant;
16720	      }
16721	      else
16722	      {
16723	         SCIPerrorMessage("scalar is zero in aggregation\n");
16724	         SCIPABORT();
16725	         return SCIP_INVALID; /*lint !e527*/
16726	      }
16727	
16728	   case SCIP_VARSTATUS_MULTAGGR:
16729	      /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16730	      if ( var->data.multaggr.nvars == 1 )
16731	      {
16732	         assert(var->data.multaggr.vars != NULL);
16733	         assert(var->data.multaggr.scalars != NULL);
16734	         assert(var->data.multaggr.vars[0] != NULL);
16735	
16736	         if( var->data.multaggr.scalars[0] > 0.0 )
16737	         {
16738	            /* a > 0 -> get lower bound of y */
16739	            assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16740	            assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16741	            return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16742	               + var->data.multaggr.constant;
16743	         }
16744	         else if( var->data.multaggr.scalars[0] < 0.0 )
16745	         {
16746	            /* a < 0 -> get upper bound of y */
16747	            assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16748	            assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16749	            return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16750	               + var->data.multaggr.constant;
16751	         }
16752	         else
16753	         {
16754	            SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16755	            SCIPABORT();
16756	            return SCIP_INVALID; /*lint !e527*/
16757	         }
16758	      }
16759	      SCIPerrorMessage("cannot get the bounds of a multiple aggregated variable.\n");
16760	      SCIPABORT();
16761	      return SCIP_INVALID; /*lint !e527*/
16762	
16763	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
16764	      assert(var->negatedvar != NULL);
16765	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
16766	      assert(var->negatedvar->negatedvar == var);
16767	      return var->data.negate.constant - SCIPvarGetLbAtIndex(var->negatedvar, bdchgidx, after);
16768	
16769	   default:
16770	      SCIPerrorMessage("unknown variable status\n");
16771	      SCIPABORT();
16772	      return SCIP_INVALID; /*lint !e527*/
16773	   }
16774	}
16775	
16776	/** returns lower or upper bound of variable directly before or after the bound change given by the bound change index
16777	 *  was applied
16778	 *
16779	 *  @deprecated Please use SCIPgetVarBdAtIndex()
16780	 */
16781	SCIP_Real SCIPvarGetBdAtIndex(
16782	   SCIP_VAR*             var,                /**< problem variable */
16783	   SCIP_BOUNDTYPE        boundtype,          /**< type of bound: lower or upper bound */
16784	   SCIP_BDCHGIDX*        bdchgidx,           /**< bound change index representing time on path to current node */
16785	   SCIP_Bool             after               /**< should the bound change with given index be included? */
16786	   )
16787	{
16788	   if( boundtype == SCIP_BOUNDTYPE_LOWER )
16789	      return SCIPvarGetLbAtIndex(var, bdchgidx, after);
16790	   else
16791	   {
16792	      assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16793	      return SCIPvarGetUbAtIndex(var, bdchgidx, after);
16794	   }
16795	}
16796	
16797	/** returns whether the binary variable was fixed at the time given by the bound change index
16798	 *
16799	 *  @deprecated Please use SCIPgetVarWasFixedAtIndex()
16800	 */
16801	SCIP_Bool SCIPvarWasFixedAtIndex(
16802	   SCIP_VAR*             var,                /**< problem variable */
16803	   SCIP_BDCHGIDX*        bdchgidx,           /**< bound change index representing time on path to current node */
16804	   SCIP_Bool             after               /**< should the bound change with given index be included? */
16805	   )
16806	{
16807	   assert(var != NULL);
16808	   assert(SCIPvarIsBinary(var));
16809	
16810	   /* check the current bounds first in order to decide at which bound change information we have to look
16811	    * (which is expensive because we have to follow the aggregation tree to the active variable)
16812	    */
16813	   return ((SCIPvarGetLbLocal(var) > 0.5 && SCIPvarGetLbAtIndex(var, bdchgidx, after) > 0.5)
16814	      || (SCIPvarGetUbLocal(var) < 0.5 && SCIPvarGetUbAtIndex(var, bdchgidx, after) < 0.5));
16815	}
16816	
16817	/** bound change index representing the initial time before any bound changes took place */
16818	static SCIP_BDCHGIDX initbdchgidx = {-2, 0};
16819	
16820	/** bound change index representing the presolving stage */
16821	static SCIP_BDCHGIDX presolvebdchgidx = {-1, 0};
16822	
16823	/** returns the last bound change index, at which the bounds of the given variable were tightened */
16824	SCIP_BDCHGIDX* SCIPvarGetLastBdchgIndex(
16825	   SCIP_VAR*             var                 /**< problem variable */
16826	   )
16827	{
16828	   SCIP_BDCHGIDX* lbchgidx;
16829	   SCIP_BDCHGIDX* ubchgidx;
16830	
16831	   assert(var != NULL);
16832	
16833	   var = SCIPvarGetProbvar(var);
16834	
16835	   /* check, if variable is original without transformed variable */
16836	   if( var == NULL )
16837	      return &initbdchgidx;
16838	
16839	   /* check, if variable was fixed in presolving */
16840	   if( !SCIPvarIsActive(var) )
16841	      return &presolvebdchgidx;
16842	
16843	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
16844	
16845	   /* get depths of last bound change information for the lower and upper bound */
16846	   lbchgidx = (var->nlbchginfos > 0 && !var->lbchginfos[var->nlbchginfos-1].redundant
16847	      ? &var->lbchginfos[var->nlbchginfos-1].bdchgidx : &initbdchgidx);
16848	   ubchgidx = (var->nubchginfos > 0 && !var->ubchginfos[var->nubchginfos-1].redundant
16849	      ? &var->ubchginfos[var->nubchginfos-1].bdchgidx : &initbdchgidx);
16850	
16851	   if( SCIPbdchgidxIsEarlierNonNull(lbchgidx, ubchgidx) )
16852	      return ubchgidx;
16853	   else
16854	      return lbchgidx;
16855	}
16856	
16857	/** returns the last depth level, at which the bounds of the given variable were tightened;
16858	 *  returns -2, if the variable's bounds are still the global bounds
16859	 *  returns -1, if the variable was fixed in presolving
16860	 */
16861	int SCIPvarGetLastBdchgDepth(
16862	   SCIP_VAR*             var                 /**< problem variable */
16863	   )
16864	{
16865	   SCIP_BDCHGIDX* bdchgidx;
16866	
16867	   bdchgidx = SCIPvarGetLastBdchgIndex(var);
16868	   assert(bdchgidx != NULL);
16869	
16870	   return bdchgidx->depth;
16871	}
16872	
16873	/** returns at which depth in the tree a bound change was applied to the variable that conflicts with the
16874	 *  given bound; returns -1 if the bound does not conflict with the current local bounds of the variable
16875	 */
16876	int SCIPvarGetConflictingBdchgDepth(
16877	   SCIP_VAR*             var,                /**< problem variable */
16878	   SCIP_SET*             set,                /**< global SCIP settings */
16879	   SCIP_BOUNDTYPE        boundtype,          /**< bound type of the conflicting bound */
16880	   SCIP_Real             bound               /**< conflicting bound */
16881	   )
16882	{
16883	   int i;
16884	
16885	   assert(var != NULL);
16886	   assert(set != NULL);
16887	   assert(var->scip == set->scip);
16888	
16889	   if( boundtype == SCIP_BOUNDTYPE_LOWER )
16890	   {
16891	      /* check if the bound is in conflict with the current local bounds */
16892	      if( SCIPsetIsLE(set, bound, var->locdom.ub) )
16893	         return -1;
16894	
16895	      /* check if the bound is in conflict with the global bound */
16896	      if( SCIPsetIsGT(set, bound, var->glbdom.ub) )
16897	         return 0;
16898	
16899	      /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16900	      assert(var->nubchginfos > 0);
16901	      assert(SCIPsetIsGT(set, bound, var->ubchginfos[var->nubchginfos-1].newbound));
16902	
16903	      /* search for the first conflicting bound change */
16904	      for( i = var->nubchginfos-1; i > 0 && SCIPsetIsGT(set, bound, var->ubchginfos[i-1].newbound); --i )
16905	      {
16906	         assert(var->ubchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16907	         assert((SCIP_BOUNDTYPE)var->ubchginfos[i].boundtype == SCIP_BOUNDTYPE_UPPER);
16908	      }
16909	      assert(SCIPsetIsGT(set, bound, var->ubchginfos[i].newbound));             /* bound change i is conflicting */
16910	      assert(i == 0 || SCIPsetIsLE(set, bound, var->ubchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16911	
16912	      /* return the depth at which the first conflicting bound change took place */
16913	      return var->ubchginfos[i].bdchgidx.depth;
16914	   }
16915	   else
16916	   {
16917	      assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16918	
16919	      /* check if the bound is in conflict with the current local bounds */
16920	      if( SCIPsetIsGE(set, bound, var->locdom.lb) )
16921	         return -1;
16922	
16923	      /* check if the bound is in conflict with the global bound */
16924	      if( SCIPsetIsLT(set, bound, var->glbdom.lb) )
16925	         return 0;
16926	
16927	      /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16928	      assert(var->nlbchginfos > 0);
16929	      assert(SCIPsetIsLT(set, bound, var->lbchginfos[var->nlbchginfos-1].newbound));
16930	
16931	      /* search for the first conflicting bound change */
16932	      for( i = var->nlbchginfos-1; i > 0 && SCIPsetIsLT(set, bound, var->lbchginfos[i-1].newbound); --i )
16933	      {
16934	         assert(var->lbchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16935	         assert((SCIP_BOUNDTYPE)var->lbchginfos[i].boundtype == SCIP_BOUNDTYPE_LOWER);
16936	      }
16937	      assert(SCIPsetIsLT(set, bound, var->lbchginfos[i].newbound));             /* bound change i is conflicting */
16938	      assert(i == 0 || SCIPsetIsGE(set, bound, var->lbchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16939	
16940	      /* return the depth at which the first conflicting bound change took place */
16941	      return var->lbchginfos[i].bdchgidx.depth;
16942	   }
16943	}
16944	
16945	/** returns whether the first binary variable was fixed earlier than the second one;
16946	 *  returns FALSE, if the first variable is not fixed, and returns TRUE, if the first variable is fixed, but the
16947	 *  second one is not fixed
16948	 */
16949	SCIP_Bool SCIPvarWasFixedEarlier(
16950	   SCIP_VAR*             var1,               /**< first binary variable */
16951	   SCIP_VAR*             var2                /**< second binary variable */
16952	   )
16953	{
16954	   SCIP_BDCHGIDX* bdchgidx1;
16955	   SCIP_BDCHGIDX* bdchgidx2;
16956	
16957	   assert(var1 != NULL);
16958	   assert(var2 != NULL);
16959	   assert(SCIPvarIsBinary(var1));
16960	   assert(SCIPvarIsBinary(var2));
16961	
16962	   var1 = SCIPvarGetProbvar(var1);
16963	   var2 = SCIPvarGetProbvar(var2);
16964	   assert(var1 != NULL);
16965	   assert(var2 != NULL);
16966	
16967	   /* check, if variables are globally fixed */
16968	   if( !SCIPvarIsActive(var2) || var2->glbdom.lb > 0.5 || var2->glbdom.ub < 0.5 )
16969	      return FALSE;
16970	   if( !SCIPvarIsActive(var1) || var1->glbdom.lb > 0.5 || var1->glbdom.ub < 0.5 )
16971	      return TRUE;
16972	
16973	   assert(SCIPvarGetStatus(var1) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var1) == SCIP_VARSTATUS_COLUMN);
16974	   assert(SCIPvarGetStatus(var2) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var2) == SCIP_VARSTATUS_COLUMN);
16975	   assert(SCIPvarIsBinary(var1));
16976	   assert(SCIPvarIsBinary(var2));
16977	   assert(var1->nlbchginfos + var1->nubchginfos <= 1);
16978	   assert(var2->nlbchginfos + var2->nubchginfos <= 1);
16979	   assert(var1->nlbchginfos == 0 || !var1->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16980	   assert(var1->nubchginfos == 0 || !var1->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16981	   assert(var2->nlbchginfos == 0 || !var2->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16982	   assert(var2->nubchginfos == 0 || !var2->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16983	
16984	   if( var1->nlbchginfos == 1 )
16985	      bdchgidx1 = &var1->lbchginfos[0].bdchgidx;
16986	   else if( var1->nubchginfos == 1 )
16987	      bdchgidx1 = &var1->ubchginfos[0].bdchgidx;
16988	   else
16989	      bdchgidx1 = NULL;
16990	
16991	   if( var2->nlbchginfos == 1 )
16992	      bdchgidx2 = &var2->lbchginfos[0].bdchgidx;
16993	   else if( var2->nubchginfos == 1 )
16994	      bdchgidx2 = &var2->ubchginfos[0].bdchgidx;
16995	   else
16996	      bdchgidx2 = NULL;
16997	
16998	   return SCIPbdchgidxIsEarlier(bdchgidx1, bdchgidx2);
16999	}
17000	
17001	
17002	
17003	/*
17004	 * Hash functions
17005	 */
17006	
17007	/** gets the key (i.e. the name) of the given variable */
17008	SCIP_DECL_HASHGETKEY(SCIPhashGetKeyVar)
17009	{  /*lint --e{715}*/
17010	   SCIP_VAR* var = (SCIP_VAR*)elem;
17011	
17012	   assert(var != NULL);
17013	   return var->name;
17014	}
17015	
17016	
17017	
17018	
17019	/*
17020	 * simple functions implemented as defines
17021	 */
17022	
17023	/* In debug mode, the following methods are implemented as function calls to ensure
17024	 * type validity.
17025	 * In optimized mode, the methods are implemented as defines to improve performance.
17026	 * However, we want to have them in the library anyways, so we have to undef the defines.
17027	 */
17028	
17029	#undef SCIPboundchgGetNewbound
17030	#undef SCIPboundchgGetVar
17031	#undef SCIPboundchgGetBoundchgtype
17032	#undef SCIPboundchgGetBoundtype
17033	#undef SCIPboundchgIsRedundant
17034	#undef SCIPdomchgGetNBoundchgs
17035	#undef SCIPdomchgGetBoundchg
17036	#undef SCIPholelistGetLeft
17037	#undef SCIPholelistGetRight
17038	#undef SCIPholelistGetNext
17039	#undef SCIPvarGetName
17040	#undef SCIPvarGetNUses
17041	#undef SCIPvarGetData
17042	#undef SCIPvarSetData
17043	#undef SCIPvarSetDelorigData
17044	#undef SCIPvarSetTransData
17045	#undef SCIPvarSetDeltransData
17046	#undef SCIPvarGetStatus
17047	#undef SCIPvarIsOriginal
17048	#undef SCIPvarIsTransformed
17049	#undef SCIPvarIsNegated
17050	#undef SCIPvarGetType
17051	#undef SCIPvarIsBinary
17052	#undef SCIPvarIsIntegral
17053	#undef SCIPvarIsInitial
17054	#undef SCIPvarIsRemovable
17055	#undef SCIPvarIsDeleted
17056	#undef SCIPvarIsDeletable
17057	#undef SCIPvarMarkDeletable
17058	#undef SCIPvarMarkNotDeletable
17059	#undef SCIPvarIsActive
17060	#undef SCIPvarGetIndex
17061	#undef SCIPvarGetProbindex
17062	#undef SCIPvarGetTransVar
17063	#undef SCIPvarGetCol
17064	#undef SCIPvarIsInLP
17065	#undef SCIPvarGetAggrVar
17066	#undef SCIPvarGetAggrScalar
17067	#undef SCIPvarGetAggrConstant
17068	#undef SCIPvarGetMultaggrNVars
17069	#undef SCIPvarGetMultaggrVars
17070	#undef SCIPvarGetMultaggrScalars
17071	#undef SCIPvarGetMultaggrConstant
17072	#undef SCIPvarGetNegatedVar
17073	#undef SCIPvarGetNegationVar
17074	#undef SCIPvarGetNegationConstant
17075	#undef SCIPvarGetObj
17076	#undef SCIPvarGetLbOriginal
17077	#undef SCIPvarGetUbOriginal
17078	#undef SCIPvarGetHolelistOriginal
17079	#undef SCIPvarGetLbGlobal
17080	#undef SCIPvarGetUbGlobal
17081	#undef SCIPvarGetHolelistGlobal
17082	#undef SCIPvarGetBestBoundGlobal
17083	#undef SCIPvarGetWorstBoundGlobal
17084	#undef SCIPvarGetLbLocal
17085	#undef SCIPvarGetUbLocal
17086	#undef SCIPvarGetHolelistLocal
17087	#undef SCIPvarGetBestBoundLocal
17088	#undef SCIPvarGetWorstBoundLocal
17089	#undef SCIPvarGetBestBoundType
17090	#undef SCIPvarGetWorstBoundType
17091	#undef SCIPvarGetLbLazy
17092	#undef SCIPvarGetUbLazy
17093	#undef SCIPvarGetBranchFactor
17094	#undef SCIPvarGetBranchPriority
17095	#undef SCIPvarGetBranchDirection
17096	#undef SCIPvarGetNVlbs
17097	#undef SCIPvarGetVlbVars
17098	#undef SCIPvarGetVlbCoefs
17099	#undef SCIPvarGetVlbConstants
17100	#undef SCIPvarGetNVubs
17101	#undef SCIPvarGetVubVars
17102	#undef SCIPvarGetVubCoefs
17103	#undef SCIPvarGetVubConstants
17104	#undef SCIPvarGetNImpls
17105	#undef SCIPvarGetImplVars
17106	#undef SCIPvarGetImplTypes
17107	#undef SCIPvarGetImplBounds
17108	#undef SCIPvarGetImplIds
17109	#undef SCIPvarGetNCliques
17110	#undef SCIPvarGetCliques
17111	#undef SCIPvarGetLPSol
17112	#undef SCIPvarGetNLPSol
17113	#undef SCIPvarGetBdchgInfoLb
17114	#undef SCIPvarGetNBdchgInfosLb
17115	#undef SCIPvarGetBdchgInfoUb
17116	#undef SCIPvarGetNBdchgInfosUb
17117	#undef SCIPvarGetValuehistory
17118	#undef SCIPvarGetPseudoSol
17119	#undef SCIPvarCatchEvent
17120	#undef SCIPvarDropEvent
17121	#undef SCIPvarGetVSIDS
17122	#undef SCIPvarGetCliqueComponentIdx
17123	#undef SCIPvarIsRelaxationOnly
17124	#undef SCIPvarMarkRelaxationOnly
17125	#undef SCIPbdchgidxGetPos
17126	#undef SCIPbdchgidxIsEarlierNonNull
17127	#undef SCIPbdchgidxIsEarlier
17128	#undef SCIPbdchginfoGetOldbound
17129	#undef SCIPbdchginfoGetNewbound
17130	#undef SCIPbdchginfoGetVar
17131	#undef SCIPbdchginfoGetChgtype
17132	#undef SCIPbdchginfoGetBoundtype
17133	#undef SCIPbdchginfoGetDepth
17134	#undef SCIPbdchginfoGetPos
17135	#undef SCIPbdchginfoGetIdx
17136	#undef SCIPbdchginfoGetInferVar
17137	#undef SCIPbdchginfoGetInferCons
17138	#undef SCIPbdchginfoGetInferProp
17139	#undef SCIPbdchginfoGetInferInfo
17140	#undef SCIPbdchginfoGetInferBoundtype
17141	#undef SCIPbdchginfoIsRedundant
17142	#undef SCIPbdchginfoHasInferenceReason
17143	#undef SCIPbdchginfoIsTighter
17144	
17145	
17146	/** returns the new value of the bound in the bound change data */
17147	SCIP_Real SCIPboundchgGetNewbound(
17148	   SCIP_BOUNDCHG*        boundchg            /**< bound change data */
17149	   )
17150	{
17151	   assert(boundchg != NULL);
17152	
17153	   return boundchg->newbound;
17154	}
17155	
17156	/** returns the variable of the bound change in the bound change data */
17157	SCIP_VAR* SCIPboundchgGetVar(
17158	   SCIP_BOUNDCHG*        boundchg            /**< bound change data */
17159	   )
17160	{
17161	   assert(boundchg != NULL);
17162	
17163	   return boundchg->var;
17164	}
17165	
17166	/** returns the bound change type of the bound change in the bound change data */
17167	SCIP_BOUNDCHGTYPE SCIPboundchgGetBoundchgtype(
17168	   SCIP_BOUNDCHG*        boundchg            /**< bound change data */
17169	   )
17170	{
17171	   assert(boundchg != NULL);
17172	
17173	   return (SCIP_BOUNDCHGTYPE)(boundchg->boundchgtype);
17174	}
17175	
17176	/** returns the bound type of the bound change in the bound change data */
17177	SCIP_BOUNDTYPE SCIPboundchgGetBoundtype(
17178	   SCIP_BOUNDCHG*        boundchg            /**< bound change data */
17179	   )
17180	{
17181	   assert(boundchg != NULL);
17182	
17183	   return (SCIP_BOUNDTYPE)(boundchg->boundtype);
17184	}
17185	
17186	/** returns whether the bound change is redundant due to a more global bound that is at least as strong */
17187	SCIP_Bool SCIPboundchgIsRedundant(
17188	   SCIP_BOUNDCHG*        boundchg            /**< bound change data */
17189	   )
17190	{
17191	   assert(boundchg != NULL);
17192	
17193	   return boundchg->redundant;
17194	}
17195	
17196	/** returns the number of bound changes in the domain change data */
17197	int SCIPdomchgGetNBoundchgs(
17198	   SCIP_DOMCHG*          domchg              /**< domain change data */
17199	   )
17200	{
17201	   return domchg != NULL ? domchg->domchgbound.nboundchgs : 0;
17202	}
17203	
17204	/** returns a particular bound change in the domain change data */
17205	SCIP_BOUNDCHG* SCIPdomchgGetBoundchg(
17206	   SCIP_DOMCHG*          domchg,             /**< domain change data */
17207	   int                   pos                 /**< position of the bound change in the domain change data */
17208	   )
17209	{
17210	   assert(domchg != NULL);
17211	   assert(0 <= pos && pos < (int)domchg->domchgbound.nboundchgs);
17212	
17213	   return &domchg->domchgbound.boundchgs[pos];
17214	}
17215	
17216	/** returns left bound of open interval in hole */
17217	SCIP_Real SCIPholelistGetLeft(
17218	   SCIP_HOLELIST*        holelist            /**< hole list pointer to hole of interest */
17219	   )
17220	{
17221	   assert(holelist != NULL);
17222	
17223	   return holelist->hole.left;
17224	}
17225	
17226	/** returns right bound of open interval in hole */
17227	SCIP_Real SCIPholelistGetRight(
17228	   SCIP_HOLELIST*        holelist            /**< hole list pointer to hole of interest */
17229	   )
17230	{
17231	   assert(holelist != NULL);
17232	
17233	   return holelist->hole.right;
17234	}
17235	
17236	/** returns next hole in list */
17237	SCIP_HOLELIST* SCIPholelistGetNext(
17238	   SCIP_HOLELIST*        holelist            /**< hole list pointer to hole of interest */
17239	   )
17240	{
17241	   assert(holelist != NULL);
17242	
17243	   return holelist->next;
17244	}
17245	
17246	/** returns the name of the variable
17247	 *
17248	 *  @note to change the name of a variable, use SCIPchgVarName() from scip.h
17249	 */
17250	const char* SCIPvarGetName(
17251	   SCIP_VAR*             var                 /**< problem variable */
17252	   )
17253	{
17254	   assert(var != NULL);
17255	
17256	   return var->name;
17257	}
17258	
17259	/** gets number of times, the variable is currently captured */
17260	int SCIPvarGetNUses(
17261	   SCIP_VAR*             var                 /**< problem variable */
17262	   )
17263	{
17264	   assert(var != NULL);
17265	
17266	   return var->nuses;
17267	}
17268	
17269	/** returns the user data of the variable */
17270	SCIP_VARDATA* SCIPvarGetData(
17271	   SCIP_VAR*             var                 /**< problem variable */
17272	   )
17273	{
17274	   assert(var != NULL);
17275	
17276	   return var->vardata;
17277	}
17278	
17279	/** sets the user data for the variable */
17280	void SCIPvarSetData(
17281	   SCIP_VAR*             var,                /**< problem variable */
17282	   SCIP_VARDATA*         vardata             /**< user variable data */
17283	   )
17284	{
17285	   assert(var != NULL);
17286	
17287	   var->vardata = vardata;
17288	}
17289	
17290	/** sets method to free user data for the original variable */
17291	void SCIPvarSetDelorigData(
17292	   SCIP_VAR*             var,                /**< problem variable */
17293	   SCIP_DECL_VARDELORIG  ((*vardelorig))     /**< frees user data of original variable */
17294	   )
17295	{
17296	   assert(var != NULL);
17297	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17298	
17299	   var->vardelorig = vardelorig;
17300	}
17301	
17302	/** sets method to transform user data of the variable */
17303	void SCIPvarSetTransData(
17304	   SCIP_VAR*             var,                /**< problem variable */
17305	   SCIP_DECL_VARTRANS    ((*vartrans))       /**< creates transformed user data by transforming original user data */
17306	   )
17307	{
17308	   assert(var != NULL);
17309	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17310	
17311	   var->vartrans = vartrans;
17312	}
17313	
17314	/** sets method to free transformed user data for the variable */
17315	void SCIPvarSetDeltransData(
17316	   SCIP_VAR*             var,                /**< problem variable */
17317	   SCIP_DECL_VARDELTRANS ((*vardeltrans))    /**< frees user data of transformed variable */
17318	   )
17319	{
17320	   assert(var != NULL);
17321	
17322	   var->vardeltrans = vardeltrans;
17323	}
17324	
17325	/** sets method to copy this variable into sub-SCIPs */
17326	void SCIPvarSetCopyData(
17327	   SCIP_VAR*             var,                /**< problem variable */
17328	   SCIP_DECL_VARCOPY     ((*varcopy))        /**< copy method of the variable */
17329	   )
17330	{
17331	   assert(var != NULL);
17332	
17333	   var->varcopy = varcopy;
17334	}
17335	
17336	/** sets the initial flag of a variable; only possible for original or loose variables */
17337	SCIP_RETCODE SCIPvarSetInitial(
17338	   SCIP_VAR*             var,                /**< problem variable */
17339	   SCIP_Bool             initial             /**< initial flag */
17340	   )
17341	{
17342	   assert(var != NULL);
17343	
17344	   if( (SCIP_VARSTATUS)var->varstatus != SCIP_VARSTATUS_ORIGINAL && (SCIP_VARSTATUS)var->varstatus != SCIP_VARSTATUS_LOOSE )
17345	      return SCIP_INVALIDCALL;
17346	
17347	   var->initial = initial;
17348	
17349	   return SCIP_OKAY;
17350	}
17351	
17352	/** sets the removable flag of a variable; only possible for original or loose variables */
17353	SCIP_RETCODE SCIPvarSetRemovable(
17354	   SCIP_VAR*             var,                /**< problem variable */
17355	   SCIP_Bool             removable           /**< removable flag */
17356	   )
17357	{
17358	   assert(var != NULL);
17359	
17360	   if( (SCIP_VARSTATUS)var->varstatus != SCIP_VARSTATUS_ORIGINAL && (SCIP_VARSTATUS)var->varstatus != SCIP_VARSTATUS_LOOSE )
17361	      return SCIP_INVALIDCALL;
17362	
17363	   var->removable = removable;
17364	
17365	   return SCIP_OKAY;
17366	}
17367	
17368	/** gets status of variable */
17369	SCIP_VARSTATUS SCIPvarGetStatus(
17370	   SCIP_VAR*             var                 /**< problem variable */
17371	   )
17372	{
17373	   assert(var != NULL);
17374	
17375	   return (SCIP_VARSTATUS)(var->varstatus);
17376	}
17377	
17378	/** returns whether the variable belongs to the original problem */
17379	SCIP_Bool SCIPvarIsOriginal(
17380	   SCIP_VAR*             var                 /**< problem variable */
17381	   )
17382	{
17383	   assert(var != NULL);
17384	   assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
17385	
17386	   return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL
17387	      || (SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED
17388	         && SCIPvarGetStatus(var->negatedvar) == SCIP_VARSTATUS_ORIGINAL));
17389	}
17390	
17391	/** returns whether the variable belongs to the transformed problem */
17392	SCIP_Bool SCIPvarIsTransformed(
17393	   SCIP_VAR*             var                 /**< problem variable */
17394	   )
17395	{
17396	   assert(var != NULL);
17397	   assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
17398	
17399	   return (SCIPvarGetStatus(var) != SCIP_VARSTATUS_ORIGINAL
17400	      && (SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED
17401	         || SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_ORIGINAL));
17402	}
17403	
17404	/** returns whether the variable was created by negation of a different variable */
17405	SCIP_Bool SCIPvarIsNegated(
17406	   SCIP_VAR*             var                 /**< problem variable */
17407	   )
17408	{
17409	   assert(var != NULL);
17410	
17411	   return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17412	}
17413	
17414	/** gets type of variable */
17415	SCIP_VARTYPE SCIPvarGetType(
17416	   SCIP_VAR*             var                 /**< problem variable */
17417	   )
17418	{
17419	   assert(var != NULL);
17420	
17421	   return (SCIP_VARTYPE)(var->vartype);
17422	}
17423	
17424	/** returns TRUE if the variable is of binary type; this is the case if:
17425	 *  (1) variable type is binary
17426	 *  (2) variable type is integer or implicit integer and 
17427	 *      (i)  the global lower bound is greater than or equal to zero
17428	 *      (ii) the global upper bound is less than or equal to one
17429	 */
17430	SCIP_Bool SCIPvarIsBinary(
17431	   SCIP_VAR*             var                 /**< problem variable */
17432	   )
17433	{
17434	   assert(var != NULL);
17435	
17436	   return (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY || 
17437	      (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && var->glbdom.lb >= 0.0 && var->glbdom.ub <= 1.0));
17438	}
17439	
17440	/** returns whether variable is of integral type (binary, integer, or implicit integer) */
17441	SCIP_Bool SCIPvarIsIntegral(
17442	   SCIP_VAR*             var                 /**< problem variable */
17443	   )
17444	{
17445	   assert(var != NULL);
17446	
17447	   return (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
17448	}
17449	
17450	/** returns whether variable's column should be present in the initial root LP */
17451	SCIP_Bool SCIPvarIsInitial(
17452	   SCIP_VAR*             var                 /**< problem variable */
17453	   )
17454	{
17455	   assert(var != NULL);
17456	
17457	   return var->initial;
17458	}
17459	
17460	/** returns whether variable's column is removable from the LP (due to aging or cleanup) */
17461	SCIP_Bool SCIPvarIsRemovable(
17462	   SCIP_VAR*             var                 /**< problem variable */
17463	   )
17464	{
17465	   assert(var != NULL);
17466	
17467	   return var->removable;
17468	}
17469	
17470	/** returns whether the variable was deleted from the problem */
17471	SCIP_Bool SCIPvarIsDeleted(
17472	   SCIP_VAR*             var                 /**< problem variable */
17473	   )
17474	{
17475	   assert(var != NULL);
17476	
17477	   return var->deleted;
17478	}
17479	
17480	/** marks the variable to be deletable, i.e., it may be deleted completely from the problem;
17481	 *  method can only be called before the variable is added to the problem by SCIPaddVar() or SCIPaddPricedVar()
17482	 */
17483	void SCIPvarMarkDeletable(
17484	   SCIP_VAR*             var                 /**< problem variable */
17485	   )
17486	{
17487	   assert(var != NULL);
17488	   assert(var->probindex == -1);
17489	
17490	   var->deletable = TRUE;
17491	}
17492	
17493	/** marks the variable to be not deletable from the problem */
17494	void SCIPvarMarkNotDeletable(
17495	   SCIP_VAR*             var
17496	   )
17497	{
17498	   assert(var != NULL);
17499	
17500	   var->deletable = FALSE;
17501	}
17502	
17503	/** marks variable to be deleted from global structures (cliques etc.) when cleaning up
17504	 *
17505	 *  @note: this is not equivalent to marking the variable itself for deletion, this is done by using SCIPvarMarkDeletable()
17506	 */
17507	void SCIPvarMarkDeleteGlobalStructures(
17508	   SCIP_VAR*             var                 /**< problem variable */
17509	   )
17510	{
17511	   assert(var != NULL);
17512	
17513	   var->delglobalstructs = TRUE;
17514	}
17515	
17516	/** returns whether the variable was flagged for deletion from global structures (cliques etc.) */
17517	SCIP_Bool SCIPvarIsMarkedDeleteGlobalStructures(
17518	   SCIP_VAR*             var                 /**< problem variable */
17519	   )
17520	{
17521	   assert(var != NULL);
17522	
17523	   return var->delglobalstructs;
17524	}
17525	
17526	/** returns whether a variable has been introduced to define a relaxation
17527	 *
17528	 * These variables are only valid for the current SCIP solve round,
17529	 * they are not contained in any (checked) constraints, but may be used
17530	 * in cutting planes, for example.
17531	 * Relaxation-only variables are not copied by SCIPcopyVars and cuts
17532	 * that contain these variables are not added as linear constraints when
17533	 * restarting or transferring information from a copied SCIP to a SCIP.
17534	 * Also conflicts with relaxation-only variables are not generated at
17535	 * the moment.
17536	 */
17537	SCIP_Bool SCIPvarIsRelaxationOnly(
17538	   SCIP_VAR*             var                 /**< problem variable */
17539	   )
17540	{
17541	   assert(var != NULL);
17542	
17543	   return var->relaxationonly;
17544	}
17545	
17546	/** marks that this variable has only been introduced to define a relaxation
17547	 *
17548	 * The variable must not have a coefficient in the objective and must be deletable.
17549	 * If it is not marked deletable, it will be marked as deletable, which is only possible
17550	 * before the variable is added to a problem.
17551	 *
17552	 * @see SCIPvarIsRelaxationOnly
17553	 * @see SCIPvarMarkDeletable
17554	 */
17555	void SCIPvarMarkRelaxationOnly(
17556	   SCIP_VAR*             var                 /**< problem variable */
17557	   )
17558	{
17559	   assert(var != NULL);
17560	   assert(SCIPvarGetObj(var) == 0.0);
17561	
17562	   if( !SCIPvarIsDeletable(var) )
17563	      SCIPvarMarkDeletable(var);
17564	
17565	   var->relaxationonly = TRUE;
17566	}
17567	
17568	/** returns whether variable is allowed to be deleted completely from the problem */
17569	SCIP_Bool SCIPvarIsDeletable(
17570	   SCIP_VAR*             var
17571	   )
17572	{
17573	   assert(var != NULL);
17574	
17575	   return var->deletable;
17576	}
17577	
17578	/** returns whether variable is an active (neither fixed nor aggregated) variable */
17579	SCIP_Bool SCIPvarIsActive(
17580	   SCIP_VAR*             var                 /**< problem variable */
17581	   )
17582	{
17583	   assert(var != NULL);
17584	
17585	   return (var->probindex >= 0);
17586	}
17587	
17588	/** gets unique index of variable */
17589	int SCIPvarGetIndex(
17590	   SCIP_VAR*             var                 /**< problem variable */
17591	   )
17592	{
17593	   assert(var != NULL);
17594	
17595	   return var->index;
17596	}
17597	
17598	/** gets position of variable in problem, or -1 if variable is not active */
17599	int SCIPvarGetProbindex(
17600	   SCIP_VAR*             var                 /**< problem variable */
17601	   )
17602	{
17603	   assert(var != NULL);
17604	
17605	   return var->probindex;
17606	}
17607	
17608	/** gets transformed variable of ORIGINAL variable */
17609	SCIP_VAR* SCIPvarGetTransVar(
17610	   SCIP_VAR*             var                 /**< problem variable */
17611	   )
17612	{
17613	   assert(var != NULL);
17614	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17615	
17616	   return var->data.original.transvar;
17617	}
17618	
17619	/** gets column of COLUMN variable */
17620	SCIP_COL* SCIPvarGetCol(
17621	   SCIP_VAR*             var                 /**< problem variable */
17622	   )
17623	{
17624	   assert(var != NULL);
17625	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
17626	
17627	   return var->data.col;
17628	}
17629	
17630	/** returns whether the variable is a COLUMN variable that is member of the current LP */
17631	SCIP_Bool SCIPvarIsInLP(
17632	   SCIP_VAR*             var                 /**< problem variable */
17633	   )
17634	{
17635	   assert(var != NULL);
17636	
17637	   return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN && SCIPcolIsInLP(var->data.col));
17638	}
17639	
17640	/** gets aggregation variable y of an aggregated variable x = a*y + c */
17641	SCIP_VAR* SCIPvarGetAggrVar(
17642	   SCIP_VAR*             var                 /**< problem variable */
17643	   )
17644	{
17645	   assert(var != NULL);
17646	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_AGGREGATED);
17647	   assert(!var->donotaggr);
17648	
17649	   return var->data.aggregate.var;
17650	}
17651	
17652	/** gets aggregation scalar a of an aggregated variable x = a*y + c */
17653	SCIP_Real SCIPvarGetAggrScalar(
17654	   SCIP_VAR*             var                 /**< problem variable */
17655	   )
17656	{
17657	   assert(var != NULL);
17658	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_AGGREGATED);
17659	   assert(!var->donotaggr);
17660	
17661	   return var->data.aggregate.scalar;
17662	}
17663	
17664	/** gets aggregation constant c of an aggregated variable x = a*y + c */
17665	SCIP_Real SCIPvarGetAggrConstant(
17666	   SCIP_VAR*             var                 /**< problem variable */
17667	   )
17668	{
17669	   assert(var != NULL);
17670	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_AGGREGATED);
17671	   assert(!var->donotaggr);
17672	
17673	   return var->data.aggregate.constant;
17674	}
17675	
17676	/** gets number n of aggregation variables of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17677	int SCIPvarGetMultaggrNVars(
17678	   SCIP_VAR*             var                 /**< problem variable */
17679	   )
17680	{
17681	   assert(var != NULL);
17682	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17683	   assert(!var->donotmultaggr);
17684	
17685	   return var->data.multaggr.nvars;
17686	}
17687	
17688	/** gets vector of aggregation variables y of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17689	SCIP_VAR** SCIPvarGetMultaggrVars(
17690	   SCIP_VAR*             var                 /**< problem variable */
17691	   )
17692	{
17693	   assert(var != NULL);
17694	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17695	   assert(!var->donotmultaggr);
17696	
17697	   return var->data.multaggr.vars;
17698	}
17699	
17700	/** gets vector of aggregation scalars a of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17701	SCIP_Real* SCIPvarGetMultaggrScalars(
17702	   SCIP_VAR*             var                 /**< problem variable */
17703	   )
17704	{
17705	   assert(var != NULL);
17706	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17707	   assert(!var->donotmultaggr);
17708	
17709	   return var->data.multaggr.scalars;
17710	}
17711	
17712	/** gets aggregation constant c of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17713	SCIP_Real SCIPvarGetMultaggrConstant(
17714	   SCIP_VAR*             var                 /**< problem variable */
17715	   )
17716	{
17717	   assert(var != NULL);
17718	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17719	   assert(!var->donotmultaggr);
17720	
17721	   return var->data.multaggr.constant;
17722	}
17723	
17724	/** gets the negation of the given variable; may return NULL, if no negation is existing yet */
17725	SCIP_VAR* SCIPvarGetNegatedVar(
17726	   SCIP_VAR*             var                 /**< negated problem variable */
17727	   )
17728	{
17729	   assert(var != NULL);
17730	
17731	   return var->negatedvar;
17732	}
17733	
17734	/** gets the negation variable x of a negated variable x' = offset - x */
17735	SCIP_VAR* SCIPvarGetNegationVar(
17736	   SCIP_VAR*             var                 /**< negated problem variable */
17737	   )
17738	{
17739	   assert(var != NULL);
17740	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17741	
17742	   return var->negatedvar;
17743	}
17744	
17745	/** gets the negation offset of a negated variable x' = offset - x */
17746	SCIP_Real SCIPvarGetNegationConstant(
17747	   SCIP_VAR*             var                 /**< negated problem variable */
17748	   )
17749	{
17750	   assert(var != NULL);
17751	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17752	
17753	   return var->data.negate.constant;
17754	}
17755	
17756	/** gets objective function value of variable */
17757	SCIP_Real SCIPvarGetObj(
17758	   SCIP_VAR*             var                 /**< problem variable */
17759	   )
17760	{
17761	   assert(var != NULL);
17762	
17763	   return var->obj;
17764	}
17765	
17766	/** gets the unchanged objective function value of a variable (ignoring temproray changes performed in probing mode) */
17767	SCIP_Real SCIPvarGetUnchangedObj(
17768	   SCIP_VAR*             var                 /**< problem variable */
17769	   )
17770	{
17771	   assert(var != NULL);
17772	
17773	   return var->unchangedobj;
17774	}
17775	
17776	/** gets corresponding objective value of active, fixed, or multi-aggregated problem variable of given variable
17777	 *  e.g. obj(x) = 1 this method returns for ~x the value -1
17778	 */
17779	SCIP_RETCODE SCIPvarGetAggregatedObj(
17780	   SCIP_VAR*             var,                /**< problem variable */
17781	   SCIP_Real*            aggrobj             /**< pointer to store the aggregated objective value */
17782	   )
17783	{
17784	   SCIP_VAR* probvar = var;
17785	   SCIP_Real mult = 1.0;
17786	
17787	   assert(probvar != NULL);
17788	   assert(aggrobj != NULL);
17789	
17790	   while( probvar != NULL )
17791	   {
17792	      switch( SCIPvarGetStatus(probvar) )
17793	      {
17794	      case SCIP_VARSTATUS_ORIGINAL:
17795	      case SCIP_VARSTATUS_LOOSE:
17796	      case SCIP_VARSTATUS_COLUMN:
17797		 (*aggrobj) = mult * SCIPvarGetObj(probvar);
17798		 return SCIP_OKAY;
17799	
17800	      case SCIP_VARSTATUS_FIXED:
17801		 assert(SCIPvarGetObj(probvar) == 0.0);
17802		 (*aggrobj) = 0.0;
17803	         return SCIP_OKAY;
17804	
17805	      case SCIP_VARSTATUS_MULTAGGR:
17806	         /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17807	         if ( probvar->data.multaggr.nvars == 1 )
17808	         {
17809	            assert( probvar->data.multaggr.vars != NULL );
17810	            assert( probvar->data.multaggr.scalars != NULL );
17811	            assert( probvar->data.multaggr.vars[0] != NULL );
17812	            mult *= probvar->data.multaggr.scalars[0];
17813	            probvar = probvar->data.multaggr.vars[0];
17814	            break;
17815	         }
17816		 else
17817		 {
17818		    SCIP_Real tmpobj;
17819		    int v;
17820	
17821		    (*aggrobj) = 0.0;
17822	
17823		    for( v = probvar->data.multaggr.nvars - 1; v >= 0; --v )
17824		    {
17825		       SCIP_CALL( SCIPvarGetAggregatedObj(probvar->data.multaggr.vars[v], &tmpobj) );
17826		       (*aggrobj) += probvar->data.multaggr.scalars[v] * tmpobj;
17827		    }
17828		    return SCIP_OKAY;
17829		 }
17830	
17831	      case SCIP_VARSTATUS_AGGREGATED:  /* x = a'*x' + c'  =>  a*x + c == (a*a')*x' + (a*c' + c) */
17832	         assert(probvar->data.aggregate.var != NULL);
17833	         mult *= probvar->data.aggregate.scalar;
17834	         probvar = probvar->data.aggregate.var;
17835	         break;
17836	
17837	      case SCIP_VARSTATUS_NEGATED:     /* x =  - x' + c'  =>  a*x + c ==   (-a)*x' + (a*c' + c) */
17838	         assert(probvar->negatedvar != NULL);
17839	         assert(SCIPvarGetStatus(probvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
17840	         assert(probvar->negatedvar->negatedvar == probvar);
17841	         mult *= -1.0;
17842	         probvar = probvar->negatedvar;
17843	         break;
17844	
17845	      default:
17846		 SCIPABORT();
17847		 return SCIP_INVALIDDATA; /*lint !e527*/
17848	      }
17849	   }
17850	
17851	   return SCIP_INVALIDDATA;
17852	}
17853	
17854	/** gets original lower bound of original problem variable (i.e. the bound set in problem creation) */
17855	SCIP_Real SCIPvarGetLbOriginal(
17856	   SCIP_VAR*             var                 /**< original problem variable */
17857	   )
17858	{
17859	   assert(var != NULL);
17860	   assert(SCIPvarIsOriginal(var));
17861	
17862	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL )
17863	      return var->data.original.origdom.lb;
17864	   else
17865	   {
17866	      assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17867	      assert(var->negatedvar != NULL);
17868	      assert(SCIPvarGetStatus(var->negatedvar) == SCIP_VARSTATUS_ORIGINAL);
17869	
17870	      return var->data.negate.constant - var->negatedvar->data.original.origdom.ub;
17871	   }
17872	}
17873	
17874	/** gets original upper bound of original problem variable (i.e. the bound set in problem creation) */
17875	SCIP_Real SCIPvarGetUbOriginal(
17876	   SCIP_VAR*             var                 /**< original problem variable */
17877	   )
17878	{
17879	   assert(var != NULL);
17880	   assert(SCIPvarIsOriginal(var));
17881	
17882	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL )
17883	      return var->data.original.origdom.ub;
17884	   else
17885	   {
17886	      assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17887	      assert(var->negatedvar != NULL);
17888	      assert(SCIPvarGetStatus(var->negatedvar) == SCIP_VARSTATUS_ORIGINAL);
17889	
17890	      return var->data.negate.constant - var->negatedvar->data.original.origdom.lb;
17891	   }
17892	}
17893	
17894	/** gets the original hole list of an original variable */
17895	SCIP_HOLELIST* SCIPvarGetHolelistOriginal(
17896	   SCIP_VAR*             var                 /**< problem variable */
17897	   )
17898	{
17899	   assert(var != NULL);
17900	   assert(SCIPvarIsOriginal(var));
17901	
17902	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL )
17903	      return var->data.original.origdom.holelist;
17904	
17905	   return NULL;
17906	}
17907	
17908	/** gets global lower bound of variable */
17909	SCIP_Real SCIPvarGetLbGlobal(
17910	   SCIP_VAR*             var                 /**< problem variable */
17911	   )
17912	{
17913	   assert(var != NULL);
17914	
17915	   return var->glbdom.lb;
17916	}
17917	
17918	/** gets global upper bound of variable */
17919	SCIP_Real SCIPvarGetUbGlobal(
17920	   SCIP_VAR*             var                 /**< problem variable */
17921	   )
17922	{
17923	   assert(var != NULL);
17924	
17925	   return var->glbdom.ub;
17926	}
17927	
17928	/** gets the global hole list of an active variable */
17929	SCIP_HOLELIST* SCIPvarGetHolelistGlobal(
17930	   SCIP_VAR*             var                 /**< problem variable */
17931	   )
17932	{
17933	   assert(var != NULL);
17934	
17935	   return var->glbdom.holelist;
17936	}
17937	
17938	/** gets best global bound of variable with respect to the objective function */
17939	SCIP_Real SCIPvarGetBestBoundGlobal(
17940	   SCIP_VAR*             var                 /**< problem variable */
17941	   )
17942	{
17943	   assert(var != NULL);
17944	
17945	   if( var->obj >= 0.0 )
17946	      return var->glbdom.lb;
17947	   else
17948	      return var->glbdom.ub;
17949	}
17950	
17951	/** gets worst global bound of variable with respect to the objective function */
17952	SCIP_Real SCIPvarGetWorstBoundGlobal(
17953	   SCIP_VAR*             var                 /**< problem variable */
17954	   )
17955	{
17956	   assert(var != NULL);
17957	
17958	   if( var->obj >= 0.0 )
17959	      return var->glbdom.ub;
17960	   else
17961	      return var->glbdom.lb;
17962	}
17963	
17964	/** gets current lower bound of variable */
17965	SCIP_Real SCIPvarGetLbLocal(
17966	   SCIP_VAR*             var                 /**< problem variable */
17967	   )
17968	{
17969	   assert(var != NULL);
17970	
17971	   return var->locdom.lb;
17972	}
17973	
17974	/** gets current upper bound of variable */
17975	SCIP_Real SCIPvarGetUbLocal(
17976	   SCIP_VAR*             var                 /**< problem variable */
17977	   )
17978	{
17979	   assert(var != NULL);
17980	
17981	   return var->locdom.ub;
17982	}
17983	
17984	/** gets the current hole list of an active variable */
17985	SCIP_HOLELIST* SCIPvarGetHolelistLocal(
17986	   SCIP_VAR*             var                 /**< problem variable */
17987	   )
17988	{
17989	   assert(var != NULL);
17990	
17991	   return var->locdom.holelist;
17992	}
17993	
17994	/** gets best local bound of variable with respect to the objective function */
17995	SCIP_Real SCIPvarGetBestBoundLocal(
17996	   SCIP_VAR*             var                 /**< problem variable */
17997	   )
17998	{
17999	   assert(var != NULL);
18000	
18001	   if( var->obj >= 0.0 )
18002	      return var->locdom.lb;
18003	   else
18004	      return var->locdom.ub;
18005	}
18006	
18007	/** gets worst local bound of variable with respect to the objective function */
18008	SCIP_Real SCIPvarGetWorstBoundLocal(
18009	   SCIP_VAR*             var                 /**< problem variable */
18010	   )
18011	{
18012	   assert(var != NULL);
18013	
18014	   if( var->obj >= 0.0 )
18015	      return var->locdom.ub;
18016	   else
18017	      return var->locdom.lb;
18018	}
18019	
18020	/** gets type (lower or upper) of best bound of variable with respect to the objective function */
18021	SCIP_BOUNDTYPE SCIPvarGetBestBoundType(
18022	   SCIP_VAR*             var                 /**< problem variable */
18023	   )
18024	{
18025	   assert(var != NULL);
18026	
18027	   if( var->obj >= 0.0 )
18028	      return SCIP_BOUNDTYPE_LOWER;
18029	   else
18030	      return SCIP_BOUNDTYPE_UPPER;
18031	}
18032	
18033	/** gets type (lower or upper) of worst bound of variable with respect to the objective function */
18034	SCIP_BOUNDTYPE SCIPvarGetWorstBoundType(
18035	   SCIP_VAR*             var                 /**< problem variable */
18036	   )
18037	{
18038	   assert(var != NULL);
18039	
18040	   if( var->obj >= 0.0 )
18041	      return SCIP_BOUNDTYPE_UPPER;
18042	   else
18043	      return SCIP_BOUNDTYPE_LOWER;
18044	}
18045	
18046	/** gets lazy lower bound of variable, returns -infinity if the variable has no lazy lower bound */
18047	SCIP_Real SCIPvarGetLbLazy(
18048	   SCIP_VAR*             var                 /**< problem variable */
18049	   )
18050	{
18051	   assert(var != NULL);
18052	
18053	   return var->lazylb;
18054	}
18055	
18056	/** gets lazy upper bound of variable, returns infinity if the variable has no lazy upper bound */
18057	SCIP_Real SCIPvarGetUbLazy(
18058	   SCIP_VAR*             var                 /**< problem variable */
18059	   )
18060	{
18061	   assert(var != NULL);
18062	
18063	   return var->lazyub;
18064	}
18065	
18066	/** gets the branch factor of the variable; this value can be used in the branching methods to scale the score
18067	 *  values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
18068	 */
18069	SCIP_Real SCIPvarGetBranchFactor(
18070	   SCIP_VAR*             var                 /**< problem variable */
18071	   )
18072	{
18073	   assert(var != NULL);
18074	
18075	   return var->branchfactor;
18076	}
18077	
18078	/** gets the branch priority of the variable; variables with higher priority should always be preferred to variables
18079	 *  with lower priority
18080	 */
18081	int SCIPvarGetBranchPriority(
18082	   SCIP_VAR*             var                 /**< problem variable */
18083	   )
18084	{
18085	   assert(var != NULL);
18086	
18087	   return var->branchpriority;
18088	}
18089	
18090	/** gets the preferred branch direction of the variable (downwards, upwards, or auto) */
18091	SCIP_BRANCHDIR SCIPvarGetBranchDirection(
18092	   SCIP_VAR*             var                 /**< problem variable */
18093	   )
18094	{
18095	   assert(var != NULL);
18096	
18097	   return (SCIP_BRANCHDIR)var->branchdirection;
18098	}
18099	
18100	/** gets number of variable lower bounds x >= b_i*z_i + d_i of given variable x */
18101	int SCIPvarGetNVlbs(
18102	   SCIP_VAR*             var                 /**< problem variable */
18103	   )
18104	{
18105	   assert(var != NULL);
18106	
18107	   return SCIPvboundsGetNVbds(var->vlbs);
18108	}
18109	
18110	/** gets array with bounding variables z_i in variable lower bounds x >= b_i*z_i + d_i of given variable x;
18111	 *  the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
18112	 */
18113	SCIP_VAR** SCIPvarGetVlbVars(
18114	   SCIP_VAR*             var                 /**< problem variable */
18115	   )
18116	{
18117	   assert(var != NULL);
18118	
18119	   return SCIPvboundsGetVars(var->vlbs);
18120	}
18121	
18122	/** gets array with bounding coefficients b_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
18123	SCIP_Real* SCIPvarGetVlbCoefs(
18124	   SCIP_VAR*             var                 /**< problem variable */
18125	   )
18126	{
18127	   assert(var != NULL);
18128	
18129	   return SCIPvboundsGetCoefs(var->vlbs);
18130	}
18131	
18132	/** gets array with bounding constants d_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
18133	SCIP_Real* SCIPvarGetVlbConstants(
18134	   SCIP_VAR*             var                 /**< problem variable */
18135	   )
18136	{
18137	   assert(var != NULL);
18138	
18139	   return SCIPvboundsGetConstants(var->vlbs);
18140	}
18141	
18142	/** gets number of variable upper bounds x <= b_i*z_i + d_i of given variable x */
18143	int SCIPvarGetNVubs(
18144	   SCIP_VAR*             var                 /**< problem variable */
18145	   )
18146	{
18147	   assert(var != NULL);
18148	
18149	   return SCIPvboundsGetNVbds(var->vubs);
18150	}
18151	
18152	/** gets array with bounding variables z_i in variable upper bounds x <= b_i*z_i + d_i of given variable x;
18153	 *  the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
18154	 */
18155	SCIP_VAR** SCIPvarGetVubVars(
18156	   SCIP_VAR*             var                 /**< problem variable */
18157	   )
18158	{
18159	   assert(var != NULL);
18160	
18161	   return SCIPvboundsGetVars(var->vubs);
18162	}
18163	
18164	/** gets array with bounding coefficients b_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
18165	SCIP_Real* SCIPvarGetVubCoefs(
18166	   SCIP_VAR*             var                 /**< problem variable */
18167	   )
18168	{
18169	   assert(var != NULL);
18170	
18171	   return SCIPvboundsGetCoefs(var->vubs);
18172	}
18173	
18174	/** gets array with bounding constants d_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
18175	SCIP_Real* SCIPvarGetVubConstants(
18176	   SCIP_VAR*             var                 /**< problem variable */
18177	   )
18178	{
18179	   assert(var != NULL);
18180	
18181	   return SCIPvboundsGetConstants(var->vubs);
18182	}
18183	
18184	/** gets number of implications  y <= b or y >= b for x == 0 or x == 1 of given active problem variable x, 
18185	 *  there are no implications for nonbinary variable x
18186	 */
18187	int SCIPvarGetNImpls(
18188	   SCIP_VAR*             var,                /**< active problem variable */
18189	   SCIP_Bool             varfixing           /**< FALSE for implications for x == 0, TRUE for x == 1 */
18190	   )
18191	{
18192	   assert(var != NULL);
18193	   assert(SCIPvarIsActive(var));
18194	
18195	   return SCIPimplicsGetNImpls(var->implics, varfixing);
18196	}
18197	
18198	/** gets array with implication variables y of implications  y <= b or y >= b for x == 0 or x == 1 of given active
18199	 *  problem variable x, there are no implications for nonbinary variable x;
18200	 *  the implications are sorted such that implications with binary implied variables precede the ones with non-binary
18201	 *  implied variables, and as a second criteria, the implied variables are sorted by increasing variable index
18202	 *  (see SCIPvarGetIndex())
18203	 */
18204	SCIP_VAR** SCIPvarGetImplVars(
18205	   SCIP_VAR*             var,                /**< active problem variable */
18206	   SCIP_Bool             varfixing           /**< FALSE for implications for x == 0, TRUE for x == 1 */
18207	   )
18208	{
18209	   assert(var != NULL);
18210	   assert(SCIPvarIsActive(var));
18211	
18212	   return SCIPimplicsGetVars(var->implics, varfixing);
18213	}
18214	
18215	/** gets array with implication types of implications  y <= b or y >= b for x == 0 or x == 1 of given active problem
18216	 *  variable x (SCIP_BOUNDTYPE_UPPER if y <= b, SCIP_BOUNDTYPE_LOWER if y >= b), 
18217	 *  there are no implications for nonbinary variable x
18218	 */
18219	SCIP_BOUNDTYPE* SCIPvarGetImplTypes(
18220	   SCIP_VAR*             var,                /**< active problem variable */
18221	   SCIP_Bool             varfixing           /**< FALSE for implications for x == 0, TRUE for x == 1 */
18222	   )
18223	{
18224	   assert(var != NULL);
18225	   assert(SCIPvarIsActive(var));
18226	
18227	   return SCIPimplicsGetTypes(var->implics, varfixing);
18228	}
18229	
18230	/** gets array with implication bounds b of implications  y <= b or y >= b for x == 0 or x == 1 of given active problem
18231	 *  variable x, there are no implications for nonbinary variable x
18232	 */
18233	SCIP_Real* SCIPvarGetImplBounds(
18234	   SCIP_VAR*             var,                /**< active problem variable */
18235	   SCIP_Bool             varfixing           /**< FALSE for implications for x == 0, TRUE for x == 1 */
18236	   )
18237	{
18238	   assert(var != NULL);
18239	   assert(SCIPvarIsActive(var));
18240	
18241	   return SCIPimplicsGetBounds(var->implics, varfixing);
18242	}
18243	
18244	/** Gets array with unique ids of implications  y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
18245	 *  there are no implications for nonbinary variable x.
18246	 *  If an implication is a shortcut, i.e., it was added as part of the transitive closure of another implication,
18247	 *  its id is negative, otherwise it is nonnegative.
18248	 */
18249	int* SCIPvarGetImplIds(
18250	   SCIP_VAR*             var,                /**< active problem variable */
18251	   SCIP_Bool             varfixing           /**< FALSE for implications for x == 0, TRUE for x == 1 */
18252	   )
18253	{
18254	   assert(var != NULL);
18255	   assert(SCIPvarIsActive(var));
18256	
18257	   return SCIPimplicsGetIds(var->implics, varfixing);
18258	}
18259	
18260	/** gets number of cliques, the active variable is contained in */
18261	int SCIPvarGetNCliques(
18262	   SCIP_VAR*             var,                /**< active problem variable */
18263	   SCIP_Bool             varfixing           /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
18264	   )
18265	{
18266	   assert(var != NULL);
18267	
18268	   return SCIPcliquelistGetNCliques(var->cliquelist, varfixing);
18269	}
18270	
18271	/** gets array of cliques, the active variable is contained in */
18272	SCIP_CLIQUE** SCIPvarGetCliques(
18273	   SCIP_VAR*             var,                /**< active problem variable */
18274	   SCIP_Bool             varfixing           /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
18275	   )
18276	{
18277	   assert(var != NULL);
18278	
18279	   return SCIPcliquelistGetCliques(var->cliquelist, varfixing);
18280	}
18281	
18282	/** gets primal LP solution value of variable */
18283	SCIP_Real SCIPvarGetLPSol(
18284	   SCIP_VAR*             var                 /**< problem variable */
18285	   )
18286	{
18287	   assert(var != NULL);
18288	
18289	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN )
18290	      return SCIPcolGetPrimsol(var->data.col);
18291	   else
18292	      return SCIPvarGetLPSol_rec(var);
18293	}
18294	
18295	/** gets primal NLP solution value of variable */
18296	SCIP_Real SCIPvarGetNLPSol(
18297	   SCIP_VAR*             var                 /**< problem variable */
18298	   )
18299	{
18300	   assert(var != NULL);
18301	
18302	   if( (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE) )
18303	      return var->nlpsol;
18304	   else
18305	      return SCIPvarGetNLPSol_rec(var);
18306	}
18307	
18308	/** return lower bound change info at requested position */
18309	SCIP_BDCHGINFO* SCIPvarGetBdchgInfoLb(
18310	   SCIP_VAR*             var,                /**< problem variable */
18311	   int                   pos                 /**< requested position */
18312	   )
18313	{
18314	   assert(pos >= 0);
18315	   assert(pos < var->nlbchginfos);
18316	
18317	   return &var->lbchginfos[pos];
18318	} 
18319	
18320	/** gets the number of lower bound change info array */
18321	int SCIPvarGetNBdchgInfosLb(
18322	   SCIP_VAR*             var                 /**< problem variable */
18323	   )
18324	{
18325	   return var->nlbchginfos;
18326	} 
18327	
18328	/** return upper bound change info at requested position */
18329	SCIP_BDCHGINFO* SCIPvarGetBdchgInfoUb(
18330	   SCIP_VAR*             var,                /**< problem variable */
18331	   int                   pos                 /**< requested position */
18332	   )
18333	{
18334	   assert(pos >= 0);
18335	   assert(pos < var->nubchginfos);
18336	
18337	   return &var->ubchginfos[pos];
18338	} 
18339	
18340	/** gets the number upper bound change info array */
18341	int SCIPvarGetNBdchgInfosUb(
18342	   SCIP_VAR*             var                 /**< problem variable */
18343	   )
18344	{
18345	   assert(var != NULL);
18346	
18347	   return var->nubchginfos;
18348	} 
18349	
18350	/** returns the value based history for the variable */
18351	SCIP_VALUEHISTORY* SCIPvarGetValuehistory(
18352	   SCIP_VAR*             var                 /**< problem variable */
18353	   )
18354	{
18355	   assert(var != NULL);
18356	
18357	   return var->valuehistory;
18358	}
18359	
18360	/** gets pseudo solution value of variable */
18361	SCIP_Real SCIPvarGetPseudoSol(
18362	   SCIP_VAR*             var                 /**< problem variable */
18363	   )
18364	{
18365	   assert(var != NULL);
18366	
18367	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN )
18368	      return SCIPvarGetBestBoundLocal(var);
18369	   else
18370	      return SCIPvarGetPseudoSol_rec(var);
18371	}
18372	
18373	/** returns the variable's VSIDS score */
18374	SCIP_Real SCIPvarGetVSIDS(
18375	   SCIP_VAR*             var,                /**< problem variable */
18376	   SCIP_STAT*            stat,               /**< problem statistics */
18377	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
18378	   )
18379	{
18380	   assert(var != NULL);
18381	
18382	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN )
18383	      return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
18384	   else
18385	      return SCIPvarGetVSIDS_rec(var, stat, dir);
18386	}
18387	
18388	/** includes event handler with given data in variable's event filter */
18389	SCIP_RETCODE SCIPvarCatchEvent(
18390	   SCIP_VAR*             var,                /**< problem variable */
18391	   BMS_BLKMEM*           blkmem,             /**< block memory */
18392	   SCIP_SET*             set,                /**< global SCIP settings */
18393	   SCIP_EVENTTYPE        eventtype,          /**< event type to catch */
18394	   SCIP_EVENTHDLR*       eventhdlr,          /**< event handler to call for the event processing */
18395	   SCIP_EVENTDATA*       eventdata,          /**< event data to pass to the event handler for the event processing */
18396	   int*                  filterpos           /**< pointer to store position of event filter entry, or NULL */
18397	   )
18398	{
18399	   assert(var != NULL);
18400	   assert(set != NULL);
18401	   assert(var->scip == set->scip);
18402	   assert(var->eventfilter != NULL);
18403	   assert((eventtype & ~SCIP_EVENTTYPE_VARCHANGED) == 0);
18404	   assert((eventtype & SCIP_EVENTTYPE_VARCHANGED) != 0);
18405	   assert(SCIPvarIsTransformed(var));
18406	
18407	   SCIPsetDebugMsg(set, "catch event of type 0x%" SCIP_EVENTTYPE_FORMAT " of variable <%s> with handler %p and data %p\n",
18408	      eventtype, var->name, (void*)eventhdlr, (void*)eventdata);
18409	
18410	   SCIP_CALL( SCIPeventfilterAdd(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
18411	
18412	   return SCIP_OKAY;
18413	}
18414	
18415	/** deletes event handler with given data from variable's event filter */
18416	SCIP_RETCODE SCIPvarDropEvent(
18417	   SCIP_VAR*             var,                /**< problem variable */
18418	   BMS_BLKMEM*           blkmem,             /**< block memory */
18419	   SCIP_SET*             set,                /**< global SCIP settings */
18420	   SCIP_EVENTTYPE        eventtype,          /**< event type mask of dropped event */
18421	   SCIP_EVENTHDLR*       eventhdlr,          /**< event handler to call for the event processing */
18422	   SCIP_EVENTDATA*       eventdata,          /**< event data to pass to the event handler for the event processing */
18423	   int                   filterpos           /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
18424	   )
18425	{
18426	   assert(var != NULL);
18427	   assert(set != NULL);
18428	   assert(var->scip == set->scip);
18429	   assert(var->eventfilter != NULL);
18430	   assert(SCIPvarIsTransformed(var));
18431	
18432	   SCIPsetDebugMsg(set, "drop event of variable <%s> with handler %p and data %p\n", var->name, (void*)eventhdlr,
18433	         (void*)eventdata);
18434	
18435	   SCIP_CALL( SCIPeventfilterDel(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
18436	
18437	   return SCIP_OKAY;
18438	}
18439	
18440	/** returns the position of the bound change index */
18441	int SCIPbdchgidxGetPos(
18442	   SCIP_BDCHGIDX*        bdchgidx            /**< bound change index */
18443	   )
18444	{
18445	   assert(bdchgidx != NULL);
18446	
18447	   return bdchgidx->pos;
18448	}
18449	
18450	/** returns whether first bound change index belongs to an earlier applied bound change than second one */
18451	SCIP_Bool SCIPbdchgidxIsEarlierNonNull(
18452	   SCIP_BDCHGIDX*        bdchgidx1,          /**< first bound change index */
18453	   SCIP_BDCHGIDX*        bdchgidx2           /**< second bound change index */
18454	   )
18455	{
18456	   assert(bdchgidx1 != NULL);
18457	   assert(bdchgidx1->depth >= -2);
18458	   assert(bdchgidx1->pos >= 0);
18459	   assert(bdchgidx2 != NULL);
18460	   assert(bdchgidx2->depth >= -2);
18461	   assert(bdchgidx2->pos >= 0);
18462	
18463	   return (bdchgidx1->depth < bdchgidx2->depth)
18464	      || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
18465	}
18466	
18467	/** returns whether first bound change index belongs to an earlier applied bound change than second one;
18468	 *  if a bound change index is NULL, the bound change index represents the current time, i.e. the time after the
18469	 *  last bound change was applied to the current node
18470	 */
18471	SCIP_Bool SCIPbdchgidxIsEarlier(
18472	   SCIP_BDCHGIDX*        bdchgidx1,          /**< first bound change index, or NULL */
18473	   SCIP_BDCHGIDX*        bdchgidx2           /**< second bound change index, or NULL */
18474	   )
18475	{
18476	   assert(bdchgidx1 == NULL || bdchgidx1->depth >= -2);
18477	   assert(bdchgidx1 == NULL || bdchgidx1->pos >= 0);
18478	   assert(bdchgidx2 == NULL || bdchgidx2->depth >= -2);
18479	   assert(bdchgidx2 == NULL || bdchgidx2->pos >= 0);
18480	
18481	   if( bdchgidx1 == NULL )
18482	      return FALSE;
18483	   else if( bdchgidx2 == NULL )
18484	      return TRUE;
18485	   else
18486	      return (bdchgidx1->depth < bdchgidx2->depth)
18487	         || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
18488	}
18489	
18490	/** returns old bound that was overwritten for given bound change information */
18491	SCIP_Real SCIPbdchginfoGetOldbound(
18492	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18493	   )
18494	{
18495	   assert(bdchginfo != NULL);
18496	
18497	   return bdchginfo->oldbound;
18498	}
18499	
18500	/** returns new bound installed for given bound change information */
18501	SCIP_Real SCIPbdchginfoGetNewbound(
18502	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18503	   )
18504	{
18505	   assert(bdchginfo != NULL);
18506	
18507	   return bdchginfo->newbound;
18508	}
18509	
18510	/** returns variable that belongs to the given bound change information */
18511	SCIP_VAR* SCIPbdchginfoGetVar(
18512	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18513	   )
18514	{
18515	   assert(bdchginfo != NULL);
18516	
18517	   return bdchginfo->var;
18518	}
18519	
18520	/** returns whether the bound change information belongs to a branching decision or a deduction */
18521	SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(
18522	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18523	   )
18524	{
18525	   assert(bdchginfo != NULL);
18526	
18527	   return (SCIP_BOUNDCHGTYPE)(bdchginfo->boundchgtype);
18528	}
18529	
18530	/** returns whether the bound change information belongs to a lower or upper bound change */
18531	SCIP_BOUNDTYPE SCIPbdchginfoGetBoundtype(
18532	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18533	   )
18534	{
18535	   assert(bdchginfo != NULL);
18536	
18537	   return (SCIP_BOUNDTYPE)(bdchginfo->boundtype);
18538	}
18539	
18540	/** returns depth level of given bound change information */
18541	int SCIPbdchginfoGetDepth(
18542	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18543	   )
18544	{
18545	   assert(bdchginfo != NULL);
18546	
18547	   return bdchginfo->bdchgidx.depth;
18548	}
18549	
18550	/** returns bound change position in its depth level of given bound change information */
18551	int SCIPbdchginfoGetPos(
18552	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18553	   )
18554	{
18555	   assert(bdchginfo != NULL);
18556	
18557	   return bdchginfo->bdchgidx.pos;
18558	}
18559	
18560	/** returns bound change index of given bound change information */
18561	SCIP_BDCHGIDX* SCIPbdchginfoGetIdx(
18562	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18563	   )
18564	{
18565	   assert(bdchginfo != NULL);
18566	
18567	   return &bdchginfo->bdchgidx;
18568	}
18569	
18570	/** returns inference variable of given bound change information */
18571	SCIP_VAR* SCIPbdchginfoGetInferVar(
18572	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18573	   )
18574	{
18575	   assert(bdchginfo != NULL);
18576	   assert((SCIP_BOUNDCHGTYPE)bdchginfo->boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER
18577	      || (SCIP_BOUNDCHGTYPE)bdchginfo->boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER);
18578	
18579	   return bdchginfo->inferencedata.var;
18580	}
18581	
18582	/** returns inference constraint of given bound change information */
18583	SCIP_CONS* SCIPbdchginfoGetInferCons(
18584	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18585	   )
18586	{
18587	   assert(bdchginfo != NULL);
18588	   assert((SCIP_BOUNDCHGTYPE)bdchginfo->boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER);
18589	   assert(bdchginfo->inferencedata.reason.cons != NULL);
18590	
18591	   return bdchginfo->inferencedata.reason.cons;
18592	}
18593	
18594	/** returns inference propagator of given bound change information, or NULL if no propagator was responsible */
18595	SCIP_PROP* SCIPbdchginfoGetInferProp(
18596	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18597	   )
18598	{
18599	   assert(bdchginfo != NULL);
18600	   assert((SCIP_BOUNDCHGTYPE)bdchginfo->boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER);
18601	
18602	   return bdchginfo->inferencedata.reason.prop;
18603	}
18604	
18605	/** returns inference user information of given bound change information */
18606	int SCIPbdchginfoGetInferInfo(
18607	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18608	   )
18609	{
18610	   assert(bdchginfo != NULL);
18611	   assert((SCIP_BOUNDCHGTYPE)bdchginfo->boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER
18612	      || (SCIP_BOUNDCHGTYPE)bdchginfo->boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER);
18613	
18614	   return bdchginfo->inferencedata.info;
18615	}
18616	
18617	/** returns inference bound of inference variable of given bound change information */
18618	SCIP_BOUNDTYPE SCIPbdchginfoGetInferBoundtype(
18619	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18620	   )
18621	{
18622	   assert(bdchginfo != NULL);
18623	   assert((SCIP_BOUNDCHGTYPE)bdchginfo->boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER
18624	      || (SCIP_BOUNDCHGTYPE)bdchginfo->boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER);
18625	
18626	   return (SCIP_BOUNDTYPE)(bdchginfo->inferboundtype);
18627	}
18628	
18629	/** returns the relaxed bound change type */
18630	SCIP_Real SCIPbdchginfoGetRelaxedBound(
18631	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change to add to the conflict set */
18632	   )
18633	{
18634	   return ((SCIP_BOUNDTYPE)(bdchginfo->boundtype) == SCIP_BOUNDTYPE_LOWER ? bdchginfo->var->conflictrelaxedlb : bdchginfo->var->conflictrelaxedub);
18635	}
18636	
18637	
18638	/** returns whether the bound change information belongs to a redundant bound change */
18639	SCIP_Bool SCIPbdchginfoIsRedundant(
18640	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18641	   )
18642	{
18643	   assert(bdchginfo != NULL);
18644	   assert(bdchginfo->redundant == (bdchginfo->oldbound == bdchginfo->newbound)); /*lint !e777*/
18645	
18646	   return bdchginfo->redundant;
18647	}
18648	
18649	/** returns whether the bound change has an inference reason (constraint or propagator), that can be resolved */
18650	SCIP_Bool SCIPbdchginfoHasInferenceReason(
18651	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18652	   )
18653	{
18654	   assert(bdchginfo != NULL);
18655	
18656	   return ((SCIP_BOUNDCHGTYPE)bdchginfo->boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER)
18657	      || ((SCIP_BOUNDCHGTYPE)bdchginfo->boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER
18658	         && bdchginfo->inferencedata.reason.prop != NULL);
18659	}
18660	
18661	/** for two bound change informations belonging to the same variable and bound, returns whether the first bound change
18662	 *  has a tighter new bound as the second bound change
18663	 */
18664	SCIP_Bool SCIPbdchginfoIsTighter(
18665	   SCIP_BDCHGINFO*       bdchginfo1,         /**< first bound change information */
18666	   SCIP_BDCHGINFO*       bdchginfo2          /**< second bound change information */
18667	   )
18668	{
18669	   assert(bdchginfo1 != NULL);
18670	   assert(bdchginfo2 != NULL);
18671	   assert(bdchginfo1->var == bdchginfo2->var);
18672	   assert(bdchginfo1->boundtype == bdchginfo2->boundtype);
18673	
18674	   return (SCIPbdchginfoGetBoundtype(bdchginfo1) == SCIP_BOUNDTYPE_LOWER
18675	      ? bdchginfo1->newbound > bdchginfo2->newbound
18676	      : bdchginfo1->newbound < bdchginfo2->newbound);
18677	}
18678