1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This file is part of the program and library             */
4    	/*         SCIP --- Solving Constraint Integer Programs                      */
5    	/*                                                                           */
6    	/*  Copyright (c) 2002-2023 Zuse Institute Berlin (ZIB)                      */
7    	/*                                                                           */
8    	/*  Licensed under the Apache License, Version 2.0 (the "License");          */
9    	/*  you may not use this file except in compliance with the License.         */
10   	/*  You may obtain a copy of the License at                                  */
11   	/*                                                                           */
12   	/*      http://www.apache.org/licenses/LICENSE-2.0                           */
13   	/*                                                                           */
14   	/*  Unless required by applicable law or agreed to in writing, software      */
15   	/*  distributed under the License is distributed on an "AS IS" BASIS,        */
16   	/*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17   	/*  See the License for the specific language governing permissions and      */
18   	/*  limitations under the License.                                           */
19   	/*                                                                           */
20   	/*  You should have received a copy of the Apache-2.0 license                */
21   	/*  along with SCIP; see the file LICENSE. If not visit scipopt.org.         */
22   	/*                                                                           */
23   	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24   	
25   	/**@file   var.c
26   	 * @ingroup OTHER_CFILES
27   	 * @brief  methods for problem variables
28   	 * @author Tobias Achterberg
29   	 * @author Timo Berthold
30   	 * @author Gerald Gamrath
31   	 * @author Stefan Heinz
32   	 * @author Marc Pfetsch
33   	 * @author Michael Winkler
34   	 * @author Kati Wolter
35   	 * @author Stefan Vigerske
36   	 *
37   	 * @todo Possibly implement the access of bounds of multi-aggregated variables by accessing the
38   	 * corresponding linear constraint if it exists. This seems to require some work, since the linear
39   	 * constraint has to be stored. Moreover, it has even to be created in case the original constraint
40   	 * was deleted after multi-aggregation, but the bounds of the multi-aggregated variable should be
41   	 * changed. This has to be done with care in order to not loose the performance gains of
42   	 * multi-aggregation.
43   	 */
44   	
45   	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
46   	
47   	#include "scip/cons.h"
48   	#include "scip/event.h"
49   	#include "scip/history.h"
50   	#include "scip/implics.h"
51   	#include "scip/lp.h"
52   	#include "scip/primal.h"
53   	#include "scip/prob.h"
54   	#include "scip/pub_cons.h"
55   	#include "scip/pub_history.h"
56   	#include "scip/pub_implics.h"
57   	#include "scip/pub_lp.h"
58   	#include "scip/pub_message.h"
59   	#include "scip/pub_misc.h"
60   	#include "scip/pub_misc_sort.h"
61   	#include "scip/pub_prop.h"
62   	#include "scip/pub_var.h"
63   	#include "scip/relax.h"
64   	#include "scip/set.h"
65   	#include "scip/sol.h"
66   	#include "scip/stat.h"
67   	#include "scip/struct_event.h"
68   	#include "scip/struct_lp.h"
69   	#include "scip/struct_prob.h"
70   	#include "scip/struct_set.h"
71   	#include "scip/struct_stat.h"
72   	#include "scip/struct_var.h"
73   	#include "scip/tree.h"
74   	#include "scip/var.h"
75   	#include <string.h>
76   	
77   	#define MAXIMPLSCLOSURE 100  /**< maximal number of descendants of implied variable for building closure
78   	                              *   in implication graph */
79   	#define MAXABSVBCOEF    1e+5 /**< maximal absolute coefficient in variable bounds added due to implications */
80   	
81   	
82   	/*
83   	 * Debugging variable release and capture
84   	 *
85   	 * Define DEBUGUSES_VARNAME to the name of the variable for which to print
86   	 * a backtrace when it is captured and released.
87   	 * Optionally define DEBUGUSES_PROBNAME to the name of a SCIP problem to consider.
88   	 * Have DEBUGUSES_NOADDR2LINE defined if you do not have addr2line installed on your system.
89   	 */
90   	/* #define DEBUGUSES_VARNAME "t_t_b7" */
91   	/* #define DEBUGUSES_PROBNAME "t_st_e35_rens" */
92   	/* #define DEBUGUSES_NOADDR2LINE */
93   	
94   	#ifdef DEBUGUSES_VARNAME
95   	#include <execinfo.h>
96   	#include <stdio.h>
97   	#include <stdlib.h>
98   	#include "scip/struct_scip.h"
99   	
100  	/** obtains a backtrace and prints it to stdout. */
101  	static
102  	void print_backtrace(void)
103  	{
104  	   void* array[10];
105  	   char** strings;
106  	   int size;
107  	   int i;
108  	
109  	   size = backtrace(array, 10);
110  	   strings = backtrace_symbols(array, size);
111  	   if( strings == NULL )
112  	      return;
113  	
114  	   /* skip first entry, which is the print_backtrace function */
115  	   for( i = 1; i < size; ++i )
116  	   {
117  	      /* if string is something like
118  	       *  /path/to/scip/bin/../lib/shared/libscip-7.0.1.3.linux.x86_64.gnu.dbg.so(+0x2675dd3)
119  	       * (that is, no function name because it is a inlined function), then call
120  	       * addr2line -e <libname> <addr> to get func and code line
121  	       * dladdr() may be an alternative
122  	       */
123  	      char* openpar;
124  	      char* closepar = NULL;
125  	#ifndef DEBUGUSES_NOADDR2LINE
126  	      openpar = strchr(strings[i], '(');
127  	      if( openpar != NULL && openpar[1] == '+' )
128  	         closepar = strchr(openpar+2, ')');
129  	#endif
130  	      if( closepar != NULL )
131  	      {
132  	         char cmd[SCIP_MAXSTRLEN];
133  	         (void) SCIPsnprintf(cmd, SCIP_MAXSTRLEN, "addr2line -f -p -e \"%.*s\" %.*s", openpar - strings[i], strings[i], closepar-openpar-1, openpar+1);
134  	         printf("  ");
135  	         fflush(stdout);
136  	         system(cmd);
137  	      }
138  	      else
139  	         printf("  %s\n", strings[i]);
140  	    }
141  	
142  	  free(strings);
143  	}
144  	#endif
145  	
146  	/*
147  	 * hole, holelist, and domain methods
148  	 */
149  	
150  	/** creates a new holelist element */
151  	static
152  	SCIP_RETCODE holelistCreate(
153  	   SCIP_HOLELIST**       holelist,           /**< pointer to holelist to create */
154  	   BMS_BLKMEM*           blkmem,             /**< block memory for target holelist */
155  	   SCIP_SET*             set,                /**< global SCIP settings */
156  	   SCIP_Real             left,               /**< left bound of open interval in new hole */
157  	   SCIP_Real             right               /**< right bound of open interval in new hole */
158  	   )
159  	{
160  	   assert(holelist != NULL);
161  	   assert(blkmem != NULL);
162  	   assert(SCIPsetIsLT(set, left, right));
163  	
164  	   SCIPsetDebugMsg(set, "create hole list element (%.15g,%.15g) in blkmem %p\n", left, right, (void*)blkmem);
165  	
166  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, holelist) );
167  	   (*holelist)->hole.left = left;
168  	   (*holelist)->hole.right = right;
169  	   (*holelist)->next = NULL;
170  	
171  	   return SCIP_OKAY;
172  	}
173  	
174  	/** frees all elements in the holelist */
175  	static
176  	void holelistFree(
177  	   SCIP_HOLELIST**       holelist,           /**< pointer to holelist to free */
178  	   BMS_BLKMEM*           blkmem              /**< block memory for target holelist */
179  	   )
180  	{
181  	   assert(holelist != NULL);
182  	   assert(blkmem != NULL);
183  	
184  	   while( *holelist != NULL )
185  	   {
186  	      SCIP_HOLELIST* next;
187  	
188  	      SCIPdebugMessage("free hole list element (%.15g,%.15g) in blkmem %p\n", 
189  	         (*holelist)->hole.left, (*holelist)->hole.right, (void*)blkmem);
190  	
191  	      next = (*holelist)->next;
192  	      BMSfreeBlockMemory(blkmem, holelist);
193  	      assert(*holelist == NULL);
194  	
195  	      *holelist = next;
196  	   }
197  	   assert(*holelist == NULL);
198  	}
199  	
200  	/** duplicates a list of holes */
201  	static
202  	SCIP_RETCODE holelistDuplicate(
203  	   SCIP_HOLELIST**       target,             /**< pointer to target holelist */
204  	   BMS_BLKMEM*           blkmem,             /**< block memory for target holelist */
205  	   SCIP_SET*             set,                /**< global SCIP settings */
206  	   SCIP_HOLELIST*        source              /**< holelist to duplicate */
207  	   )
208  	{
209  	   assert(target != NULL);
210  	
211  	   while( source != NULL )
212  	   {
213  	      assert(source->next == NULL || SCIPsetIsGE(set, source->next->hole.left, source->hole.right));
214  	      SCIP_CALL( holelistCreate(target, blkmem, set, source->hole.left, source->hole.right) );
215  	      source = source->next;
216  	      target = &(*target)->next;
217  	   }
218  	
219  	   return SCIP_OKAY;
220  	}
221  	
222  	/** adds a hole to the domain */
223  	static
224  	SCIP_RETCODE domAddHole(
225  	   SCIP_DOM*             dom,                /**< domain to add hole to */
226  	   BMS_BLKMEM*           blkmem,             /**< block memory */
227  	   SCIP_SET*             set,                /**< global SCIP settings */
228  	   SCIP_Real             left,               /**< left bound of open interval in new hole */
229  	   SCIP_Real             right,              /**< right bound of open interval in new hole */
230  	   SCIP_Bool*            added               /**< pointer to store whether the hole was added (variable didn't had that hole before), or NULL */
231  	   )
232  	{
233  	   SCIP_HOLELIST** insertpos;
234  	   SCIP_HOLELIST* next;
235  	
236  	   assert(dom != NULL);
237  	   assert(added != NULL);
238  	
239  	   /* search for the position of the new hole */
240  	   insertpos = &dom->holelist;
241  	   while( *insertpos != NULL && (*insertpos)->hole.left < left )
242  	      insertpos = &(*insertpos)->next;
243  	
244  	   /* check if new hole already exists in the hole list or is a sub hole of an existing one */
245  	   if( *insertpos != NULL && (*insertpos)->hole.left == left && (*insertpos)->hole.right >= right )  /*lint !e777 */
246  	   {
247  	      SCIPsetDebugMsg(set, "new hole (%.15g,%.15g) is redundant through known hole (%.15g,%.15g)\n",
248  	         left, right, (*insertpos)->hole.left, (*insertpos)->hole.right);
249  	      *added = FALSE;
250  	      return SCIP_OKAY;
251  	   }
252  	
253  	   /* add hole */
254  	   *added = TRUE;
255  	
256  	   next = *insertpos;
257  	   SCIP_CALL( holelistCreate(insertpos, blkmem, set, left, right) );
258  	   (*insertpos)->next = next;
259  	
260  	   return SCIP_OKAY;
261  	}
262  	
263  	/** merges overlapping holes into single holes, computes and moves lower and upper bound, respectively */
264  	/**@todo  the domMerge() method is currently called if a lower or an upper bound locally or globally changed; this could
265  	 *        be more efficient if performed with the knowledge if it was a lower or an upper bound which triggered this
266  	 *        merge */
267  	static
268  	void domMerge(
269  	   SCIP_DOM*             dom,                /**< domain to merge */
270  	   BMS_BLKMEM*           blkmem,             /**< block memory */
271  	   SCIP_SET*             set,                /**< global SCIP settings */
272  	   SCIP_Real*            newlb,              /**< pointer to store new lower bound */
273  	   SCIP_Real*            newub               /**< pointer to store new upper bound */
274  	   )
275  	{
276  	   SCIP_HOLELIST** holelistptr;
277  	   SCIP_HOLELIST** lastnextptr;
278  	   SCIP_Real* lastrightptr;
279  	
280  	   assert(dom != NULL);
281  	   assert(SCIPsetIsLE(set, dom->lb, dom->ub));
282  	
283  	#ifndef NDEBUG
284  	   {
285  	      /* check if the holelist is sorted w.r.t. to the left interval bounds */
286  	      SCIP_Real lastleft;
287  	
288  	      holelistptr = &dom->holelist;
289  	
290  	      lastleft = -SCIPsetInfinity(set);
291  	
292  	      while( *holelistptr != NULL )
293  	      {
294  	         if( (*holelistptr)->next != NULL )
295  	         {
296  	            assert( SCIPsetIsLE(set, lastleft, (*holelistptr)->hole.left) );
297  	            lastleft = (*holelistptr)->hole.left;
298  	         }
299  	
300  	         holelistptr = &(*holelistptr)->next;
301  	      }   
302  	   }
303  	#endif
304  	
305  	   SCIPsetDebugMsg(set, "merge hole list\n");
306  	
307  	   holelistptr = &dom->holelist;
308  	   lastrightptr = &dom->lb;  /* lower bound is the right bound of the hole (-infinity,lb) */
309  	   lastnextptr = holelistptr;
310  	
311  	   while( *holelistptr != NULL )
312  	   {
313  	      SCIPsetDebugMsg(set, "check hole (%.15g,%.15g) last right interval was <%.15g>\n", (*holelistptr)->hole.left, (*holelistptr)->hole.right, *lastrightptr);
314  	
315  	      /* check that the hole is not empty */
316  	      assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right));
317  	
318  	      if( SCIPsetIsGE(set, (*holelistptr)->hole.left, dom->ub) )
319  	      {
320  	         /* the remaining holes start behind the upper bound: remove them */
321  	         SCIPsetDebugMsg(set, "remove remaining hole since upper bound <%.15g> is less then the left hand side of the current hole\n", dom->ub);
322  	         holelistFree(holelistptr, blkmem);
323  	         assert(*holelistptr == NULL);
324  	
325  	         /* unlink this hole from the previous hole */
326  	         *lastnextptr = NULL;
327  	      }
328  	      else if( SCIPsetIsGT(set, (*holelistptr)->hole.right, dom->ub) )
329  	      {
330  	         /* the hole overlaps the upper bound: decrease upper bound, remove this hole and all remaining holes */
331  	         SCIPsetDebugMsg(set, "upper bound <%.15g> lays in current hole; store new upper bound and remove this and all remaining holes\n", dom->ub);
332  	
333  	         assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, dom->ub));
334  	
335  	         /* adjust upper bound */
336  	         dom->ub = (*holelistptr)->hole.left;
337  	
338  	         if(newub != NULL )
339  	            *newub = (*holelistptr)->hole.left;
340  	
341  	         /* remove remaining hole list */
342  	         holelistFree(holelistptr, blkmem);
343  	         assert(*holelistptr == NULL);
344  	
345  	         /* unlink this hole from the previous hole */
346  	         *lastnextptr = NULL;
347  	      }
348  	      else if( SCIPsetIsGT(set, *lastrightptr, (*holelistptr)->hole.left) )
349  	      {
350  	         /* the right bound of the last hole is greater than the left bound of this hole: increase the right bound of
351  	          * the last hole, delete this hole */
352  	         SCIP_HOLELIST* nextholelist;
353  	
354  	         if( SCIPsetIsEQ(set, *lastrightptr, dom->lb ) )
355  	         {
356  	            /* the reason for the overlap results from the lower bound hole (-infinity,lb); therefore, we can increase
357  	             * the lower bound */
358  	            SCIPsetDebugMsg(set, "lower bound <%.15g> lays in current hole; store new lower bound and remove hole\n", dom->lb);
359  	            *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
360  	
361  	            /* adjust lower bound */
362  	            dom->lb = *lastrightptr;
363  	
364  	            if(newlb != NULL )
365  	               *newlb = *lastrightptr;
366  	         }
367  	         else
368  	         {
369  	            SCIPsetDebugMsg(set, "current hole overlaps with the previous one (...,%.15g); merge to (...,%.15g)\n",
370  	               *lastrightptr, MAX(*lastrightptr, (*holelistptr)->hole.right) );
371  	            *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
372  	         }
373  	         nextholelist = (*holelistptr)->next;
374  	         (*holelistptr)->next = NULL;
375  	         holelistFree(holelistptr, blkmem);
376  	
377  	         /* connect the linked list after removing the hole */
378  	         *lastnextptr = nextholelist;
379  	
380  	         /* get next hole */
381  	         *holelistptr = nextholelist;
382  	      }
383  	      else
384  	      {
385  	         /* the holes do not overlap: update lastholelist and lastrightptr */
386  	         lastrightptr = &(*holelistptr)->hole.right;
387  	         lastnextptr = &(*holelistptr)->next;
388  	
389  	         /* get next hole */
390  	         holelistptr = &(*holelistptr)->next;
391  	      }
392  	   }
393  	
394  	#ifndef NDEBUG
395  	   {
396  	      /* check that holes are merged */
397  	      SCIP_Real lastright;
398  	
399  	      lastright = dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
400  	      holelistptr = &dom->holelist;
401  	
402  	      while( *holelistptr != NULL )
403  	      {
404  	         /* check the the last right interval is smaller or equal to the current left interval (none overlapping) */
405  	         assert( SCIPsetIsLE(set, lastright, (*holelistptr)->hole.left) );
406  	
407  	         /* check the hole property (check that the hole is not empty) */
408  	         assert( SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right) );
409  	         lastright = (*holelistptr)->hole.right;
410  	
411  	         /* get next hole */
412  	         holelistptr = &(*holelistptr)->next;
413  	      }   
414  	
415  	      /* check the the last right interval is smaller or equal to the upper bound (none overlapping) */     
416  	      assert( SCIPsetIsLE(set, lastright, dom->ub) );
417  	   }
418  	#endif
419  	}
420  	
421  	/*
422  	 * domain change methods
423  	 */
424  	
425  	/** ensures, that bound change info array for lower bound changes can store at least num entries */
426  	static
427  	SCIP_RETCODE varEnsureLbchginfosSize(
428  	   SCIP_VAR*             var,                /**< problem variable */
429  	   BMS_BLKMEM*           blkmem,             /**< block memory */
430  	   SCIP_SET*             set,                /**< global SCIP settings */
431  	   int                   num                 /**< minimum number of entries to store */
432  	   )
433  	{
434  	   assert(var != NULL);
435  	   assert(var->nlbchginfos <= var->lbchginfossize);
436  	   assert(SCIPvarIsTransformed(var));
437  	
438  	   if( num > var->lbchginfossize )
439  	   {
440  	      int newsize;
441  	
442  	      newsize = SCIPsetCalcMemGrowSize(set, num);
443  	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->lbchginfos, var->lbchginfossize, newsize) );
444  	      var->lbchginfossize = newsize;
445  	   }
446  	   assert(num <= var->lbchginfossize);
447  	
448  	   return SCIP_OKAY;
449  	}
450  	
451  	/** ensures, that bound change info array for upper bound changes can store at least num entries */
452  	static
453  	SCIP_RETCODE varEnsureUbchginfosSize(
454  	   SCIP_VAR*             var,                /**< problem variable */
455  	   BMS_BLKMEM*           blkmem,             /**< block memory */
456  	   SCIP_SET*             set,                /**< global SCIP settings */
457  	   int                   num                 /**< minimum number of entries to store */
458  	   )
459  	{
460  	   assert(var != NULL);
461  	   assert(var->nubchginfos <= var->ubchginfossize);
462  	   assert(SCIPvarIsTransformed(var));
463  	
464  	   if( num > var->ubchginfossize )
465  	   {
466  	      int newsize;
467  	
468  	      newsize = SCIPsetCalcMemGrowSize(set, num);
469  	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->ubchginfos, var->ubchginfossize, newsize) );
470  	      var->ubchginfossize = newsize;
471  	   }
472  	   assert(num <= var->ubchginfossize);
473  	
474  	   return SCIP_OKAY;
475  	}
476  	
477  	/** adds domain change info to the variable's lower bound change info array */
478  	static
479  	SCIP_RETCODE varAddLbchginfo(
480  	   SCIP_VAR*             var,                /**< problem variable */
481  	   BMS_BLKMEM*           blkmem,             /**< block memory */
482  	   SCIP_SET*             set,                /**< global SCIP settings */
483  	   SCIP_Real             oldbound,           /**< old value for bound */
484  	   SCIP_Real             newbound,           /**< new value for bound */
485  	   int                   depth,              /**< depth in the tree, where the bound change takes place */
486  	   int                   pos,                /**< position of the bound change in its bound change array */
487  	   SCIP_VAR*             infervar,           /**< variable that was changed (parent of var, or var itself) */
488  	   SCIP_CONS*            infercons,          /**< constraint that inferred this bound change, or NULL */
489  	   SCIP_PROP*            inferprop,          /**< propagator that deduced the bound change, or NULL */
490  	   int                   inferinfo,          /**< user information for inference to help resolving the conflict */
491  	   SCIP_BOUNDTYPE        inferboundtype,     /**< type of bound for inference var: lower or upper bound */
492  	   SCIP_BOUNDCHGTYPE     boundchgtype        /**< bound change type: branching decision or inferred bound change */
493  	   )
494  	{
495  	   assert(var != NULL);
496  	   assert(SCIPsetIsLT(set, oldbound, newbound));
497  	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, oldbound));
498  	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
499  	   assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 0.0));
500  	   assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 1.0));
501  	   assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
502  	   assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
503  	   assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
504  	
505  	   SCIPsetDebugMsg(set, "adding lower bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
506  	      SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
507  	      infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
508  	      oldbound, newbound);
509  	
510  	   SCIP_CALL( varEnsureLbchginfosSize(var, blkmem, set, var->nlbchginfos+1) );
511  	   var->lbchginfos[var->nlbchginfos].oldbound = oldbound;
512  	   var->lbchginfos[var->nlbchginfos].newbound = newbound;
513  	   var->lbchginfos[var->nlbchginfos].var = var;
514  	   var->lbchginfos[var->nlbchginfos].bdchgidx.depth = depth;
515  	   var->lbchginfos[var->nlbchginfos].bdchgidx.pos = pos;
516  	   var->lbchginfos[var->nlbchginfos].pos = var->nlbchginfos; /*lint !e732*/
517  	   var->lbchginfos[var->nlbchginfos].boundchgtype = boundchgtype; /*lint !e641*/
518  	   var->lbchginfos[var->nlbchginfos].boundtype = SCIP_BOUNDTYPE_LOWER; /*lint !e641*/
519  	   var->lbchginfos[var->nlbchginfos].redundant = FALSE;
520  	   var->lbchginfos[var->nlbchginfos].inferboundtype = inferboundtype; /*lint !e641*/
521  	   var->lbchginfos[var->nlbchginfos].inferencedata.var = infervar;
522  	   var->lbchginfos[var->nlbchginfos].inferencedata.info = inferinfo;
523  	
524  	   /**@note The "pos" data member of the bound change info has a size of 27 bits */
525  	   assert(var->nlbchginfos < 1 << 27);
526  	
527  	   switch( boundchgtype )
528  	   {
529  	   case SCIP_BOUNDCHGTYPE_BRANCHING:
530  	      break;
531  	   case SCIP_BOUNDCHGTYPE_CONSINFER:
532  	      assert(infercons != NULL);
533  	      var->lbchginfos[var->nlbchginfos].inferencedata.reason.cons = infercons;
534  	      break;
535  	   case SCIP_BOUNDCHGTYPE_PROPINFER:
536  	      var->lbchginfos[var->nlbchginfos].inferencedata.reason.prop = inferprop;
537  	      break;
538  	   default:
539  	      SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
540  	      return SCIP_INVALIDDATA;
541  	   }
542  	
543  	   var->nlbchginfos++;
544  	
545  	   assert(var->nlbchginfos < 2
546  	      || SCIPbdchgidxIsEarlier(&var->lbchginfos[var->nlbchginfos-2].bdchgidx,
547  	         &var->lbchginfos[var->nlbchginfos-1].bdchgidx));
548  	
549  	   return SCIP_OKAY;
550  	}
551  	
552  	/** adds domain change info to the variable's upper bound change info array */
553  	static
554  	SCIP_RETCODE varAddUbchginfo(
555  	   SCIP_VAR*             var,                /**< problem variable */
556  	   BMS_BLKMEM*           blkmem,             /**< block memory */
557  	   SCIP_SET*             set,                /**< global SCIP settings */
558  	   SCIP_Real             oldbound,           /**< old value for bound */
559  	   SCIP_Real             newbound,           /**< new value for bound */
560  	   int                   depth,              /**< depth in the tree, where the bound change takes place */
561  	   int                   pos,                /**< position of the bound change in its bound change array */
562  	   SCIP_VAR*             infervar,           /**< variable that was changed (parent of var, or var itself) */
563  	   SCIP_CONS*            infercons,          /**< constraint that inferred this bound change, or NULL */
564  	   SCIP_PROP*            inferprop,          /**< propagator that deduced the bound change, or NULL */
565  	   int                   inferinfo,          /**< user information for inference to help resolving the conflict */
566  	   SCIP_BOUNDTYPE        inferboundtype,     /**< type of bound for inference var: lower or upper bound */
567  	   SCIP_BOUNDCHGTYPE     boundchgtype        /**< bound change type: branching decision or inferred bound change */
568  	   )
569  	{
570  	   assert(var != NULL);
571  	   assert(SCIPsetIsGT(set, oldbound, newbound));
572  	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, oldbound));
573  	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
574  	   assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 1.0));
575  	   assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 0.0));
576  	   assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
577  	   assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
578  	   assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
579  	
580  	   SCIPsetDebugMsg(set, "adding upper bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
581  	      SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
582  	      infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
583  	      oldbound, newbound);
584  	
585  	   SCIP_CALL( varEnsureUbchginfosSize(var, blkmem, set, var->nubchginfos+1) );
586  	   var->ubchginfos[var->nubchginfos].oldbound = oldbound;
587  	   var->ubchginfos[var->nubchginfos].newbound = newbound;
588  	   var->ubchginfos[var->nubchginfos].var = var;
589  	   var->ubchginfos[var->nubchginfos].bdchgidx.depth = depth;
590  	   var->ubchginfos[var->nubchginfos].bdchgidx.pos = pos;
591  	   var->ubchginfos[var->nubchginfos].pos = var->nubchginfos; /*lint !e732*/
592  	   var->ubchginfos[var->nubchginfos].boundchgtype = boundchgtype; /*lint !e641*/
593  	   var->ubchginfos[var->nubchginfos].boundtype = SCIP_BOUNDTYPE_UPPER; /*lint !e641*/
594  	   var->ubchginfos[var->nubchginfos].redundant = FALSE;
595  	   var->ubchginfos[var->nubchginfos].inferboundtype = inferboundtype; /*lint !e641*/
596  	   var->ubchginfos[var->nubchginfos].inferencedata.var = infervar;
597  	   var->ubchginfos[var->nubchginfos].inferencedata.info = inferinfo;
598  	
599  	   /**@note The "pos" data member of the bound change info has a size of 27 bits */
600  	   assert(var->nubchginfos < 1 << 27);
601  	
602  	   switch( boundchgtype )
603  	   {
604  	   case SCIP_BOUNDCHGTYPE_BRANCHING:
605  	      break;
606  	   case SCIP_BOUNDCHGTYPE_CONSINFER:
607  	      assert(infercons != NULL);
608  	      var->ubchginfos[var->nubchginfos].inferencedata.reason.cons = infercons;
609  	      break;
610  	   case SCIP_BOUNDCHGTYPE_PROPINFER:
611  	      var->ubchginfos[var->nubchginfos].inferencedata.reason.prop = inferprop;
612  	      break;
613  	   default:
614  	      SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
615  	      return SCIP_INVALIDDATA;
616  	   }
617  	
618  	   var->nubchginfos++;
619  	
620  	   assert(var->nubchginfos < 2
621  	      || SCIPbdchgidxIsEarlier(&var->ubchginfos[var->nubchginfos-2].bdchgidx,
622  	         &var->ubchginfos[var->nubchginfos-1].bdchgidx));
623  	
624  	   return SCIP_OKAY;
625  	}
626  	
627  	/** applies single bound change */
628  	SCIP_RETCODE SCIPboundchgApply(
629  	   SCIP_BOUNDCHG*        boundchg,           /**< bound change to apply */
630  	   BMS_BLKMEM*           blkmem,             /**< block memory */
631  	   SCIP_SET*             set,                /**< global SCIP settings */
632  	   SCIP_STAT*            stat,               /**< problem statistics */
633  	   SCIP_LP*              lp,                 /**< current LP data */
634  	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
635  	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
636  	   int                   depth,              /**< depth in the tree, where the bound change takes place */
637  	   int                   pos,                /**< position of the bound change in its bound change array */
638  	   SCIP_Bool*            cutoff              /**< pointer to store whether an infeasible bound change was detected */
639  	   )
640  	{
641  	   SCIP_VAR* var;
642  	
643  	   assert(boundchg != NULL);
644  	   assert(stat != NULL);
645  	   assert(depth > 0);
646  	   assert(pos >= 0);
647  	   assert(cutoff != NULL);
648  	
649  	   *cutoff = FALSE;
650  	
651  	   /* ignore redundant bound changes */
652  	   if( boundchg->redundant )
653  	      return SCIP_OKAY;
654  	
655  	   var = boundchg->var;
656  	   assert(var != NULL);
657  	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
658  	   assert(!SCIPvarIsIntegral(var) || SCIPsetIsFeasIntegral(set, boundchg->newbound));
659  	
660  	   /* apply bound change */
661  	   switch( boundchg->boundtype )
662  	   {
663  	   case SCIP_BOUNDTYPE_LOWER:
664  	      /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
665  	      if( SCIPsetIsGT(set, boundchg->newbound, var->locdom.lb) )
666  	      {
667  	         if( SCIPsetIsLE(set, boundchg->newbound, var->locdom.ub) )
668  	         {
669  	            /* add the bound change info to the variable's bound change info array */
670  	            switch( boundchg->boundchgtype )
671  	            {
672  	            case SCIP_BOUNDCHGTYPE_BRANCHING:
673  	               SCIPsetDebugMsg(set, " -> branching: new lower bound of <%s>[%g,%g]: %g\n",
674  	                  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
675  	               SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
676  	                     NULL, NULL, NULL, 0, SCIP_BOUNDTYPE_LOWER, SCIP_BOUNDCHGTYPE_BRANCHING) );
677  	               stat->lastbranchvar = var;
678  	               stat->lastbranchdir = SCIP_BRANCHDIR_UPWARDS;
679  	               stat->lastbranchvalue = boundchg->newbound;
680  	               break;
681  	
682  	            case SCIP_BOUNDCHGTYPE_CONSINFER:
683  	               assert(boundchg->data.inferencedata.reason.cons != NULL);
684  	               SCIPsetDebugMsg(set, " -> constraint <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
685  	                  SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
686  	                  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
687  	               SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
688  	                     boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
689  	                     boundchg->data.inferencedata.info,
690  	                     (SCIP_BOUNDTYPE)(boundchg->inferboundtype), SCIP_BOUNDCHGTYPE_CONSINFER) );
691  	               break;
692  	
693  	            case SCIP_BOUNDCHGTYPE_PROPINFER:
694  	               SCIPsetDebugMsg(set, " -> propagator <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
695  	                  boundchg->data.inferencedata.reason.prop != NULL
696  	                  ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
697  	                  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
698  	               SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
699  	                     boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
700  	                     boundchg->data.inferencedata.info,
701  	                     (SCIP_BOUNDTYPE)(boundchg->inferboundtype), SCIP_BOUNDCHGTYPE_PROPINFER) );
702  	               break;
703  	
704  	            default:
705  	               SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
706  	               return SCIP_INVALIDDATA;
707  	            }
708  	
709  	            /* change local bound of variable */
710  	            SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
711  	         }
712  	         else
713  	         {
714  	            SCIPsetDebugMsg(set, " -> cutoff: new lower bound of <%s>[%g,%g]: %g\n",
715  	               SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
716  	            *cutoff = TRUE;
717  	            boundchg->redundant = TRUE; /* bound change has not entered the lbchginfos array of the variable! */
718  	         }
719  	      }
720  	      else
721  	      {
722  	         /* mark bound change to be inactive */
723  	         SCIPsetDebugMsg(set, " -> inactive %s: new lower bound of <%s>[%g,%g]: %g\n",
724  	            (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
725  	            SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
726  	         boundchg->redundant = TRUE;
727  	      }
728  	      break;
729  	
730  	   case SCIP_BOUNDTYPE_UPPER:
731  	      /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
732  	      if( SCIPsetIsLT(set, boundchg->newbound, var->locdom.ub) )
733  	      {
734  	         if( SCIPsetIsGE(set, boundchg->newbound, var->locdom.lb) )
735  	         {
736  	            /* add the bound change info to the variable's bound change info array */
737  	            switch( boundchg->boundchgtype )
738  	            {
739  	            case SCIP_BOUNDCHGTYPE_BRANCHING:
740  	               SCIPsetDebugMsg(set, " -> branching: new upper bound of <%s>[%g,%g]: %g\n",
741  	                  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
742  	               SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
743  	                     NULL, NULL, NULL, 0, SCIP_BOUNDTYPE_UPPER, SCIP_BOUNDCHGTYPE_BRANCHING) );
744  	               stat->lastbranchvar = var;
745  	               stat->lastbranchdir = SCIP_BRANCHDIR_DOWNWARDS;
746  	               stat->lastbranchvalue = boundchg->newbound;
747  	               break;
748  	
749  	            case SCIP_BOUNDCHGTYPE_CONSINFER:
750  	               assert(boundchg->data.inferencedata.reason.cons != NULL);
751  	               SCIPsetDebugMsg(set, " -> constraint <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
752  	                  SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
753  	                  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
754  	               SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
755  	                     boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
756  	                     boundchg->data.inferencedata.info,
757  	                     (SCIP_BOUNDTYPE)(boundchg->inferboundtype), SCIP_BOUNDCHGTYPE_CONSINFER) );
758  	               break;
759  	
760  	            case SCIP_BOUNDCHGTYPE_PROPINFER:
761  	               SCIPsetDebugMsg(set, " -> propagator <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
762  	                  boundchg->data.inferencedata.reason.prop != NULL
763  	                  ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
764  	                  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
765  	               SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
766  	                     boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
767  	                     boundchg->data.inferencedata.info,
768  	                     (SCIP_BOUNDTYPE)(boundchg->inferboundtype), SCIP_BOUNDCHGTYPE_PROPINFER) );
769  	               break;
770  	
771  	            default:
772  	               SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
773  	               return SCIP_INVALIDDATA;
774  	            }
775  	
776  	            /* change local bound of variable */
777  	            SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
778  	         }
779  	         else
780  	         {
781  	            SCIPsetDebugMsg(set, " -> cutoff: new upper bound of <%s>[%g,%g]: %g\n",
782  	               SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
783  	            *cutoff = TRUE;
784  	            boundchg->redundant = TRUE; /* bound change has not entered the ubchginfos array of the variable! */
785  	         }
786  	      }
787  	      else
788  	      {
789  	         /* mark bound change to be inactive */
790  	         SCIPsetDebugMsg(set, " -> inactive %s: new upper bound of <%s>[%g,%g]: %g\n",
791  	            (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
792  	            SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
793  	         boundchg->redundant = TRUE;
794  	      }
795  	      break;
796  	
797  	   default:
798  	      SCIPerrorMessage("unknown bound type\n");
799  	      return SCIP_INVALIDDATA;
800  	   }
801  	
802  	   /* update the branching and inference history */
803  	   if( !boundchg->applied && !boundchg->redundant )
804  	   {
805  	      assert(var == boundchg->var);
806  	
807  	      if( (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING )
808  	      {
809  	         SCIP_CALL( SCIPvarIncNBranchings(var, blkmem, set, stat,
810  	               (SCIP_BOUNDTYPE)boundchg->boundtype == SCIP_BOUNDTYPE_LOWER
811  	               ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS, boundchg->newbound, depth) );
812  	      }
813  	      else if( stat->lastbranchvar != NULL )
814  	      {
815  	         /**@todo if last branching variable is unknown, retrieve it from the nodes' boundchg arrays */
816  	         SCIP_CALL( SCIPvarIncInferenceSum(stat->lastbranchvar, blkmem, set, stat, stat->lastbranchdir, stat->lastbranchvalue, 1.0) );
817  	      }
818  	      boundchg->applied = TRUE;
819  	   }
820  	
821  	   return SCIP_OKAY;
822  	}
823  	
824  	/** undoes single bound change */
825  	SCIP_RETCODE SCIPboundchgUndo(
826  	   SCIP_BOUNDCHG*        boundchg,           /**< bound change to remove */
827  	   BMS_BLKMEM*           blkmem,             /**< block memory */
828  	   SCIP_SET*             set,                /**< global SCIP settings */
829  	   SCIP_STAT*            stat,               /**< problem statistics */
830  	   SCIP_LP*              lp,                 /**< current LP data */
831  	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
832  	   SCIP_EVENTQUEUE*      eventqueue          /**< event queue */
833  	   )
834  	{
835  	   SCIP_VAR* var;
836  	
837  	   assert(boundchg != NULL);
838  	   assert(stat != NULL);
839  	
840  	   /* ignore redundant bound changes */
841  	   if( boundchg->redundant )
842  	      return SCIP_OKAY;
843  	
844  	   var = boundchg->var;
845  	   assert(var != NULL);
846  	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
847  	
848  	   /* undo bound change: apply the previous bound change of variable */
849  	   switch( boundchg->boundtype )
850  	   {
851  	   case SCIP_BOUNDTYPE_LOWER:
852  	      var->nlbchginfos--;
853  	      assert(var->nlbchginfos >= 0);
854  	      assert(var->lbchginfos != NULL);
855  	      assert( SCIPsetIsFeasEQ(set, var->lbchginfos[var->nlbchginfos].newbound, var->locdom.lb) ); /*lint !e777*/
856  	      assert( SCIPsetIsFeasLE(set, boundchg->newbound, var->locdom.lb) ); /* current lb might be larger to intermediate global bound change */
857  	
858  	      SCIPsetDebugMsg(set, "removed lower bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
859  	         SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
860  	         var->lbchginfos[var->nlbchginfos].bdchgidx.depth, var->lbchginfos[var->nlbchginfos].bdchgidx.pos,
861  	         var->lbchginfos[var->nlbchginfos].oldbound, var->lbchginfos[var->nlbchginfos].newbound);
862  	
863  	      /* reinstall the previous local bound */
864  	      SCIP_CALL( SCIPvarChgLbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
865  	            var->lbchginfos[var->nlbchginfos].oldbound) );
866  	
867  	      /* in case all bound changes are removed the local bound should match the global bound */
868  	      assert(var->nlbchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.lb, var->glbdom.lb));
869  	
870  	      break;
871  	
872  	   case SCIP_BOUNDTYPE_UPPER:
873  	      var->nubchginfos--;
874  	      assert(var->nubchginfos >= 0);
875  	      assert(var->ubchginfos != NULL);
876  	      assert( SCIPsetIsFeasEQ(set, var->ubchginfos[var->nubchginfos].newbound, var->locdom.ub) ); /*lint !e777*/
877  	      assert( SCIPsetIsFeasGE(set, boundchg->newbound, var->locdom.ub) ); /* current ub might be smaller to intermediate global bound change */
878  	
879  	      SCIPsetDebugMsg(set, "removed upper bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
880  	         SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
881  	         var->ubchginfos[var->nubchginfos].bdchgidx.depth, var->ubchginfos[var->nubchginfos].bdchgidx.pos,
882  	         var->ubchginfos[var->nubchginfos].oldbound, var->ubchginfos[var->nubchginfos].newbound);
883  	
884  	      /* reinstall the previous local bound */
885  	      SCIP_CALL( SCIPvarChgUbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
886  	            var->ubchginfos[var->nubchginfos].oldbound) );
887  	
888  	      /* in case all bound changes are removed the local bound should match the global bound */
889  	      assert(var->nubchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.ub, var->glbdom.ub));
890  	
891  	      break;
892  	
893  	   default:
894  	      SCIPerrorMessage("unknown bound type\n");
895  	      return SCIP_INVALIDDATA;
896  	   }
897  	
898  	   /* update last branching variable */
899  	   if( (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING )
900  	   {
901  	      stat->lastbranchvar = NULL;
902  	      stat->lastbranchvalue = SCIP_UNKNOWN;
903  	   }
904  	
905  	   return SCIP_OKAY;
906  	}
907  	
908  	/** applies single bound change to the global problem by changing the global bound of the corresponding variable */
909  	static
910  	SCIP_RETCODE boundchgApplyGlobal(
911  	   SCIP_BOUNDCHG*        boundchg,           /**< bound change to apply */
912  	   BMS_BLKMEM*           blkmem,             /**< block memory */
913  	   SCIP_SET*             set,                /**< global SCIP settings */
914  	   SCIP_STAT*            stat,               /**< problem statistics */
915  	   SCIP_LP*              lp,                 /**< current LP data */
916  	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
917  	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
918  	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
919  	   SCIP_Bool*            cutoff              /**< pointer to store whether an infeasible bound change was detected */
920  	   )
921  	{
922  	   SCIP_VAR* var;
923  	   SCIP_Real newbound;
924  	   SCIP_BOUNDTYPE boundtype;
925  	
926  	   assert(boundchg != NULL);
927  	   assert(cutoff != NULL);
928  	
929  	   *cutoff = FALSE;
930  	
931  	   /* ignore redundant bound changes */
932  	   if( boundchg->redundant )
933  	      return SCIP_OKAY;
934  	
935  	   var = SCIPboundchgGetVar(boundchg);
936  	   newbound = SCIPboundchgGetNewbound(boundchg);
937  	   boundtype = SCIPboundchgGetBoundtype(boundchg);
938  	
939  	   /* check if the bound change is redundant which can happen due to a (better) global bound change which was performed
940  	    * after that bound change was applied
941  	    *
942  	    * @note a global bound change is not captured by the redundant member of the bound change data structure
943  	    */
944  	   if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasLE(set, newbound, SCIPvarGetLbGlobal(var)))
945  	      || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasGE(set, newbound, SCIPvarGetUbGlobal(var))) )
946  	   {
947  	      return SCIP_OKAY;
948  	   }
949  	
950  	   SCIPsetDebugMsg(set, "applying global bound change: <%s>[%g,%g] %s %g\n",
951  	      SCIPvarGetName(var), SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var),
952  	      boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", newbound);
953  	
954  	   /* check for cutoff */
955  	   if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, newbound, SCIPvarGetUbGlobal(var)))
956  	      || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, newbound, SCIPvarGetLbGlobal(var))) )
957  	   {
958  	      *cutoff = TRUE;
959  	      return SCIP_OKAY;
960  	   }
961  	
962  	   /* apply bound change */
963  	   SCIP_CALL( SCIPvarChgBdGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound, boundtype) );
964  	
965  	   return SCIP_OKAY;
966  	}
967  	
968  	/** captures branching and inference data of bound change */
969  	static
970  	SCIP_RETCODE boundchgCaptureData(
971  	   SCIP_BOUNDCHG*        boundchg            /**< bound change to remove */
972  	   )
973  	{
974  	   assert(boundchg != NULL);
975  	
976  	   /* capture variable associated with the bound change */
977  	   assert(boundchg->var != NULL);
978  	   SCIPvarCapture(boundchg->var);
979  	
980  	   switch( boundchg->boundchgtype )
981  	   {
982  	   case SCIP_BOUNDCHGTYPE_BRANCHING:
983  	   case SCIP_BOUNDCHGTYPE_PROPINFER:
984  	      break;
985  	
986  	   case SCIP_BOUNDCHGTYPE_CONSINFER:
987  	      assert(boundchg->data.inferencedata.var != NULL);
988  	      assert(boundchg->data.inferencedata.reason.cons != NULL);
989  	      SCIPconsCapture(boundchg->data.inferencedata.reason.cons);
990  	      break;
991  	
992  	   default:
993  	      SCIPerrorMessage("invalid bound change type\n");
994  	      return SCIP_INVALIDDATA;
995  	   }
996  	
997  	   return SCIP_OKAY;
998  	}
999  	
1000 	/** releases branching and inference data of bound change */
1001 	static
1002 	SCIP_RETCODE boundchgReleaseData(
1003 	   SCIP_BOUNDCHG*        boundchg,           /**< bound change to remove */
1004 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1005 	   SCIP_SET*             set,                /**< global SCIP settings */
1006 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
1007 	   SCIP_LP*              lp                  /**< current LP data */
1008 	
1009 	   )
1010 	{
1011 	   assert(boundchg != NULL);
1012 	
1013 	   switch( boundchg->boundchgtype )
1014 	   {
1015 	   case SCIP_BOUNDCHGTYPE_BRANCHING:
1016 	   case SCIP_BOUNDCHGTYPE_PROPINFER:
1017 	      break;
1018 	
1019 	   case SCIP_BOUNDCHGTYPE_CONSINFER:
1020 	      assert(boundchg->data.inferencedata.var != NULL);
1021 	      assert(boundchg->data.inferencedata.reason.cons != NULL);
1022 	      SCIP_CALL( SCIPconsRelease(&boundchg->data.inferencedata.reason.cons, blkmem, set) );
1023 	      break;
1024 	
1025 	   default:
1026 	      SCIPerrorMessage("invalid bound change type\n");
1027 	      return SCIP_INVALIDDATA;
1028 	   }
1029 	
1030 	   /* release variable */
1031 	   assert(boundchg->var != NULL);
1032 	   SCIP_CALL( SCIPvarRelease(&boundchg->var, blkmem, set, eventqueue, lp) );
1033 	
1034 	   return SCIP_OKAY;
1035 	}
1036 	
1037 	/** creates empty domain change data with dynamic arrays */
1038 	static
1039 	SCIP_RETCODE domchgCreate(
1040 	   SCIP_DOMCHG**         domchg,             /**< pointer to domain change data */
1041 	   BMS_BLKMEM*           blkmem              /**< block memory */
1042 	   )
1043 	{
1044 	   assert(domchg != NULL);
1045 	   assert(blkmem != NULL);
1046 	
1047 	   SCIP_ALLOC( BMSallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN)) );
1048 	   (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1049 	   (*domchg)->domchgdyn.nboundchgs = 0;
1050 	   (*domchg)->domchgdyn.boundchgs = NULL;
1051 	   (*domchg)->domchgdyn.nholechgs = 0;
1052 	   (*domchg)->domchgdyn.holechgs = NULL;
1053 	   (*domchg)->domchgdyn.boundchgssize = 0;
1054 	   (*domchg)->domchgdyn.holechgssize = 0;
1055 	
1056 	   return SCIP_OKAY;
1057 	}
1058 	
1059 	/** frees domain change data */
1060 	SCIP_RETCODE SCIPdomchgFree(
1061 	   SCIP_DOMCHG**         domchg,             /**< pointer to domain change */
1062 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1063 	   SCIP_SET*             set,                /**< global SCIP settings */
1064 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
1065 	   SCIP_LP*              lp                  /**< current LP data */
1066 	   )
1067 	{
1068 	   assert(domchg != NULL);
1069 	   assert(blkmem != NULL);
1070 	
1071 	   if( *domchg != NULL )
1072 	   {
1073 	      int i;
1074 	
1075 	      /* release variables, branching and inference data associated with the bound changes */
1076 	      for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1077 	      {
1078 	         SCIP_CALL( boundchgReleaseData(&(*domchg)->domchgbound.boundchgs[i], blkmem, set, eventqueue, lp) );
1079 	      }
1080 	
1081 	      /* free memory for bound and hole changes */
1082 	      switch( (*domchg)->domchgdyn.domchgtype )
1083 	      {
1084 	      case SCIP_DOMCHGTYPE_BOUND:
1085 	         BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgbound.boundchgs, (*domchg)->domchgbound.nboundchgs);
1086 	         BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND));
1087 	         break;
1088 	      case SCIP_DOMCHGTYPE_BOTH:
1089 	         BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.boundchgs, (*domchg)->domchgboth.nboundchgs);
1090 	         BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.holechgs, (*domchg)->domchgboth.nholechgs);
1091 	         BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH));
1092 	         break;
1093 	      case SCIP_DOMCHGTYPE_DYNAMIC:
1094 	         BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.boundchgs, (*domchg)->domchgdyn.boundchgssize);
1095 	         BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1096 	         BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN));
1097 	         break;
1098 	      default:
1099 	         SCIPerrorMessage("invalid domain change type\n");
1100 	         return SCIP_INVALIDDATA;
1101 	      }
1102 	   }
1103 	
1104 	   return SCIP_OKAY;
1105 	}
1106 	
1107 	/** converts a static domain change data into a dynamic one */
1108 	static
1109 	SCIP_RETCODE domchgMakeDynamic(
1110 	   SCIP_DOMCHG**         domchg,             /**< pointer to domain change data */
1111 	   BMS_BLKMEM*           blkmem              /**< block memory */
1112 	   )
1113 	{
1114 	   assert(domchg != NULL);
1115 	   assert(blkmem != NULL);
1116 	
1117 	   SCIPdebugMessage("making domain change data %p pointing to %p dynamic\n", (void*)domchg, (void*)*domchg);
1118 	
1119 	   if( *domchg == NULL )
1120 	   {
1121 	      SCIP_CALL( domchgCreate(domchg, blkmem) );
1122 	   }
1123 	   else
1124 	   {
1125 	      switch( (*domchg)->domchgdyn.domchgtype )
1126 	      {
1127 	      case SCIP_DOMCHGTYPE_BOUND:
1128 	         SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND), sizeof(SCIP_DOMCHGDYN)) );
1129 	         (*domchg)->domchgdyn.nholechgs = 0;
1130 	         (*domchg)->domchgdyn.holechgs = NULL;
1131 	         (*domchg)->domchgdyn.boundchgssize = (int) (*domchg)->domchgdyn.nboundchgs;
1132 	         (*domchg)->domchgdyn.holechgssize = 0;
1133 	         (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1134 	         break;
1135 	      case SCIP_DOMCHGTYPE_BOTH:
1136 	         SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGDYN)) );
1137 	         (*domchg)->domchgdyn.boundchgssize = (int) (*domchg)->domchgdyn.nboundchgs;
1138 	         (*domchg)->domchgdyn.holechgssize = (*domchg)->domchgdyn.nholechgs;
1139 	         (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1140 	         break;
1141 	      case SCIP_DOMCHGTYPE_DYNAMIC:
1142 	         break;
1143 	      default:
1144 	         SCIPerrorMessage("invalid domain change type\n");
1145 	         return SCIP_INVALIDDATA;
1146 	      }
1147 	   }
1148 	#ifndef NDEBUG
1149 	   {
1150 	      int i;
1151 	      for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1152 	         assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1153 	            || EPSISINT((*domchg)->domchgbound.boundchgs[i].newbound, 1e-06));
1154 	   }
1155 	#endif
1156 	
1157 	   return SCIP_OKAY;
1158 	}
1159 	
1160 	/** converts a dynamic domain change data into a static one, using less memory than for a dynamic one */
1161 	SCIP_RETCODE SCIPdomchgMakeStatic(
1162 	   SCIP_DOMCHG**         domchg,             /**< pointer to domain change data */
1163 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1164 	   SCIP_SET*             set,                /**< global SCIP settings */
1165 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
1166 	   SCIP_LP*              lp                  /**< current LP data */
1167 	   )
1168 	{
1169 	   assert(domchg != NULL);
1170 	   assert(blkmem != NULL);
1171 	
1172 	   SCIPsetDebugMsg(set, "making domain change data %p pointing to %p static\n", (void*)domchg, (void*)*domchg);
1173 	
1174 	   if( *domchg != NULL )
1175 	   {
1176 	      switch( (*domchg)->domchgdyn.domchgtype )
1177 	      {
1178 	      case SCIP_DOMCHGTYPE_BOUND:
1179 	         if( (*domchg)->domchgbound.nboundchgs == 0 )
1180 	         {
1181 	            SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1182 	         }
1183 	         break;
1184 	      case SCIP_DOMCHGTYPE_BOTH:
1185 	         if( (*domchg)->domchgboth.nholechgs == 0 )
1186 	         {
1187 	            if( (*domchg)->domchgbound.nboundchgs == 0 )
1188 	            {
1189 	               SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1190 	            }
1191 	            else
1192 	            {
1193 	               SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGBOUND)) );
1194 	               (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1195 	            }
1196 	         }
1197 	         break;
1198 	      case SCIP_DOMCHGTYPE_DYNAMIC:
1199 	         if( (*domchg)->domchgboth.nholechgs == 0 )
1200 	         {
1201 	            if( (*domchg)->domchgbound.nboundchgs == 0 )
1202 	            {
1203 	               SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1204 	            }
1205 	            else
1206 	            {
1207 	               /* shrink dynamic size arrays to their minimal sizes */
1208 	               SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs, \
1209 	                     (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1210 	               BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1211 	
1212 	               /* convert into static domain change */
1213 	               SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOUND)) );
1214 	               (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1215 	            }
1216 	         }
1217 	         else
1218 	         {
1219 	            /* shrink dynamic size arrays to their minimal sizes */
1220 	            SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs, \
1221 	                  (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1222 	            SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.holechgs, \
1223 	                  (*domchg)->domchgdyn.holechgssize, (*domchg)->domchgdyn.nholechgs) );
1224 	
1225 	            /* convert into static domain change */
1226 	            SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOTH)) );
1227 	            (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOTH; /*lint !e641*/
1228 	         }
1229 	         break;
1230 	      default:
1231 	         SCIPerrorMessage("invalid domain change type\n");
1232 	         return SCIP_INVALIDDATA;
1233 	      }
1234 	#ifndef NDEBUG
1235 	      if( *domchg != NULL )
1236 	      {
1237 	         int i;
1238 	         for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1239 	            assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1240 	               || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1241 	      }
1242 	#endif
1243 	   }
1244 	
1245 	   return SCIP_OKAY;
1246 	}
1247 	
1248 	/** ensures, that boundchgs array can store at least num entries */
1249 	static
1250 	SCIP_RETCODE domchgEnsureBoundchgsSize(
1251 	   SCIP_DOMCHG*          domchg,             /**< domain change data structure */
1252 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1253 	   SCIP_SET*             set,                /**< global SCIP settings */
1254 	   int                   num                 /**< minimum number of entries to store */
1255 	   )
1256 	{
1257 	   assert(domchg != NULL);
1258 	   assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1259 	
1260 	   if( num > domchg->domchgdyn.boundchgssize )
1261 	   {
1262 	      int newsize;
1263 	
1264 	      newsize = SCIPsetCalcMemGrowSize(set, num);
1265 	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.boundchgs, domchg->domchgdyn.boundchgssize, newsize) );
1266 	      domchg->domchgdyn.boundchgssize = newsize;
1267 	   }
1268 	   assert(num <= domchg->domchgdyn.boundchgssize);
1269 	
1270 	   return SCIP_OKAY;
1271 	}
1272 	
1273 	/** ensures, that holechgs array can store at least num additional entries */
1274 	static
1275 	SCIP_RETCODE domchgEnsureHolechgsSize(
1276 	   SCIP_DOMCHG*          domchg,             /**< domain change data structure */
1277 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1278 	   SCIP_SET*             set,                /**< global SCIP settings */
1279 	   int                   num                 /**< minimum number of additional entries to store */
1280 	   )
1281 	{
1282 	   assert(domchg != NULL);
1283 	   assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1284 	
1285 	   if( num > domchg->domchgdyn.holechgssize )
1286 	   {
1287 	      int newsize;
1288 	
1289 	      newsize = SCIPsetCalcMemGrowSize(set, num);
1290 	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.holechgs, domchg->domchgdyn.holechgssize, newsize) );
1291 	      domchg->domchgdyn.holechgssize = newsize;
1292 	   }
1293 	   assert(num <= domchg->domchgdyn.holechgssize);
1294 	
1295 	   return SCIP_OKAY;
1296 	}
1297 	
1298 	/** applies domain change */
1299 	SCIP_RETCODE SCIPdomchgApply(
1300 	   SCIP_DOMCHG*          domchg,             /**< domain change to apply */
1301 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1302 	   SCIP_SET*             set,                /**< global SCIP settings */
1303 	   SCIP_STAT*            stat,               /**< problem statistics */
1304 	   SCIP_LP*              lp,                 /**< current LP data */
1305 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
1306 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
1307 	   int                   depth,              /**< depth in the tree, where the domain change takes place */
1308 	   SCIP_Bool*            cutoff              /**< pointer to store whether an infeasible domain change was detected */
1309 	   )
1310 	{
1311 	   int i;
1312 	
1313 	   assert(cutoff != NULL);
1314 	
1315 	   *cutoff = FALSE;
1316 	
1317 	   SCIPsetDebugMsg(set, "applying domain changes at %p in depth %d\n", (void*)domchg, depth);
1318 	
1319 	   if( domchg == NULL )
1320 	      return SCIP_OKAY;
1321 	
1322 	   /* apply bound changes */
1323 	   for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1324 	   {
1325 	      SCIP_CALL( SCIPboundchgApply(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1326 	            branchcand, eventqueue, depth, i, cutoff) );
1327 	      if( *cutoff )
1328 	         break;
1329 	   }
1330 	   SCIPsetDebugMsg(set, " -> %u bound changes (cutoff %u)\n", domchg->domchgbound.nboundchgs, *cutoff);
1331 	
1332 	   /* mark all bound changes after a cutoff redundant */
1333 	   for( ; i < (int)domchg->domchgbound.nboundchgs; ++i )
1334 	      domchg->domchgbound.boundchgs[i].redundant = TRUE;
1335 	
1336 	   /* apply holelist changes */
1337 	   if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1338 	   {
1339 	      for( i = 0; i < domchg->domchgboth.nholechgs; ++i )
1340 	         *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].newlist;
1341 	      SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1342 	   }
1343 	
1344 	   return SCIP_OKAY;
1345 	}
1346 	
1347 	/** undoes domain change */
1348 	SCIP_RETCODE SCIPdomchgUndo(
1349 	   SCIP_DOMCHG*          domchg,             /**< domain change to remove */
1350 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1351 	   SCIP_SET*             set,                /**< global SCIP settings */
1352 	   SCIP_STAT*            stat,               /**< problem statistics */
1353 	   SCIP_LP*              lp,                 /**< current LP data */
1354 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
1355 	   SCIP_EVENTQUEUE*      eventqueue          /**< event queue */
1356 	   )
1357 	{
1358 	   int i;
1359 	
1360 	   SCIPsetDebugMsg(set, "undoing domain changes at %p\n", (void*)domchg);
1361 	   if( domchg == NULL )
1362 	      return SCIP_OKAY;
1363 	
1364 	   /* undo holelist changes */
1365 	   if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1366 	   {
1367 	      for( i = domchg->domchgboth.nholechgs-1; i >= 0; --i )
1368 	         *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].oldlist;
1369 	      SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1370 	   }
1371 	
1372 	   /* undo bound changes */
1373 	   for( i = domchg->domchgbound.nboundchgs-1; i >= 0; --i )
1374 	   {
1375 	      SCIP_CALL( SCIPboundchgUndo(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp, branchcand, eventqueue) );
1376 	   }
1377 	   SCIPsetDebugMsg(set, " -> %u bound changes\n", domchg->domchgbound.nboundchgs);
1378 	
1379 	   return SCIP_OKAY;
1380 	}
1381 	
1382 	/** applies domain change to the global problem */
1383 	SCIP_RETCODE SCIPdomchgApplyGlobal(
1384 	   SCIP_DOMCHG*          domchg,             /**< domain change to apply */
1385 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1386 	   SCIP_SET*             set,                /**< global SCIP settings */
1387 	   SCIP_STAT*            stat,               /**< problem statistics */
1388 	   SCIP_LP*              lp,                 /**< current LP data */
1389 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
1390 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
1391 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
1392 	   SCIP_Bool*            cutoff              /**< pointer to store whether an infeasible domain change was detected */
1393 	   )
1394 	{
1395 	   int i;
1396 	
1397 	   assert(cutoff != NULL);
1398 	
1399 	   *cutoff = FALSE;
1400 	
1401 	   if( domchg == NULL )
1402 	      return SCIP_OKAY;
1403 	
1404 	   SCIPsetDebugMsg(set, "applying domain changes at %p to the global problem\n", (void*)domchg);
1405 	
1406 	   /* apply bound changes */
1407 	   for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1408 	   {
1409 	      SCIP_CALL( boundchgApplyGlobal(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1410 	            branchcand, eventqueue, cliquetable, cutoff) );
1411 	      if( *cutoff )
1412 	         break;
1413 	   }
1414 	   SCIPsetDebugMsg(set, " -> %u global bound changes\n", domchg->domchgbound.nboundchgs);
1415 	
1416 	   /**@todo globally apply holelist changes - how can this be done without confusing pointer updates? */
1417 	
1418 	   return SCIP_OKAY;
1419 	}
1420 	
1421 	/** adds bound change to domain changes */
1422 	SCIP_RETCODE SCIPdomchgAddBoundchg(
1423 	   SCIP_DOMCHG**         domchg,             /**< pointer to domain change data structure */
1424 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1425 	   SCIP_SET*             set,                /**< global SCIP settings */
1426 	   SCIP_VAR*             var,                /**< variable to change the bounds for */
1427 	   SCIP_Real             newbound,           /**< new value for bound */
1428 	   SCIP_BOUNDTYPE        boundtype,          /**< type of bound for var: lower or upper bound */
1429 	   SCIP_BOUNDCHGTYPE     boundchgtype,       /**< type of bound change: branching decision or inference */
1430 	   SCIP_Real             lpsolval,           /**< solval of variable in last LP on path to node, or SCIP_INVALID if unknown */
1431 	   SCIP_VAR*             infervar,           /**< variable that was changed (parent of var, or var itself), or NULL */
1432 	   SCIP_CONS*            infercons,          /**< constraint that deduced the bound change, or NULL */
1433 	   SCIP_PROP*            inferprop,          /**< propagator that deduced the bound change, or NULL */
1434 	   int                   inferinfo,          /**< user information for inference to help resolving the conflict */
1435 	   SCIP_BOUNDTYPE        inferboundtype      /**< type of bound for inference var: lower or upper bound */
1436 	   )
1437 	{
1438 	   SCIP_BOUNDCHG* boundchg;
1439 	
1440 	   assert(domchg != NULL);
1441 	   assert(var != NULL);
1442 	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
1443 	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
1444 	   assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, boundtype == SCIP_BOUNDTYPE_LOWER ? 1.0 : 0.0));
1445 	   assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
1446 	   assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
1447 	   assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
1448 	
1449 	   SCIPsetDebugMsg(set, "adding %s bound change <%s: %g> of variable <%s> to domain change at %p pointing to %p\n",
1450 	      boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
1451 	      newbound, var->name, (void*)domchg, (void*)*domchg);
1452 	
1453 	   /* if domain change data doesn't exist, create it;
1454 	    * if domain change is static, convert it into dynamic change
1455 	    */
1456 	   if( *domchg == NULL )
1457 	   {
1458 	      SCIP_CALL( domchgCreate(domchg, blkmem) );
1459 	   }
1460 	   else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1461 	   {
1462 	      SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1463 	   }
1464 	   assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1465 	
1466 	   /* get memory for additional bound change */
1467 	   SCIP_CALL( domchgEnsureBoundchgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nboundchgs+1) );
1468 	
1469 	   /* fill in the bound change data */
1470 	   boundchg = &(*domchg)->domchgdyn.boundchgs[(*domchg)->domchgdyn.nboundchgs];
1471 	   boundchg->var = var;
1472 	   switch( boundchgtype )
1473 	   {
1474 	   case SCIP_BOUNDCHGTYPE_BRANCHING:
1475 	      boundchg->data.branchingdata.lpsolval = lpsolval;
1476 	      break;
1477 	   case SCIP_BOUNDCHGTYPE_CONSINFER:
1478 	      assert(infercons != NULL);
1479 	      boundchg->data.inferencedata.var = infervar;
1480 	      boundchg->data.inferencedata.reason.cons = infercons;
1481 	      boundchg->data.inferencedata.info = inferinfo; 
1482 	      break;
1483 	   case SCIP_BOUNDCHGTYPE_PROPINFER:
1484 	      boundchg->data.inferencedata.var = infervar;
1485 	      boundchg->data.inferencedata.reason.prop = inferprop;
1486 	      boundchg->data.inferencedata.info = inferinfo; 
1487 	      break;
1488 	   default:
1489 	      SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
1490 	      return SCIP_INVALIDDATA;
1491 	   }
1492 	
1493 	   boundchg->newbound = newbound;
1494 	   boundchg->boundchgtype = boundchgtype; /*lint !e641*/
1495 	   boundchg->boundtype = boundtype; /*lint !e641*/
1496 	   boundchg->inferboundtype = inferboundtype; /*lint !e641*/
1497 	   boundchg->applied = FALSE;
1498 	   boundchg->redundant = FALSE;
1499 	   (*domchg)->domchgdyn.nboundchgs++;
1500 	
1501 	   /* capture branching and inference data associated with the bound changes */
1502 	   SCIP_CALL( boundchgCaptureData(boundchg) );
1503 	
1504 	#ifdef SCIP_DISABLED_CODE /* expensive debug check */
1505 	#ifdef SCIP_MORE_DEBUG
1506 	   {
1507 	      int i;
1508 	      for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1509 	         assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1510 	            || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1511 	   }
1512 	#endif
1513 	#endif
1514 	
1515 	   return SCIP_OKAY;
1516 	}
1517 	
1518 	/** adds hole change to domain changes */
1519 	SCIP_RETCODE SCIPdomchgAddHolechg(
1520 	   SCIP_DOMCHG**         domchg,             /**< pointer to domain change data structure */
1521 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1522 	   SCIP_SET*             set,                /**< global SCIP settings */
1523 	   SCIP_HOLELIST**       ptr,                /**< changed list pointer */
1524 	   SCIP_HOLELIST*        newlist,            /**< new value of list pointer */
1525 	   SCIP_HOLELIST*        oldlist             /**< old value of list pointer */
1526 	   )
1527 	{
1528 	   SCIP_HOLECHG* holechg;
1529 	
1530 	   assert(domchg != NULL);
1531 	   assert(ptr != NULL);
1532 	
1533 	   /* if domain change data doesn't exist, create it;
1534 	    * if domain change is static, convert it into dynamic change
1535 	    */
1536 	   if( *domchg == NULL )
1537 	   {
1538 	      SCIP_CALL( domchgCreate(domchg, blkmem) );
1539 	   }
1540 	   else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1541 	   {
1542 	      SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1543 	   }
1544 	   assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1545 	
1546 	   /* get memory for additional hole change */
1547 	   SCIP_CALL( domchgEnsureHolechgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nholechgs+1) );
1548 	
1549 	   /* fill in the hole change data */
1550 	   holechg = &(*domchg)->domchgdyn.holechgs[(*domchg)->domchgdyn.nholechgs];
1551 	   holechg->ptr = ptr;
1552 	   holechg->newlist = newlist;
1553 	   holechg->oldlist = oldlist;
1554 	   (*domchg)->domchgdyn.nholechgs++;
1555 	
1556 	   return SCIP_OKAY;
1557 	}
1558 	
1559 	
1560 	
1561 	
1562 	/*
1563 	 * methods for variables 
1564 	 */
1565 	
1566 	/** returns adjusted lower bound value, which is rounded for integral variable types */
1567 	static
1568 	SCIP_Real adjustedLb(
1569 	   SCIP_SET*             set,                /**< global SCIP settings */
1570 	   SCIP_VARTYPE          vartype,            /**< type of variable */
1571 	   SCIP_Real             lb                  /**< lower bound to adjust */
1572 	   )
1573 	{
1574 	   if( lb < 0.0 && SCIPsetIsInfinity(set, -lb) )
1575 	      return -SCIPsetInfinity(set);
1576 	   else if( lb > 0.0 && SCIPsetIsInfinity(set, lb) )
1577 	      return SCIPsetInfinity(set);
1578 	   else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1579 	      return SCIPsetFeasCeil(set, lb);
1580 	   else if( lb > 0.0 && lb < SCIPsetEpsilon(set) )
1581 	      return 0.0;
1582 	   else
1583 	      return lb;
1584 	}
1585 	
1586 	/** returns adjusted upper bound value, which is rounded for integral variable types */
1587 	static
1588 	SCIP_Real adjustedUb(
1589 	   SCIP_SET*             set,                /**< global SCIP settings */
1590 	   SCIP_VARTYPE          vartype,            /**< type of variable */
1591 	   SCIP_Real             ub                  /**< upper bound to adjust */
1592 	   )
1593 	{
1594 	   if( ub > 0.0 && SCIPsetIsInfinity(set, ub) )
1595 	      return SCIPsetInfinity(set);
1596 	   else if( ub < 0.0 && SCIPsetIsInfinity(set, -ub) )
1597 	      return -SCIPsetInfinity(set);
1598 	   else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1599 	      return SCIPsetFeasFloor(set, ub);
1600 	   else if( ub < 0.0 && ub > -SCIPsetEpsilon(set) )
1601 	      return 0.0;
1602 	   else
1603 	      return ub;
1604 	}
1605 	
1606 	/** removes (redundant) cliques, implications and variable bounds of variable from all other variables' implications and variable
1607 	 *  bounds arrays, and optionally removes them also from the variable itself
1608 	 */
1609 	SCIP_RETCODE SCIPvarRemoveCliquesImplicsVbs(
1610 	   SCIP_VAR*             var,                /**< problem variable */
1611 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1612 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
1613 	   SCIP_SET*             set,                /**< global SCIP settings */
1614 	   SCIP_Bool             irrelevantvar,      /**< has the variable become irrelevant? */
1615 	   SCIP_Bool             onlyredundant,      /**< should only the redundant implications and variable bounds be removed? */
1616 	   SCIP_Bool             removefromvar       /**< should the implications and variable bounds be removed from the var itself? */
1617 	   )
1618 	{
1619 	   SCIP_Real lb;
1620 	   SCIP_Real ub;
1621 	
1622 	   assert(var != NULL);
1623 	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
1624 	   assert(SCIPvarIsActive(var) || SCIPvarGetType(var) != SCIP_VARTYPE_BINARY);
1625 	
1626 	   lb = SCIPvarGetLbGlobal(var);
1627 	   ub = SCIPvarGetUbGlobal(var);
1628 	
1629 	   SCIPsetDebugMsg(set, "removing %s implications and vbounds of %s<%s>[%g,%g]\n",
1630 	      onlyredundant ? "redundant" : "all", irrelevantvar ? "irrelevant " : "", SCIPvarGetName(var), lb, ub);
1631 	
1632 	   /* remove implications of (fixed) binary variable */
1633 	   if( var->implics != NULL && (!onlyredundant || lb > 0.5 || ub < 0.5) )
1634 	   {
1635 	      SCIP_Bool varfixing;
1636 	
1637 	      assert(SCIPvarIsBinary(var));
1638 	
1639 	      varfixing = FALSE;
1640 	      do
1641 	      {
1642 	         SCIP_VAR** implvars;
1643 	         SCIP_BOUNDTYPE* impltypes;
1644 	         int nimpls;
1645 	         int i;
1646 	
1647 	         nimpls = SCIPimplicsGetNImpls(var->implics, varfixing);
1648 	         implvars = SCIPimplicsGetVars(var->implics, varfixing);
1649 	         impltypes = SCIPimplicsGetTypes(var->implics, varfixing);
1650 	
1651 	         for( i = 0; i < nimpls; i++ )
1652 	         {
1653 	            SCIP_VAR* implvar;
1654 	            SCIP_BOUNDTYPE impltype;
1655 	
1656 	            implvar = implvars[i];
1657 	            impltype = impltypes[i];
1658 	            assert(implvar != var);
1659 	
1660 	            /* remove for all implications z == 0 / 1  ==>  x <= p / x >= p (x not binary)
1661 	             * the following variable bound from x's variable bounds 
1662 	             *   x <= b*z+d (z in vubs of x)            , for z == 0 / 1  ==>  x <= p
1663 	             *   x >= b*z+d (z in vlbs of x)            , for z == 0 / 1  ==>  x >= p
1664 	             */
1665 	            if( impltype == SCIP_BOUNDTYPE_UPPER )
1666 	            {
1667 	               if( implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1668 	               {
1669 	                  SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u  ==>  <%s> <= %g\n",
1670 	                     SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
1671 	                     SCIPimplicsGetBounds(var->implics, varfixing)[i]);
1672 	                  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, varfixing) );
1673 	                  implvar->closestvblpcount = -1;
1674 	                  var->closestvblpcount = -1;
1675 	               }
1676 	            }
1677 	            else
1678 	            {
1679 	               if( implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1680 	               {
1681 	                  SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u  ==>  <%s> >= %g\n",
1682 	                     SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
1683 	                     SCIPimplicsGetBounds(var->implics, varfixing)[i]);
1684 	                  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, !varfixing) );
1685 	                  implvar->closestvblpcount = -1;
1686 	                  var->closestvblpcount = -1;
1687 	               }
1688 	            }
1689 	         }
1690 	         varfixing = !varfixing;
1691 	      }
1692 	      while( varfixing == TRUE );
1693 	
1694 	      if( removefromvar )
1695 	      {
1696 	         /* free the implications data structures */
1697 	         SCIPimplicsFree(&var->implics, blkmem);
1698 	      }
1699 	   }
1700 	
1701 	   /* remove the (redundant) variable lower bounds */
1702 	   if( var->vlbs != NULL )
1703 	   {
1704 	      SCIP_VAR** vars;
1705 	      SCIP_Real* coefs;
1706 	      SCIP_Real* constants;
1707 	      int nvbds;
1708 	      int newnvbds;
1709 	      int i;
1710 	
1711 	      nvbds = SCIPvboundsGetNVbds(var->vlbs);
1712 	      vars = SCIPvboundsGetVars(var->vlbs);
1713 	      coefs = SCIPvboundsGetCoefs(var->vlbs);
1714 	      constants = SCIPvboundsGetConstants(var->vlbs);
1715 	
1716 	      /* remove for all variable bounds x >= b*z+d the following implication from z's implications 
1717 	       *   z == ub  ==>  x >= b*ub + d           , if b > 0
1718 	       *   z == lb  ==>  x >= b*lb + d           , if b < 0
1719 	       */
1720 	      newnvbds = 0;
1721 	      for( i = 0; i < nvbds; i++ )
1722 	      {
1723 	         SCIP_VAR* implvar;
1724 	         SCIP_Real coef;
1725 	
1726 	         assert(newnvbds <= i);
1727 	
1728 	         implvar = vars[i];
1729 	         assert(implvar != NULL);
1730 	
1731 	         coef = coefs[i];
1732 	         assert(!SCIPsetIsZero(set, coef));
1733 	
1734 	         /* check, if we want to remove the variable bound */
1735 	         if( onlyredundant )
1736 	         {
1737 	            SCIP_Real vbound;
1738 	
1739 	            vbound = MAX(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i];  /*lint !e666*/
1740 	            if( SCIPsetIsFeasGT(set, vbound, lb) )
1741 	            {
1742 	               /* the variable bound is not redundant: keep it */
1743 	               if( removefromvar )
1744 	               {
1745 	                  if( newnvbds < i )
1746 	                  {
1747 	                     vars[newnvbds] = implvar;
1748 	                     coefs[newnvbds] = coef;
1749 	                     constants[newnvbds] = constants[i];
1750 	                  }
1751 	                  newnvbds++;
1752 	               }
1753 	               continue;
1754 	            }
1755 	         }
1756 	
1757 	         /* remove the corresponding implication */
1758 	         if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1759 	         {
1760 	            SCIPsetDebugMsg(set, "deleting implication: <%s> == %d  ==>  <%s> >= %g\n",
1761 	               SCIPvarGetName(implvar), (coef > 0.0), SCIPvarGetName(var), MAX(coef, 0.0) + constants[i]);
1762 	            SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef > 0.0), var, SCIP_BOUNDTYPE_LOWER) );
1763 	         }
1764 	         if( coef > 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1765 	         {
1766 	            SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
1767 	               SCIPvarGetName(implvar), SCIPvarGetName(var));
1768 	            SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, FALSE) );
1769 	            implvar->closestvblpcount = -1;
1770 	            var->closestvblpcount = -1;
1771 	         }
1772 	         else if( coef < 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1773 	         {
1774 	            SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
1775 	               SCIPvarGetName(implvar), SCIPvarGetName(var));
1776 	            SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, TRUE) );
1777 	            implvar->closestvblpcount = -1;
1778 	            var->closestvblpcount = -1;
1779 	         }
1780 	      }
1781 	
1782 	      if( removefromvar )
1783 	      {
1784 	         /* update the number of variable bounds */
1785 	         SCIPvboundsShrink(&var->vlbs, blkmem, newnvbds);
1786 	         var->closestvblpcount = -1;
1787 	      }
1788 	   }
1789 	
1790 	   /**@todo in general, variable bounds like x >= b*z + d corresponding to an implication like z = ub ==> x >= b*ub + d 
1791 	    *       might be missing because we only add variable bounds with reasonably small value of b. thus, we currently 
1792 	    *       cannot remove such variables x from z's implications.
1793 	    */
1794 	
1795 	   /* remove the (redundant) variable upper bounds */
1796 	   if( var->vubs != NULL )
1797 	   {
1798 	      SCIP_VAR** vars;
1799 	      SCIP_Real* coefs;
1800 	      SCIP_Real* constants;
1801 	      int nvbds;
1802 	      int newnvbds;
1803 	      int i;
1804 	
1805 	      nvbds = SCIPvboundsGetNVbds(var->vubs);
1806 	      vars = SCIPvboundsGetVars(var->vubs);
1807 	      coefs = SCIPvboundsGetCoefs(var->vubs);
1808 	      constants = SCIPvboundsGetConstants(var->vubs);
1809 	
1810 	      /* remove for all variable bounds x <= b*z+d the following implication from z's implications 
1811 	       *   z == lb  ==>  x <= b*lb + d           , if b > 0
1812 	       *   z == ub  ==>  x <= b*ub + d           , if b < 0
1813 	       */
1814 	      newnvbds = 0;
1815 	      for( i = 0; i < nvbds; i++ )
1816 	      {
1817 	         SCIP_VAR* implvar;
1818 	         SCIP_Real coef;
1819 	
1820 	         assert(newnvbds <= i);
1821 	
1822 	         implvar = vars[i];
1823 	         assert(implvar != NULL);
1824 	
1825 	         coef = coefs[i];
1826 	         assert(!SCIPsetIsZero(set, coef));
1827 	
1828 	         /* check, if we want to remove the variable bound */
1829 	         if( onlyredundant )
1830 	         {
1831 	            SCIP_Real vbound;
1832 	
1833 	            vbound = MIN(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i];  /*lint !e666*/
1834 	            if( SCIPsetIsFeasLT(set, vbound, ub) )
1835 	            {
1836 	               /* the variable bound is not redundant: keep it */
1837 	               if( removefromvar )
1838 	               {
1839 	                  if( newnvbds < i )
1840 	                  {
1841 	                     vars[newnvbds] = implvar;
1842 	                     coefs[newnvbds] = coefs[i];
1843 	                     constants[newnvbds] = constants[i];
1844 	                  }
1845 	                  newnvbds++;
1846 	               }
1847 	               continue;
1848 	            }
1849 	         }
1850 	
1851 	         /* remove the corresponding implication */
1852 	         if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1853 	         {
1854 	            SCIPsetDebugMsg(set, "deleting implication: <%s> == %d  ==>  <%s> <= %g\n",
1855 	               SCIPvarGetName(implvar), (coef < 0.0), SCIPvarGetName(var), MIN(coef, 0.0) + constants[i]);
1856 	            SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef < 0.0), var, SCIP_BOUNDTYPE_UPPER) );
1857 	         }
1858 	         if( coef < 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1859 	         {
1860 	            SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
1861 	               SCIPvarGetName(implvar), SCIPvarGetName(var));
1862 	            SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, TRUE) );
1863 	            implvar->closestvblpcount = -1;
1864 	            var->closestvblpcount = -1;
1865 	         }
1866 	         else if( coef > 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1867 	         {
1868 	            SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
1869 	               SCIPvarGetName(implvar), SCIPvarGetName(var));
1870 	            SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, FALSE) );
1871 	            implvar->closestvblpcount = -1;
1872 	            var->closestvblpcount = -1;
1873 	         }
1874 	      }
1875 	
1876 	      if( removefromvar )
1877 	      {
1878 	         /* update the number of variable bounds */
1879 	         SCIPvboundsShrink(&var->vubs, blkmem, newnvbds);
1880 	         var->closestvblpcount = -1;
1881 	      }
1882 	   }
1883 	
1884 	   /* remove the variable from all cliques */
1885 	   if( SCIPvarIsBinary(var) )
1886 	      SCIPcliquelistRemoveFromCliques(var->cliquelist, cliquetable, var, irrelevantvar);
1887 	
1888 	   /**@todo variable bounds like x <= b*z + d with z general integer are not removed from x's vbd arrays, because
1889 	    *       z has no link (like in the binary case) to x
1890 	    */
1891 	
1892 	   return SCIP_OKAY;
1893 	}
1894 	
1895 	/** sets the variable name */
1896 	static
1897 	SCIP_RETCODE varSetName(
1898 	   SCIP_VAR*             var,                /**< problem variable */
1899 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1900 	   SCIP_STAT*            stat,               /**< problem statistics, or NULL */
1901 	   const char*           name                /**< name of variable, or NULL for automatic name creation */
1902 	   )
1903 	{
1904 	   assert(blkmem != NULL);
1905 	   assert(var != NULL);
1906 	
1907 	   if( name == NULL )
1908 	   {
1909 	      char s[SCIP_MAXSTRLEN];
1910 	
1911 	      assert(stat != NULL);
1912 	
1913 	      (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "_var%d_", stat->nvaridx);
1914 	      SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, s, strlen(s)+1) );
1915 	   }
1916 	   else
1917 	   {
1918 	      SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, name, strlen(name)+1) );
1919 	   }
1920 	
1921 	   return SCIP_OKAY;
1922 	}
1923 	
1924 	
1925 	/** creates variable; if variable is of integral type, fractional bounds are automatically rounded; an integer variable
1926 	 *  with bounds zero and one is automatically converted into a binary variable
1927 	 */
1928 	static
1929 	SCIP_RETCODE varCreate(
1930 	   SCIP_VAR**            var,                /**< pointer to variable data */
1931 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1932 	   SCIP_SET*             set,                /**< global SCIP settings */
1933 	   SCIP_STAT*            stat,               /**< problem statistics */
1934 	   const char*           name,               /**< name of variable, or NULL for automatic name creation */
1935 	   SCIP_Real             lb,                 /**< lower bound of variable */
1936 	   SCIP_Real             ub,                 /**< upper bound of variable */
1937 	   SCIP_Real             obj,                /**< objective function value */
1938 	   SCIP_VARTYPE          vartype,            /**< type of variable */
1939 	   SCIP_Bool             initial,            /**< should var's column be present in the initial root LP? */
1940 	   SCIP_Bool             removable,          /**< is var's column removable from the LP (due to aging or cleanup)? */
1941 	   SCIP_DECL_VARCOPY     ((*varcopy)),       /**< copies variable data if wanted to subscip, or NULL */
1942 	   SCIP_DECL_VARDELORIG  ((*vardelorig)),    /**< frees user data of original variable, or NULL */
1943 	   SCIP_DECL_VARTRANS    ((*vartrans)),      /**< creates transformed user data by transforming original user data, or NULL */
1944 	   SCIP_DECL_VARDELTRANS ((*vardeltrans)),   /**< frees user data of transformed variable, or NULL */
1945 	   SCIP_VARDATA*         vardata             /**< user data for this specific variable */
1946 	   )
1947 	{
1948 	   int i;
1949 	
1950 	   assert(var != NULL);
1951 	   assert(blkmem != NULL);
1952 	   assert(stat != NULL);
1953 	
1954 	   /* adjust bounds of variable */
1955 	   lb = adjustedLb(set, vartype, lb);
1956 	   ub = adjustedUb(set, vartype, ub);
1957 	
1958 	   /* convert [0,1]-integers into binary variables and check that binary variables have correct bounds */
1959 	   if( (SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0))
1960 	      && (SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0)) )
1961 	   {
1962 	      if( vartype == SCIP_VARTYPE_INTEGER )
1963 	         vartype = SCIP_VARTYPE_BINARY;
1964 	   }
1965 	   else
1966 	   {
1967 	      if( vartype == SCIP_VARTYPE_BINARY )
1968 	      {
1969 	         SCIPerrorMessage("invalid bounds [%.2g,%.2g] for binary variable <%s>\n", lb, ub, name);
1970 	         return SCIP_INVALIDDATA;
1971 	      }
1972 	   }
1973 	
1974 	   assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0));
1975 	   assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0));
1976 	
1977 	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, var) );
1978 	
1979 	   /* set variable's name */
1980 	   SCIP_CALL( varSetName(*var, blkmem, stat, name) );
1981 	
1982 	#ifndef NDEBUG
1983 	   (*var)->scip = set->scip;
1984 	#endif
1985 	   (*var)->obj = obj;
1986 	   (*var)->unchangedobj = obj;
1987 	   (*var)->branchfactor = 1.0;
1988 	   (*var)->rootsol = 0.0;
1989 	   (*var)->bestrootsol = 0.0;
1990 	   (*var)->bestrootredcost = 0.0;
1991 	   (*var)->bestrootlpobjval = SCIP_INVALID;
1992 	   (*var)->relaxsol = 0.0;
1993 	   (*var)->nlpsol = 0.0;
1994 	   (*var)->primsolavg = 0.5 * (lb + ub);
1995 	   (*var)->conflictlb = SCIP_REAL_MIN;
1996 	   (*var)->conflictub = SCIP_REAL_MAX;
1997 	   (*var)->conflictrelaxedlb = (*var)->conflictlb;
1998 	   (*var)->conflictrelaxedub = (*var)->conflictub;
1999 	   (*var)->lazylb = -SCIPsetInfinity(set);
2000 	   (*var)->lazyub = SCIPsetInfinity(set);
2001 	   (*var)->glbdom.holelist = NULL;
2002 	   (*var)->glbdom.lb = lb;
2003 	   (*var)->glbdom.ub = ub;
2004 	   (*var)->locdom.holelist = NULL;
2005 	   (*var)->locdom.lb = lb;
2006 	   (*var)->locdom.ub = ub;
2007 	   (*var)->varcopy = varcopy;
2008 	   (*var)->vardelorig = vardelorig;
2009 	   (*var)->vartrans = vartrans;
2010 	   (*var)->vardeltrans = vardeltrans;
2011 	   (*var)->vardata = vardata;
2012 	   (*var)->parentvars = NULL;
2013 	   (*var)->negatedvar = NULL;
2014 	   (*var)->vlbs = NULL;
2015 	   (*var)->vubs = NULL;
2016 	   (*var)->implics = NULL;
2017 	   (*var)->cliquelist = NULL;
2018 	   (*var)->eventfilter = NULL;
2019 	   (*var)->lbchginfos = NULL;
2020 	   (*var)->ubchginfos = NULL;
2021 	   (*var)->index = stat->nvaridx;
2022 	   (*var)->probindex = -1;
2023 	   (*var)->pseudocandindex = -1;
2024 	   (*var)->eventqueueindexobj = -1;
2025 	   (*var)->eventqueueindexlb = -1;
2026 	   (*var)->eventqueueindexub = -1;
2027 	   (*var)->parentvarssize = 0;
2028 	   (*var)->nparentvars = 0;
2029 	   (*var)->nuses = 0;
2030 	   (*var)->branchpriority = 0;
2031 	   (*var)->branchdirection = SCIP_BRANCHDIR_AUTO; /*lint !e641*/
2032 	   (*var)->lbchginfossize = 0;
2033 	   (*var)->nlbchginfos = 0;
2034 	   (*var)->ubchginfossize = 0;
2035 	   (*var)->nubchginfos = 0;
2036 	   (*var)->conflictlbcount = 0;
2037 	   (*var)->conflictubcount = 0;
2038 	   (*var)->closestvlbidx = -1;
2039 	   (*var)->closestvubidx = -1;
2040 	   (*var)->closestvblpcount = -1;
2041 	   (*var)->initial = initial;
2042 	   (*var)->removable = removable;
2043 	   (*var)->deleted = FALSE;
2044 	   (*var)->donotaggr = FALSE;
2045 	   (*var)->donotmultaggr = FALSE;
2046 	   (*var)->vartype = vartype; /*lint !e641*/
2047 	   (*var)->pseudocostflag = FALSE;
2048 	   (*var)->eventqueueimpl = FALSE;
2049 	   (*var)->deletable = FALSE;
2050 	   (*var)->delglobalstructs = FALSE;
2051 	   (*var)->relaxationonly = FALSE;
2052 	
2053 	   for( i = 0; i < NLOCKTYPES; i++ )
2054 	   {
2055 	      (*var)->nlocksdown[i] = 0;
2056 	      (*var)->nlocksup[i] = 0;
2057 	   }
2058 	
2059 	   stat->nvaridx++;
2060 	
2061 	   /* create branching and inference history entries */
2062 	   SCIP_CALL( SCIPhistoryCreate(&(*var)->history, blkmem) );
2063 	   SCIP_CALL( SCIPhistoryCreate(&(*var)->historycrun, blkmem) );
2064 	
2065 	   /* the value based history is only created on demand */
2066 	   (*var)->valuehistory = NULL;
2067 	
2068 	   return SCIP_OKAY;
2069 	}
2070 	
2071 	/** creates and captures an original problem variable; an integer variable with bounds
2072 	 *  zero and one is automatically converted into a binary variable
2073 	 */
2074 	SCIP_RETCODE SCIPvarCreateOriginal(
2075 	   SCIP_VAR**            var,                /**< pointer to variable data */
2076 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2077 	   SCIP_SET*             set,                /**< global SCIP settings */
2078 	   SCIP_STAT*            stat,               /**< problem statistics */
2079 	   const char*           name,               /**< name of variable, or NULL for automatic name creation */
2080 	   SCIP_Real             lb,                 /**< lower bound of variable */
2081 	   SCIP_Real             ub,                 /**< upper bound of variable */
2082 	   SCIP_Real             obj,                /**< objective function value */
2083 	   SCIP_VARTYPE          vartype,            /**< type of variable */
2084 	   SCIP_Bool             initial,            /**< should var's column be present in the initial root LP? */
2085 	   SCIP_Bool             removable,          /**< is var's column removable from the LP (due to aging or cleanup)? */
2086 	   SCIP_DECL_VARDELORIG  ((*vardelorig)),    /**< frees user data of original variable, or NULL */
2087 	   SCIP_DECL_VARTRANS    ((*vartrans)),      /**< creates transformed user data by transforming original user data, or NULL */
2088 	   SCIP_DECL_VARDELTRANS ((*vardeltrans)),   /**< frees user data of transformed variable, or NULL */
2089 	   SCIP_DECL_VARCOPY     ((*varcopy)),       /**< copies variable data if wanted to subscip, or NULL */
2090 	   SCIP_VARDATA*         vardata             /**< user data for this specific variable */
2091 	   )
2092 	{
2093 	   assert(var != NULL);
2094 	   assert(blkmem != NULL);
2095 	   assert(stat != NULL);
2096 	
2097 	   /* create variable */
2098 	   SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2099 	         varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2100 	
2101 	   /* set variable status and data */
2102 	   (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2103 	   (*var)->data.original.origdom.holelist = NULL;
2104 	   (*var)->data.original.origdom.lb = lb;
2105 	   (*var)->data.original.origdom.ub = ub;
2106 	   (*var)->data.original.transvar = NULL;
2107 	
2108 	   /* capture variable */
2109 	   SCIPvarCapture(*var);
2110 	
2111 	   return SCIP_OKAY;
2112 	}
2113 	
2114 	/** creates and captures a loose variable belonging to the transformed problem; an integer variable with bounds
2115 	 *  zero and one is automatically converted into a binary variable
2116 	 */
2117 	SCIP_RETCODE SCIPvarCreateTransformed(
2118 	   SCIP_VAR**            var,                /**< pointer to variable data */
2119 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2120 	   SCIP_SET*             set,                /**< global SCIP settings */
2121 	   SCIP_STAT*            stat,               /**< problem statistics */
2122 	   const char*           name,               /**< name of variable, or NULL for automatic name creation */
2123 	   SCIP_Real             lb,                 /**< lower bound of variable */
2124 	   SCIP_Real             ub,                 /**< upper bound of variable */
2125 	   SCIP_Real             obj,                /**< objective function value */
2126 	   SCIP_VARTYPE          vartype,            /**< type of variable */
2127 	   SCIP_Bool             initial,            /**< should var's column be present in the initial root LP? */
2128 	   SCIP_Bool             removable,          /**< is var's column removable from the LP (due to aging or cleanup)? */
2129 	   SCIP_DECL_VARDELORIG  ((*vardelorig)),    /**< frees user data of original variable, or NULL */
2130 	   SCIP_DECL_VARTRANS    ((*vartrans)),      /**< creates transformed user data by transforming original user data, or NULL */
2131 	   SCIP_DECL_VARDELTRANS ((*vardeltrans)),   /**< frees user data of transformed variable, or NULL */
2132 	   SCIP_DECL_VARCOPY     ((*varcopy)),       /**< copies variable data if wanted to subscip, or NULL */
2133 	   SCIP_VARDATA*         vardata             /**< user data for this specific variable */
2134 	   )
2135 	{
2136 	   assert(var != NULL);
2137 	   assert(blkmem != NULL);
2138 	
2139 	   /* create variable */
2140 	   SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2141 	         varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2142 	
2143 	   /* create event filter for transformed variable */
2144 	   SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2145 	
2146 	   /* set variable status and data */
2147 	   (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2148 	
2149 	   /* capture variable */
2150 	   SCIPvarCapture(*var);
2151 	
2152 	   return SCIP_OKAY;   
2153 	}
2154 	
2155 	/** copies and captures a variable from source to target SCIP; an integer variable with bounds zero and one is
2156 	 *  automatically converted into a binary variable; in case the variable data cannot be copied the variable is not
2157 	 *  copied at all
2158 	 */
2159 	SCIP_RETCODE SCIPvarCopy(
2160 	   SCIP_VAR**            var,                /**< pointer to store the target variable */
2161 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2162 	   SCIP_SET*             set,                /**< global SCIP settings */
2163 	   SCIP_STAT*            stat,               /**< problem statistics */
2164 	   SCIP*                 sourcescip,         /**< source SCIP data structure */
2165 	   SCIP_VAR*             sourcevar,          /**< source variable */
2166 	   SCIP_HASHMAP*         varmap,             /**< a hashmap to store the mapping of source variables corresponding
2167 	                                              *   target variables */
2168 	   SCIP_HASHMAP*         consmap,            /**< a hashmap to store the mapping of source constraints to the corresponding
2169 	                                              *   target constraints */
2170 	   SCIP_Bool             global              /**< should global or local bounds be used? */
2171 	   )
2172 	{
2173 	   SCIP_VARDATA* targetdata;
2174 	   SCIP_RESULT result;
2175 	   SCIP_Real lb;
2176 	   SCIP_Real ub;
2177 	
2178 	   assert(set != NULL);
2179 	   assert(blkmem != NULL);
2180 	   assert(stat != NULL);
2181 	   assert(sourcescip != NULL);
2182 	   assert(sourcevar != NULL);
2183 	   assert(var != NULL);
2184 	   assert(set->stage == SCIP_STAGE_PROBLEM);
2185 	   assert(varmap != NULL);
2186 	   assert(consmap != NULL);
2187 	
2188 	   /** @todo copy hole lists */
2189 	   assert(global || SCIPvarGetHolelistLocal(sourcevar) == NULL);
2190 	   assert(!global || SCIPvarGetHolelistGlobal(sourcevar) == NULL);
2191 	
2192 	   result = SCIP_DIDNOTRUN;
2193 	   targetdata = NULL;
2194 	
2195 	   if( SCIPvarGetStatus(sourcevar) == SCIP_VARSTATUS_ORIGINAL )
2196 	   {
2197 	      lb = SCIPvarGetLbOriginal(sourcevar);
2198 	      ub = SCIPvarGetUbOriginal(sourcevar);
2199 	   }
2200 	   else
2201 	   {
2202 	      lb = global ? SCIPvarGetLbGlobal(sourcevar) : SCIPvarGetLbLocal(sourcevar);
2203 	      ub = global ? SCIPvarGetUbGlobal(sourcevar) : SCIPvarGetUbLocal(sourcevar);
2204 	   }
2205 	
2206 	   /* creates and captures the variable in the target SCIP and initialize callback methods and variable data to NULL */
2207 	   SCIP_CALL( SCIPvarCreateOriginal(var, blkmem, set, stat, SCIPvarGetName(sourcevar), 
2208 	         lb, ub, SCIPvarGetObj(sourcevar), SCIPvarGetType(sourcevar),
2209 	         SCIPvarIsInitial(sourcevar), SCIPvarIsRemovable(sourcevar), 
2210 	         NULL, NULL, NULL, NULL, NULL) );
2211 	   assert(*var != NULL);
2212 	
2213 	   /* directly copy donot(mult)aggr flag */
2214 	   (*var)->donotaggr = sourcevar->donotaggr;
2215 	   (*var)->donotmultaggr = sourcevar->donotmultaggr;
2216 	
2217 	   /* insert variable into mapping between source SCIP and the target SCIP */
2218 	   assert(!SCIPhashmapExists(varmap, sourcevar));
2219 	   SCIP_CALL( SCIPhashmapInsert(varmap, sourcevar, *var) );
2220 	
2221 	   /* in case there exists variable data and the variable data copy callback, try to copy variable data */
2222 	   if( sourcevar->vardata != NULL && sourcevar->varcopy != NULL )
2223 	   {
2224 	      SCIP_CALL( sourcevar->varcopy(set->scip, sourcescip, sourcevar, sourcevar->vardata, 
2225 	            varmap, consmap, (*var), &targetdata, &result) );
2226 	
2227 	      /* evaluate result */
2228 	      if( result != SCIP_DIDNOTRUN && result != SCIP_SUCCESS )
2229 	      {
2230 	         SCIPerrorMessage("variable data copying method returned invalid result <%d>\n", result);
2231 	         return SCIP_INVALIDRESULT;
2232 	      }
2233 	
2234 	      assert(targetdata == NULL || result == SCIP_SUCCESS);
2235 	
2236 	      /* if copying was successful, add the created variable data to the variable as well as all callback methods */
2237 	      if( result == SCIP_SUCCESS )
2238 	      {
2239 	         (*var)->varcopy = sourcevar->varcopy;
2240 	         (*var)->vardelorig = sourcevar->vardelorig;
2241 	         (*var)->vartrans = sourcevar->vartrans;
2242 	         (*var)->vardeltrans = sourcevar->vardeltrans;
2243 	         (*var)->vardata = targetdata;
2244 	      }
2245 	   }
2246 	
2247 	   /* we initialize histories of the variables by copying the source variable-information */
2248 	   if( set->history_allowtransfer )
2249 	   {
2250 	      SCIPvarMergeHistories((*var), sourcevar, stat);
2251 	   }
2252 	
2253 	   /* in case the copying was successfully, add the created variable data to the variable as well as all callback
2254 	    * methods 
2255 	    */
2256 	   if( result == SCIP_SUCCESS )
2257 	   {
2258 	      (*var)->varcopy = sourcevar->varcopy;
2259 	      (*var)->vardelorig = sourcevar->vardelorig;
2260 	      (*var)->vartrans = sourcevar->vartrans;
2261 	      (*var)->vardeltrans = sourcevar->vardeltrans;
2262 	      (*var)->vardata = targetdata;
2263 	   }
2264 	
2265 	   SCIPsetDebugMsg(set, "created copy <%s> of variable <%s>\n", SCIPvarGetName(*var), SCIPvarGetName(sourcevar));
2266 	
2267 	   return SCIP_OKAY;
2268 	}
2269 	
2270 	/** parse given string for a SCIP_Real bound */
2271 	static
2272 	SCIP_RETCODE parseValue(
2273 	   SCIP_SET*             set,                /**< global SCIP settings */
2274 	   const char*           str,                /**< string to parse */
2275 	   SCIP_Real*            value,              /**< pointer to store the parsed value */
2276 	   char**                endptr              /**< pointer to store the final string position if successfully parsed */
2277 	   )
2278 	{
2279 	   /* first check for infinity value */
2280 	   if( strncmp(str, "+inf", 4) == 0 )
2281 	   {
2282 	      *value = SCIPsetInfinity(set);
2283 	      (*endptr) = (char*)str + 4;
2284 	   }
2285 	   else if( strncmp(str, "-inf", 4) == 0 )
2286 	   {
2287 	      *value = -SCIPsetInfinity(set);
2288 	      (*endptr) = (char*)str + 4;
2289 	   }
2290 	   else
2291 	   {
2292 	      if( !SCIPstrToRealValue(str, value, endptr) )
2293 	      {
2294 	         SCIPerrorMessage("expected value: %s.\n", str);
2295 	         return SCIP_READERROR;
2296 	      }
2297 	   }
2298 	
2299 	   return SCIP_OKAY;
2300 	}
2301 	
2302 	/** parse the characters as bounds */
2303 	static
2304 	SCIP_RETCODE parseBounds(
2305 	   SCIP_SET*             set,                /**< global SCIP settings */
2306 	   const char*           str,                /**< string to parse */
2307 	   char*                 type,               /**< bound type (global, local, or lazy) */
2308 	   SCIP_Real*            lb,                 /**< pointer to store the lower bound */
2309 	   SCIP_Real*            ub,                 /**< pointer to store the upper bound */
2310 	   char**                endptr              /**< pointer to store the final string position if successfully parsed (or NULL if an error occured) */
2311 	   )
2312 	{
2313 	   char token[SCIP_MAXSTRLEN];
2314 	   char* tmpend;
2315 	
2316 	   SCIPsetDebugMsg(set, "parsing bounds: '%s'\n", str);
2317 	
2318 	   /* get bound type */
2319 	   SCIPstrCopySection(str, ' ', ' ', type, SCIP_MAXSTRLEN, endptr);
2320 	   if ( *endptr == str
2321 	        || ( strncmp(type, "original", 8) != 0 && strncmp(type, "global", 6) != 0 && strncmp(type, "local", 5) != 0 && strncmp(type, "lazy", 4) != 0 ) )
2322 	   {
2323 	      SCIPsetDebugMsg(set, "unkown bound type\n");
2324 	      *endptr = NULL;
2325 	      return SCIP_OKAY;
2326 	   }
2327 	
2328 	   SCIPsetDebugMsg(set, "parsed bound type <%s>\n", type);
2329 	
2330 	   /* get lower bound */
2331 	   SCIPstrCopySection(str, '[', ',', token, SCIP_MAXSTRLEN, endptr);
2332 	   str = *endptr;
2333 	   SCIP_CALL( parseValue(set, token, lb, &tmpend) );
2334 	
2335 	   /* get upper bound */
2336 	   SCIP_CALL( parseValue(set, str, ub, endptr) );
2337 	
2338 	   SCIPsetDebugMsg(set, "parsed bounds: [%g,%g]\n", *lb, *ub);
2339 	
2340 	   /* skip end of bounds */
2341 	   while ( **endptr != '\0' && (**endptr == ']' || **endptr == ',') )
2342 	      ++(*endptr);
2343 	
2344 	   return SCIP_OKAY;
2345 	}
2346 	
2347 	/** parses a given string for a variable informations */
2348 	static
2349 	SCIP_RETCODE varParse(
2350 	   SCIP_SET*             set,                /**< global SCIP settings */
2351 	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
2352 	   const char*           str,                /**< string to parse */
2353 	   char*                 name,               /**< pointer to store the variable name */
2354 	   SCIP_Real*            lb,                 /**< pointer to store the lower bound */
2355 	   SCIP_Real*            ub,                 /**< pointer to store the upper bound */
2356 	   SCIP_Real*            obj,                /**< pointer to store the objective coefficient */
2357 	   SCIP_VARTYPE*         vartype,            /**< pointer to store the variable type */
2358 	   SCIP_Real*            lazylb,             /**< pointer to store if the lower bound is lazy */
2359 	   SCIP_Real*            lazyub,             /**< pointer to store if the upper bound is lazy */
2360 	   SCIP_Bool             local,              /**< should the local bound be applied */
2361 	   char**                endptr,             /**< pointer to store the final string position if successfully */
2362 	   SCIP_Bool*            success             /**< pointer store if the paring process was successful */
2363 	   )
2364 	{
2365 	   SCIP_Real parsedlb;
2366 	   SCIP_Real parsedub;
2367 	   char token[SCIP_MAXSTRLEN];
2368 	   char* strptr;
2369 	   int i;
2370 	
2371 	   assert(lb != NULL);
2372 	   assert(ub != NULL);
2373 	   assert(obj != NULL);
2374 	   assert(vartype != NULL);
2375 	   assert(lazylb != NULL);
2376 	   assert(lazyub != NULL);
2377 	   assert(success != NULL);
2378 	
2379 	   (*success) = TRUE;
2380 	
2381 	   /* copy variable type */
2382 	   SCIPstrCopySection(str, '[', ']', token, SCIP_MAXSTRLEN, endptr);
2383 	   assert(*endptr != str);
2384 	   SCIPsetDebugMsg(set, "parsed variable type <%s>\n", token);
2385 	
2386 	   /* get variable type */
2387 	   if( strncmp(token, "binary", 3) == 0 )
2388 	      (*vartype) = SCIP_VARTYPE_BINARY;
2389 	   else if( strncmp(token, "integer", 3) == 0 )
2390 	      (*vartype) = SCIP_VARTYPE_INTEGER;
2391 	   else if( strncmp(token, "implicit", 3) == 0 )
2392 	      (*vartype) = SCIP_VARTYPE_IMPLINT;
2393 	   else if( strncmp(token, "continuous", 3) == 0 )
2394 	      (*vartype) = SCIP_VARTYPE_CONTINUOUS;
2395 	   else
2396 	   {
2397 	      SCIPmessagePrintWarning(messagehdlr, "unknown variable type\n");
2398 	      (*success) = FALSE;
2399 	      return SCIP_OKAY;
2400 	   }
2401 	
2402 	   /* move string pointer behind variable type */
2403 	   str = *endptr;
2404 	
2405 	   /* get variable name */
2406 	   SCIPstrCopySection(str, '<', '>', name, SCIP_MAXSTRLEN, endptr);
2407 	   assert(*endptr != str);
2408 	   SCIPsetDebugMsg(set, "parsed variable name <%s>\n", name);
2409 	
2410 	   /* move string pointer behind variable name */
2411 	   str = *endptr;
2412 	
2413 	   /* cut out objective coefficient */
2414 	   SCIPstrCopySection(str, '=', ',', token, SCIP_MAXSTRLEN, endptr);
2415 	
2416 	   /* move string pointer behind objective coefficient */
2417 	   str = *endptr;
2418 	
2419 	   /* get objective coefficient */
2420 	   if( !SCIPstrToRealValue(token, obj, endptr) )
2421 	   {
2422 	      *endptr = NULL;
2423 	      return SCIP_READERROR;
2424 	   }
2425 	
2426 	   SCIPsetDebugMsg(set, "parsed objective coefficient <%g>\n", *obj);
2427 	
2428 	   /* parse global/original bounds */
2429 	   SCIP_CALL( parseBounds(set, str, token, lb, ub, endptr) );
2430 	   if ( *endptr == NULL )
2431 	   {
2432 	      SCIPerrorMessage("Expected bound type: %s.\n", token);
2433 	      return SCIP_READERROR;
2434 	   }
2435 	   assert(strncmp(token, "global", 6) == 0 || strncmp(token, "original", 8) == 0);
2436 	
2437 	   /* initialize the lazy bound */
2438 	   *lazylb = -SCIPsetInfinity(set);
2439 	   *lazyub =  SCIPsetInfinity(set);
2440 	
2441 	   /* store pointer */
2442 	   strptr = *endptr;
2443 	
2444 	   /* possibly parse optional local and lazy bounds */
2445 	   for( i = 0; i < 2 && *endptr != NULL && **endptr != '\0'; ++i )
2446 	   {
2447 	      /* start after previous bounds */
2448 	      strptr = *endptr;
2449 	
2450 	      /* parse global bounds */
2451 	      SCIP_CALL( parseBounds(set, strptr, token, &parsedlb, &parsedub, endptr) );
2452 	
2453 	      /* stop if parsing of bounds failed */
2454 	      if( *endptr == NULL )
2455 	         break;
2456 	
2457 	      if( strncmp(token, "local", 5) == 0 && local )
2458 	      {
2459 	         *lb = parsedlb;
2460 	         *ub = parsedub;
2461 	      }
2462 	      else if( strncmp(token, "lazy", 4) == 0 )
2463 	      {
2464 	         *lazylb = parsedlb;
2465 	         *lazyub = parsedub;
2466 	      }
2467 	   }
2468 	
2469 	   /* restore pointer */
2470 	   if ( *endptr == NULL )
2471 	      *endptr = strptr;
2472 	
2473 	   /* check bounds for binary variables */
2474 	   if ( (*vartype) == SCIP_VARTYPE_BINARY )
2475 	   {
2476 	      if ( SCIPsetIsLT(set, *lb, 0.0) || SCIPsetIsGT(set, *ub, 1.0) )
2477 	      {
2478 	         SCIPerrorMessage("Parsed invalid bounds for binary variable <%s>: [%f, %f].\n", name, *lb, *ub);
2479 	         return SCIP_READERROR;
2480 	      }
2481 	      if ( !SCIPsetIsInfinity(set, -(*lazylb)) && !SCIPsetIsInfinity(set, *lazyub) && 
2482 	           ( SCIPsetIsLT(set, *lazylb, 0.0) || SCIPsetIsGT(set, *lazyub, 1.0) ) )
2483 	      {
2484 	         SCIPerrorMessage("Parsed invalid lazy bounds for binary variable <%s>: [%f, %f].\n", name, *lazylb, *lazyub);
2485 	         return SCIP_READERROR;
2486 	      }
2487 	   }
2488 	
2489 	   return SCIP_OKAY;
2490 	}
2491 	
2492 	/** parses variable information (in cip format) out of a string; if the parsing process was successful an original
2493 	 *  variable is created and captured; if variable is of integral type, fractional bounds are automatically rounded; an
2494 	 *  integer variable with bounds zero and one is automatically converted into a binary variable
2495 	 */
2496 	SCIP_RETCODE SCIPvarParseOriginal(
2497 	   SCIP_VAR**            var,                /**< pointer to variable data */
2498 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2499 	   SCIP_SET*             set,                /**< global SCIP settings */
2500 	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
2501 	   SCIP_STAT*            stat,               /**< problem statistics */
2502 	   const char*           str,                /**< string to parse */
2503 	   SCIP_Bool             initial,            /**< should var's column be present in the initial root LP? */
2504 	   SCIP_Bool             removable,          /**< is var's column removable from the LP (due to aging or cleanup)? */
2505 	   SCIP_DECL_VARCOPY     ((*varcopy)),       /**< copies variable data if wanted to subscip, or NULL */
2506 	   SCIP_DECL_VARDELORIG  ((*vardelorig)),    /**< frees user data of original variable */
2507 	   SCIP_DECL_VARTRANS    ((*vartrans)),      /**< creates transformed user data by transforming original user data */
2508 	   SCIP_DECL_VARDELTRANS ((*vardeltrans)),   /**< frees user data of transformed variable */
2509 	   SCIP_VARDATA*         vardata,            /**< user data for this specific variable */
2510 	   char**                endptr,             /**< pointer to store the final string position if successfully */
2511 	   SCIP_Bool*            success             /**< pointer store if the paring process was successful */
2512 	   )
2513 	{
2514 	   char name[SCIP_MAXSTRLEN];
2515 	   SCIP_Real lb;
2516 	   SCIP_Real ub;
2517 	   SCIP_Real obj;
2518 	   SCIP_VARTYPE vartype;
2519 	   SCIP_Real lazylb;
2520 	   SCIP_Real lazyub;
2521 	
2522 	   assert(var != NULL);
2523 	   assert(blkmem != NULL);
2524 	   assert(stat != NULL);
2525 	   assert(endptr != NULL);
2526 	   assert(success != NULL);
2527 	
2528 	   /* parse string in cip format for variable information */
2529 	   SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, FALSE, endptr, success) );
2530 	
2531 	   if( *success ) /*lint !e774*/
2532 	   {
2533 	      /* create variable */
2534 	      SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2535 	            varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2536 	
2537 	      /* set variable status and data */
2538 	      (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2539 	      (*var)->data.original.origdom.holelist = NULL;
2540 	      (*var)->data.original.origdom.lb = lb;
2541 	      (*var)->data.original.origdom.ub = ub;
2542 	      (*var)->data.original.transvar = NULL;
2543 	
2544 	      /* set lazy status of variable bounds */
2545 	      (*var)->lazylb = lazylb;
2546 	      (*var)->lazyub = lazyub;
2547 	
2548 	      /* capture variable */
2549 	      SCIPvarCapture(*var);
2550 	   }
2551 	
2552 	   return SCIP_OKAY;
2553 	}
2554 	
2555 	/** parses variable information (in cip format) out of a string; if the parsing process was successful a loose variable
2556 	 *  belonging to the transformed problem is created and captured; if variable is of integral type, fractional bounds are
2557 	 *  automatically rounded; an integer variable with bounds zero and one is automatically converted into a binary
2558 	 *  variable
2559 	 */
2560 	SCIP_RETCODE SCIPvarParseTransformed(
2561 	   SCIP_VAR**            var,                /**< pointer to variable data */
2562 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2563 	   SCIP_SET*             set,                /**< global SCIP settings */
2564 	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
2565 	   SCIP_STAT*            stat,               /**< problem statistics */
2566 	   const char*           str,                /**< string to parse */
2567 	   SCIP_Bool             initial,            /**< should var's column be present in the initial root LP? */
2568 	   SCIP_Bool             removable,          /**< is var's column removable from the LP (due to aging or cleanup)? */
2569 	   SCIP_DECL_VARCOPY     ((*varcopy)),       /**< copies variable data if wanted to subscip, or NULL */
2570 	   SCIP_DECL_VARDELORIG  ((*vardelorig)),    /**< frees user data of original variable */
2571 	   SCIP_DECL_VARTRANS    ((*vartrans)),      /**< creates transformed user data by transforming original user data */
2572 	   SCIP_DECL_VARDELTRANS ((*vardeltrans)),   /**< frees user data of transformed variable */
2573 	   SCIP_VARDATA*         vardata,            /**< user data for this specific variable */
2574 	   char**                endptr,             /**< pointer to store the final string position if successfully */
2575 	   SCIP_Bool*            success             /**< pointer store if the paring process was successful */
2576 	   )
2577 	{
2578 	   char name[SCIP_MAXSTRLEN];
2579 	   SCIP_Real lb;
2580 	   SCIP_Real ub;
2581 	   SCIP_Real obj;
2582 	   SCIP_VARTYPE vartype;
2583 	   SCIP_Real lazylb;
2584 	   SCIP_Real lazyub;
2585 	
2586 	   assert(var != NULL);
2587 	   assert(blkmem != NULL);
2588 	   assert(endptr != NULL);
2589 	   assert(success != NULL);
2590 	
2591 	   /* parse string in cip format for variable information */
2592 	   SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, TRUE, endptr, success) );
2593 	
2594 	   if( *success ) /*lint !e774*/
2595 	   {
2596 	      /* create variable */
2597 	      SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2598 	            varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2599 	
2600 	      /* create event filter for transformed variable */
2601 	      SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2602 	
2603 	      /* set variable status and data */
2604 	      (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2605 	
2606 	      /* set lazy status of variable bounds */
2607 	      (*var)->lazylb = lazylb;
2608 	      (*var)->lazyub = lazyub;
2609 	
2610 	      /* capture variable */
2611 	      SCIPvarCapture(*var);
2612 	   }
2613 	
2614 	   return SCIP_OKAY;   
2615 	}
2616 	
2617 	/** ensures, that parentvars array of var can store at least num entries */
2618 	static
2619 	SCIP_RETCODE varEnsureParentvarsSize(
2620 	   SCIP_VAR*             var,                /**< problem variable */
2621 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2622 	   SCIP_SET*             set,                /**< global SCIP settings */
2623 	   int                   num                 /**< minimum number of entries to store */
2624 	   )
2625 	{
2626 	   assert(var->nparentvars <= var->parentvarssize);
2627 	
2628 	   if( num > var->parentvarssize )
2629 	   {
2630 	      int newsize;
2631 	
2632 	      newsize = SCIPsetCalcMemGrowSize(set, num);
2633 	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->parentvars, var->parentvarssize, newsize) );
2634 	      var->parentvarssize = newsize;
2635 	   }
2636 	   assert(num <= var->parentvarssize);
2637 	
2638 	   return SCIP_OKAY;
2639 	}
2640 	
2641 	/** adds variable to parent list of a variable and captures parent variable */
2642 	static
2643 	SCIP_RETCODE varAddParent(
2644 	   SCIP_VAR*             var,                /**< variable to add parent to */
2645 	   BMS_BLKMEM*           blkmem,             /**< block memory of transformed problem */
2646 	   SCIP_SET*             set,                /**< global SCIP settings */
2647 	   SCIP_VAR*             parentvar           /**< parent variable to add */
2648 	   )
2649 	{
2650 	   assert(var != NULL);
2651 	   assert(parentvar != NULL);
2652 	
2653 	   /* the direct original counterpart must be stored as first parent */
2654 	   assert(var->nparentvars == 0 || SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL);
2655 	
2656 	   SCIPsetDebugMsg(set, "adding parent <%s>[%p] to variable <%s>[%p] in slot %d\n",
2657 	      parentvar->name, (void*)parentvar, var->name, (void*)var, var->nparentvars);
2658 	
2659 	   SCIP_CALL( varEnsureParentvarsSize(var, blkmem, set, var->nparentvars+1) );
2660 	
2661 	   var->parentvars[var->nparentvars] = parentvar;
2662 	   var->nparentvars++;
2663 	
2664 	   SCIPvarCapture(parentvar);
2665 	
2666 	   return SCIP_OKAY;
2667 	}
2668 	
2669 	/** deletes and releases all variables from the parent list of a variable, frees the memory of parents array */
2670 	static
2671 	SCIP_RETCODE varFreeParents(
2672 	   SCIP_VAR**            var,                /**< pointer to variable */
2673 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2674 	   SCIP_SET*             set,                /**< global SCIP settings */
2675 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue (or NULL, if it's an original variable) */
2676 	   SCIP_LP*              lp                  /**< current LP data (or NULL, if it's an original variable) */
2677 	   )
2678 	{
2679 	   SCIP_VAR* parentvar;
2680 	   int i;
2681 	
2682 	   SCIPsetDebugMsg(set, "free parents of <%s>\n", (*var)->name);
2683 	
2684 	   /* release the parent variables and remove the link from the parent variable to the child */
2685 	   for( i = 0; i < (*var)->nparentvars; ++i )
2686 	   {
2687 	      assert((*var)->parentvars != NULL);
2688 	      parentvar = (*var)->parentvars[i];
2689 	      assert(parentvar != NULL);
2690 	
2691 	      switch( SCIPvarGetStatus(parentvar) )
2692 	      {
2693 	      case SCIP_VARSTATUS_ORIGINAL:
2694 	         assert(parentvar->data.original.transvar == *var);
2695 	         assert(&parentvar->data.original.transvar != var);
2696 	         parentvar->data.original.transvar = NULL;
2697 	         break;
2698 	
2699 	      case SCIP_VARSTATUS_AGGREGATED:
2700 	         assert(parentvar->data.aggregate.var == *var);
2701 	         assert(&parentvar->data.aggregate.var != var);
2702 	         parentvar->data.aggregate.var = NULL;
2703 	         break;
2704 	
2705 	#if 0
2706 	      /* The following code is unclear: should the current variable be removed from its parents? */
2707 	      case SCIP_VARSTATUS_MULTAGGR:
2708 	         assert(parentvar->data.multaggr.vars != NULL);
2709 	         for( v = 0; v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] != *var; ++v )
2710 	         {}
2711 	         assert(v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] == *var);
2712 	         if( v < parentvar->data.multaggr.nvars-1 )
2713 	         {
2714 	            parentvar->data.multaggr.vars[v] = parentvar->data.multaggr.vars[parentvar->data.multaggr.nvars-1];
2715 	            parentvar->data.multaggr.scalars[v] = parentvar->data.multaggr.scalars[parentvar->data.multaggr.nvars-1];
2716 	         }
2717 	         parentvar->data.multaggr.nvars--;
2718 	         break;
2719 	#endif
2720 	
2721 	      case SCIP_VARSTATUS_NEGATED:
2722 	         assert(parentvar->negatedvar == *var);
2723 	         assert((*var)->negatedvar == parentvar);
2724 	         parentvar->negatedvar = NULL;
2725 	         (*var)->negatedvar = NULL;
2726 	         break;
2727 	
2728 	      default:
2729 	         SCIPerrorMessage("parent variable is neither ORIGINAL, AGGREGATED nor NEGATED\n");
2730 	         return SCIP_INVALIDDATA;
2731 	      }  /*lint !e788*/
2732 	
2733 	      SCIP_CALL( SCIPvarRelease(&(*var)->parentvars[i], blkmem, set, eventqueue, lp) );
2734 	   }
2735 	
2736 	   /* free parentvars array */
2737 	   BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->parentvars, (*var)->parentvarssize);
2738 	
2739 	   return SCIP_OKAY;
2740 	}
2741 	
2742 	/** frees a variable */
2743 	static
2744 	SCIP_RETCODE varFree(
2745 	   SCIP_VAR**            var,                /**< pointer to variable */
2746 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2747 	   SCIP_SET*             set,                /**< global SCIP settings */
2748 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue (may be NULL, if it's not a column variable) */
2749 	   SCIP_LP*              lp                  /**< current LP data (may be NULL, if it's not a column variable) */
2750 	   )
2751 	{
2752 	   assert(var != NULL);
2753 	   assert(*var != NULL);
2754 	   assert(SCIPvarGetStatus(*var) != SCIP_VARSTATUS_COLUMN || &(*var)->data.col->var != var);
2755 	   assert((*var)->nuses == 0);
2756 	   assert((*var)->probindex == -1);
2757 	   assert((*var)->nlocksup[SCIP_LOCKTYPE_MODEL] == 0);
2758 	   assert((*var)->nlocksdown[SCIP_LOCKTYPE_MODEL] == 0);
2759 	
2760 	   SCIPsetDebugMsg(set, "free variable <%s> with status=%d\n", (*var)->name, SCIPvarGetStatus(*var));
2761 	
2762 	   switch( SCIPvarGetStatus(*var) )
2763 	   {
2764 	   case SCIP_VARSTATUS_ORIGINAL:
2765 	      assert((*var)->data.original.transvar == NULL); /* cannot free variable, if transformed variable is still existing */
2766 	      holelistFree(&(*var)->data.original.origdom.holelist, blkmem);
2767 	      assert((*var)->data.original.origdom.holelist == NULL);
2768 	      break;
2769 	   case SCIP_VARSTATUS_LOOSE:
2770 	      break;
2771 	   case SCIP_VARSTATUS_COLUMN:
2772 	      SCIP_CALL( SCIPcolFree(&(*var)->data.col, blkmem, set, eventqueue, lp) );  /* free corresponding LP column */
2773 	      break;
2774 	   case SCIP_VARSTATUS_FIXED:
2775 	   case SCIP_VARSTATUS_AGGREGATED:
2776 	      break;
2777 	   case SCIP_VARSTATUS_MULTAGGR:
2778 	      BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.vars, (*var)->data.multaggr.varssize);
2779 	      BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.scalars, (*var)->data.multaggr.varssize);
2780 	      break;
2781 	   case SCIP_VARSTATUS_NEGATED:
2782 	      break;
2783 	   default:
2784 	      SCIPerrorMessage("unknown variable status\n");
2785 	      return SCIP_INVALIDDATA;
2786 	   }
2787 	
2788 	   /* release all parent variables and free the parentvars array */
2789 	   SCIP_CALL( varFreeParents(var, blkmem, set, eventqueue, lp) );
2790 	
2791 	   /* free user data */
2792 	   if( SCIPvarGetStatus(*var) == SCIP_VARSTATUS_ORIGINAL )
2793 	   {
2794 	      if( (*var)->vardelorig != NULL )
2795 	      {
2796 	         SCIP_CALL( (*var)->vardelorig(set->scip, *var, &(*var)->vardata) );
2797 	      }
2798 	   }
2799 	   else
2800 	   {
2801 	      if( (*var)->vardeltrans != NULL )
2802 	      {
2803 	         SCIP_CALL( (*var)->vardeltrans(set->scip, *var, &(*var)->vardata) );
2804 	      }
2805 	   }
2806 	
2807 	   /* free event filter */
2808 	   if( (*var)->eventfilter != NULL )
2809 	   {
2810 	      SCIP_CALL( SCIPeventfilterFree(&(*var)->eventfilter, blkmem, set) );
2811 	   }
2812 	   assert((*var)->eventfilter == NULL);
2813 	
2814 	   /* free hole lists */
2815 	   holelistFree(&(*var)->glbdom.holelist, blkmem);
2816 	   holelistFree(&(*var)->locdom.holelist, blkmem);
2817 	   assert((*var)->glbdom.holelist == NULL);
2818 	   assert((*var)->locdom.holelist == NULL);
2819 	
2820 	   /* free variable bounds data structures */
2821 	   SCIPvboundsFree(&(*var)->vlbs, blkmem);
2822 	   SCIPvboundsFree(&(*var)->vubs, blkmem);
2823 	
2824 	   /* free implications data structures */
2825 	   SCIPimplicsFree(&(*var)->implics, blkmem);
2826 	
2827 	   /* free clique list data structures */
2828 	   SCIPcliquelistFree(&(*var)->cliquelist, blkmem);
2829 	
2830 	   /* free bound change information arrays */
2831 	   BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->lbchginfos, (*var)->lbchginfossize);
2832 	   BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->ubchginfos, (*var)->ubchginfossize);
2833 	
2834 	   /* free branching and inference history entries */
2835 	   SCIPhistoryFree(&(*var)->history, blkmem);
2836 	   SCIPhistoryFree(&(*var)->historycrun, blkmem);
2837 	   SCIPvaluehistoryFree(&(*var)->valuehistory, blkmem);
2838 	
2839 	   /* free variable data structure */
2840 	   BMSfreeBlockMemoryArray(blkmem, &(*var)->name, strlen((*var)->name)+1);
2841 	   BMSfreeBlockMemory(blkmem, var);
2842 	
2843 	   return SCIP_OKAY;
2844 	}
2845 	
2846 	/** increases usage counter of variable */
2847 	void SCIPvarCapture(
2848 	   SCIP_VAR*             var                 /**< variable */
2849 	   )
2850 	{
2851 	   assert(var != NULL);
2852 	   assert(var->nuses >= 0);
2853 	
2854 	   SCIPdebugMessage("capture variable <%s> with nuses=%d\n", var->name, var->nuses);
2855 	   var->nuses++;
2856 	
2857 	#ifdef DEBUGUSES_VARNAME
2858 	   if( strcmp(var->name, DEBUGUSES_VARNAME) == 0
2859 	#ifdef DEBUGUSES_PROBNAME
2860 	      && ((var->scip->transprob != NULL && strcmp(SCIPprobGetName(var->scip->transprob), DEBUGUSES_PROBNAME) == 0) ||
2861 	          strcmp(SCIPprobGetName(var->scip->origprob), DEBUGUSES_PROBNAME) == 0)
2862 	#endif
2863 	   )
2864 	   {
2865 	      printf("Captured variable " DEBUGUSES_VARNAME " in SCIP %p, now %d uses; captured at\n", (void*)var->scip, var->nuses);
2866 	      print_backtrace();
2867 	   }
2868 	#endif
2869 	}
2870 	
2871 	/** decreases usage counter of variable, and frees memory if necessary */
2872 	SCIP_RETCODE SCIPvarRelease(
2873 	   SCIP_VAR**            var,                /**< pointer to variable */
2874 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2875 	   SCIP_SET*             set,                /**< global SCIP settings */
2876 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
2877 	   SCIP_LP*              lp                  /**< current LP data (or NULL, if it's an original variable) */
2878 	   )
2879 	{
2880 	   assert(var != NULL);
2881 	   assert(*var != NULL);
2882 	   assert((*var)->nuses >= 1);
2883 	   assert(blkmem != NULL);
2884 	   assert((*var)->scip == set->scip);
2885 	
2886 	   SCIPsetDebugMsg(set, "release variable <%s> with nuses=%d\n", (*var)->name, (*var)->nuses);
2887 	   (*var)->nuses--;
2888 	
2889 	#ifdef DEBUGUSES_VARNAME
2890 	   if( strcmp((*var)->name, DEBUGUSES_VARNAME) == 0
2891 	#ifdef DEBUGUSES_PROBNAME
2892 	      && (((*var)->scip->transprob != NULL && strcmp(SCIPprobGetName((*var)->scip->transprob), DEBUGUSES_PROBNAME) == 0) ||
2893 	          strcmp(SCIPprobGetName((*var)->scip->origprob), DEBUGUSES_PROBNAME) == 0)
2894 	#endif
2895 	   )
2896 	   {
2897 	      printf("Released variable " DEBUGUSES_VARNAME " in SCIP %p, now %d uses; released at\n", (void*)(*var)->scip, (*var)->nuses);
2898 	      print_backtrace();
2899 	   }
2900 	#endif
2901 	
2902 	   if( (*var)->nuses == 0 )
2903 	   {
2904 	      SCIP_CALL( varFree(var, blkmem, set, eventqueue, lp) );
2905 	   }
2906 	
2907 	   *var = NULL;
2908 	
2909 	   return SCIP_OKAY;
2910 	}
2911 	
2912 	/** change variable name */
2913 	SCIP_RETCODE SCIPvarChgName(
2914 	   SCIP_VAR*             var,                /**< problem variable */
2915 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2916 	   const char*           name                /**< name of variable */
2917 	   )
2918 	{
2919 	   assert(name != NULL);
2920 	
2921 	   /* remove old variable name */
2922 	   BMSfreeBlockMemoryArray(blkmem, &var->name, strlen(var->name)+1);
2923 	
2924 	   /* set new variable name */
2925 	   SCIP_CALL( varSetName(var, blkmem, NULL, name) );
2926 	
2927 	   return SCIP_OKAY;
2928 	}
2929 	
2930 	/** initializes variable data structure for solving */
2931 	void SCIPvarInitSolve(
2932 	   SCIP_VAR*             var                 /**< problem variable */
2933 	   )
2934 	{
2935 	   assert(var != NULL);
2936 	
2937 	   SCIPhistoryReset(var->historycrun);
2938 	   var->conflictlbcount = 0;
2939 	   var->conflictubcount = 0;
2940 	}
2941 	
2942 	/** outputs the given bounds into the file stream */
2943 	static
2944 	void printBounds(
2945 	   SCIP_SET*             set,                /**< global SCIP settings */
2946 	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
2947 	   FILE*                 file,               /**< output file (or NULL for standard output) */
2948 	   SCIP_Real             lb,                 /**< lower bound */
2949 	   SCIP_Real             ub,                 /**< upper bound */
2950 	   const char*           name                /**< bound type name */
2951 	   )
2952 	{
2953 	   assert(set != NULL);
2954 	
2955 	   SCIPmessageFPrintInfo(messagehdlr, file, ", %s=", name);
2956 	   if( SCIPsetIsInfinity(set, lb) )
2957 	      SCIPmessageFPrintInfo(messagehdlr, file, "[+inf,");
2958 	   else if( SCIPsetIsInfinity(set, -lb) )
2959 	      SCIPmessageFPrintInfo(messagehdlr, file, "[-inf,");
2960 	   else
2961 	      SCIPmessageFPrintInfo(messagehdlr, file, "[%.15g,", lb);
2962 	   if( SCIPsetIsInfinity(set, ub) )
2963 	      SCIPmessageFPrintInfo(messagehdlr, file, "+inf]");
2964 	   else if( SCIPsetIsInfinity(set, -ub) )
2965 	      SCIPmessageFPrintInfo(messagehdlr, file, "-inf]");
2966 	   else
2967 	      SCIPmessageFPrintInfo(messagehdlr, file, "%.15g]", ub);
2968 	}
2969 	
2970 	/** prints hole list to file stream */
2971 	static
2972 	void printHolelist(
2973 	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
2974 	   FILE*                 file,               /**< output file (or NULL for standard output) */
2975 	   SCIP_HOLELIST*        holelist,           /**< hole list pointer to hole of interest */
2976 	   const char*           name                /**< hole type name */
2977 	   )
2978 	{  /*lint --e{715}*/
2979 	   SCIP_Real left;
2980 	   SCIP_Real right;
2981 	
2982 	   if( holelist == NULL )
2983 	      return;
2984 	
2985 	   left = SCIPholelistGetLeft(holelist);
2986 	   right = SCIPholelistGetRight(holelist);
2987 	
2988 	   /* display first hole */
2989 	   SCIPmessageFPrintInfo(messagehdlr, file, ", %s=(%g,%g)", name, left, right);
2990 	   holelist = SCIPholelistGetNext(holelist);
2991 	
2992 	   while(holelist != NULL  )
2993 	   {
2994 	      left = SCIPholelistGetLeft(holelist);
2995 	      right = SCIPholelistGetRight(holelist);
2996 	
2997 	      /* display hole */
2998 	      SCIPmessageFPrintInfo(messagehdlr, file, "(%g,%g)", left, right);
2999 	
3000 	      /* get next hole */
3001 	      holelist = SCIPholelistGetNext(holelist);
3002 	   }
3003 	}
3004 	
3005 	/** outputs variable information into file stream */
3006 	SCIP_RETCODE SCIPvarPrint(
3007 	   SCIP_VAR*             var,                /**< problem variable */
3008 	   SCIP_SET*             set,                /**< global SCIP settings */
3009 	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
3010 	   FILE*                 file                /**< output file (or NULL for standard output) */
3011 	   )
3012 	{
3013 	   SCIP_HOLELIST* holelist;
3014 	   SCIP_Real lb;
3015 	   SCIP_Real ub;
3016 	   int i;
3017 	
3018 	   assert(var != NULL);
3019 	   assert(var->scip == set->scip);
3020 	
3021 	   /* type of variable */
3022 	   switch( SCIPvarGetType(var) )
3023 	   {
3024 	   case SCIP_VARTYPE_BINARY:
3025 	      SCIPmessageFPrintInfo(messagehdlr, file, "  [binary]");
3026 	      break;
3027 	   case SCIP_VARTYPE_INTEGER:
3028 	      SCIPmessageFPrintInfo(messagehdlr, file, "  [integer]");
3029 	      break;
3030 	   case SCIP_VARTYPE_IMPLINT:
3031 	      SCIPmessageFPrintInfo(messagehdlr, file, "  [implicit]");
3032 	      break;
3033 	   case SCIP_VARTYPE_CONTINUOUS:
3034 	      SCIPmessageFPrintInfo(messagehdlr, file, "  [continuous]");
3035 	      break;
3036 	   default:
3037 	      SCIPerrorMessage("unknown variable type\n");
3038 	      SCIPABORT();
3039 	      return SCIP_ERROR; /*lint !e527*/
3040 	   }
3041 	
3042 	   /* name */
3043 	   SCIPmessageFPrintInfo(messagehdlr, file, " <%s>:", var->name);
3044 	
3045 	   /* objective value */
3046 	   SCIPmessageFPrintInfo(messagehdlr, file, " obj=%.15g", var->obj);
3047 	
3048 	   /* bounds (global bounds for transformed variables, original bounds for original variables) */
3049 	   if( !SCIPvarIsTransformed(var) )
3050 	   {
3051 	      /* output original bound */
3052 	      lb = SCIPvarGetLbOriginal(var);
3053 	      ub = SCIPvarGetUbOriginal(var);
3054 	      printBounds(set, messagehdlr, file, lb, ub, "original bounds");
3055 	
3056 	      /* output lazy bound */
3057 	      lb = SCIPvarGetLbLazy(var);
3058 	      ub = SCIPvarGetUbLazy(var);
3059 	
3060 	      /* only display the lazy bounds if they are different from [-infinity,infinity] */
3061 	      if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
3062 	         printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
3063 	
3064 	      holelist = SCIPvarGetHolelistOriginal(var);
3065 	      printHolelist(messagehdlr, file, holelist, "original holes");
3066 	   }
3067 	   else
3068 	   {
3069 	      /* output global bound */
3070 	      lb = SCIPvarGetLbGlobal(var);
3071 	      ub = SCIPvarGetUbGlobal(var);
3072 	      printBounds(set, messagehdlr, file, lb, ub, "global bounds");
3073 	
3074 	      /* output local bound */
3075 	      lb = SCIPvarGetLbLocal(var);
3076 	      ub = SCIPvarGetUbLocal(var);
3077 	      printBounds(set, messagehdlr, file, lb, ub, "local bounds");
3078 	
3079 	      /* output lazy bound */
3080 	      lb = SCIPvarGetLbLazy(var);
3081 	      ub = SCIPvarGetUbLazy(var);
3082 	
3083 	      /* only display the lazy bounds if they are different from [-infinity,infinity] */
3084 	      if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
3085 	         printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
3086 	
3087 	      /* global hole list */
3088 	      holelist = SCIPvarGetHolelistGlobal(var);
3089 	      printHolelist(messagehdlr, file, holelist, "global holes");
3090 	
3091 	      /* local hole list */
3092 	      holelist = SCIPvarGetHolelistLocal(var);
3093 	      printHolelist(messagehdlr, file, holelist, "local holes");
3094 	   }
3095 	
3096 	   /* fixings and aggregations */
3097 	   switch( SCIPvarGetStatus(var) )
3098 	   {
3099 	   case SCIP_VARSTATUS_ORIGINAL:
3100 	   case SCIP_VARSTATUS_LOOSE:
3101 	   case SCIP_VARSTATUS_COLUMN:
3102 	      break;
3103 	
3104 	   case SCIP_VARSTATUS_FIXED:
3105 	      SCIPmessageFPrintInfo(messagehdlr, file, ", fixed:");
3106 	      if( SCIPsetIsInfinity(set, var->glbdom.lb) )
3107 	         SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
3108 	      else if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
3109 	         SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
3110 	      else
3111 	         SCIPmessageFPrintInfo(messagehdlr, file, "%.15g", var->glbdom.lb);
3112 	      break;
3113 	
3114 	   case SCIP_VARSTATUS_AGGREGATED:
3115 	      SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
3116 	      if( !SCIPsetIsZero(set, var->data.aggregate.constant) )
3117 	         SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.aggregate.constant);
3118 	      SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.aggregate.scalar, SCIPvarGetName(var->data.aggregate.var));
3119 	      break;
3120 	
3121 	   case SCIP_VARSTATUS_MULTAGGR:
3122 	      SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
3123 	      if( var->data.multaggr.nvars == 0 || !SCIPsetIsZero(set, var->data.multaggr.constant) )
3124 	         SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.multaggr.constant);
3125 	      for( i = 0; i < var->data.multaggr.nvars; ++i )
3126 	         SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.multaggr.scalars[i], SCIPvarGetName(var->data.multaggr.vars[i]));
3127 	      break;
3128 	
3129 	   case SCIP_VARSTATUS_NEGATED:
3130 	      SCIPmessageFPrintInfo(messagehdlr, file, ", negated: %.15g - <%s>", var->data.negate.constant, SCIPvarGetName(var->negatedvar));
3131 	      break;
3132 	
3133 	   default:
3134 	      SCIPerrorMessage("unknown variable status\n");
3135 	      SCIPABORT();
3136 	      return SCIP_ERROR; /*lint !e527*/
3137 	   }
3138 	
3139 	   SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3140 	
3141 	   return SCIP_OKAY;
3142 	}
3143 	
3144 	/** issues a VARUNLOCKED event on the given variable */
3145 	static
3146 	SCIP_RETCODE varEventVarUnlocked(
3147 	   SCIP_VAR*             var,                /**< problem variable to change */
3148 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3149 	   SCIP_SET*             set,                /**< global SCIP settings */
3150 	   SCIP_EVENTQUEUE*      eventqueue          /**< event queue */
3151 	   )
3152 	{
3153 	   SCIP_EVENT* event;
3154 	
3155 	   assert(var != NULL);
3156 	   assert(var->nlocksdown[SCIP_LOCKTYPE_MODEL] <= 1 && var->nlocksup[SCIP_LOCKTYPE_MODEL] <= 1);
3157 	   assert(var->scip == set->scip);
3158 	
3159 	   /* issue VARUNLOCKED event on variable */
3160 	   SCIP_CALL( SCIPeventCreateVarUnlocked(&event, blkmem, var) );
3161 	   SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3162 	
3163 	   return SCIP_OKAY;
3164 	}
3165 	
3166 	/** modifies lock numbers for rounding */
3167 	SCIP_RETCODE SCIPvarAddLocks(
3168 	   SCIP_VAR*             var,                /**< problem variable */
3169 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3170 	   SCIP_SET*             set,                /**< global SCIP settings */
3171 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
3172 	   SCIP_LOCKTYPE         locktype,           /**< type of the variable locks */
3173 	   int                   addnlocksdown,      /**< increase in number of rounding down locks */
3174 	   int                   addnlocksup         /**< increase in number of rounding up locks */
3175 	   )
3176 	{
3177 	   SCIP_VAR* lockvar;
3178 	
3179 	   assert(var != NULL);
3180 	   assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3181 	   assert(var->nlocksup[locktype] >= 0);
3182 	   assert(var->nlocksdown[locktype] >= 0);
3183 	   assert(var->scip == set->scip);
3184 	
3185 	   if( addnlocksdown == 0 && addnlocksup == 0 )
3186 	      return SCIP_OKAY;
3187 	
3188 	#ifdef SCIP_DEBUG
3189 	   SCIPsetDebugMsg(set, "add rounding locks %d/%d to variable <%s> (locks=%d/%d, type=%u)\n",
3190 	         addnlocksdown, addnlocksup, var->name, var->nlocksdown[locktype], var->nlocksup[locktype], locktype);
3191 	#endif
3192 	
3193 	   lockvar = var;
3194 	
3195 	   while( TRUE ) /*lint !e716 */
3196 	   {
3197 	      assert(lockvar != NULL);
3198 	
3199 	      switch( SCIPvarGetStatus(lockvar) )
3200 	      {
3201 	      case SCIP_VARSTATUS_ORIGINAL:
3202 	         if( lockvar->data.original.transvar != NULL )
3203 	         {
3204 	            lockvar = lockvar->data.original.transvar;
3205 	            break;
3206 	         }
3207 	         else
3208 	         {
3209 	            lockvar->nlocksdown[locktype] += addnlocksdown;
3210 	            lockvar->nlocksup[locktype] += addnlocksup;
3211 	
3212 	            assert(lockvar->nlocksdown[locktype] >= 0);
3213 	            assert(lockvar->nlocksup[locktype] >= 0);
3214 	
3215 	            return SCIP_OKAY;
3216 	         }
3217 	      case SCIP_VARSTATUS_LOOSE:
3218 	      case SCIP_VARSTATUS_COLUMN:
3219 	      case SCIP_VARSTATUS_FIXED:
3220 	         lockvar->nlocksdown[locktype] += addnlocksdown;
3221 	         lockvar->nlocksup[locktype] += addnlocksup;
3222 	
3223 	         assert(lockvar->nlocksdown[locktype] >= 0);
3224 	         assert(lockvar->nlocksup[locktype] >= 0);
3225 	
3226 	         if( locktype == SCIP_LOCKTYPE_MODEL && lockvar->nlocksdown[locktype] <= 1
3227 	            && lockvar->nlocksup[locktype] <= 1 )
3228 	         {
3229 	            SCIP_CALL( varEventVarUnlocked(lockvar, blkmem, set, eventqueue) );
3230 	         }
3231 	
3232 	         return SCIP_OKAY;
3233 	      case SCIP_VARSTATUS_AGGREGATED:
3234 	         assert(!lockvar->donotaggr);
3235 	
3236 	         if( lockvar->data.aggregate.scalar < 0.0 )
3237 	         {
3238 	            int tmp = addnlocksup;
3239 	
3240 	            addnlocksup = addnlocksdown;
3241 	            addnlocksdown = tmp;
3242 	         }
3243 	
3244 	         lockvar = lockvar->data.aggregate.var;
3245 	         break;
3246 	      case SCIP_VARSTATUS_MULTAGGR:
3247 	      {
3248 	         int v;
3249 	
3250 	         assert(!lockvar->donotmultaggr);
3251 	
3252 	         lockvar->nlocksdown[locktype] += addnlocksdown;
3253 	         lockvar->nlocksup[locktype] += addnlocksup;
3254 	
3255 	         assert(lockvar->nlocksdown[locktype] >= 0);
3256 	         assert(lockvar->nlocksup[locktype] >= 0);
3257 	
3258 	         for( v = lockvar->data.multaggr.nvars - 1; v >= 0; --v )
3259 	         {
3260 	            if( lockvar->data.multaggr.scalars[v] > 0.0 )
3261 	            {
3262 	               SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksdown,
3263 	                     addnlocksup) );
3264 	            }
3265 	            else
3266 	            {
3267 	               SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksup,
3268 	                     addnlocksdown) );
3269 	            }
3270 	         }
3271 	         return SCIP_OKAY;
3272 	      }
3273 	      case SCIP_VARSTATUS_NEGATED:
3274 	      {
3275 	         int tmp = addnlocksup;
3276 	
3277 	         assert(lockvar->negatedvar != NULL);
3278 	         assert(SCIPvarGetStatus(lockvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
3279 	         assert(lockvar->negatedvar->negatedvar == lockvar);
3280 	
3281 	         addnlocksup = addnlocksdown;
3282 	         addnlocksdown = tmp;
3283 	
3284 	         lockvar = lockvar->negatedvar;
3285 	         break;
3286 	      }
3287 	      default:
3288 	         SCIPerrorMessage("unknown variable status\n");
3289 	         return SCIP_INVALIDDATA;
3290 	      }
3291 	   }
3292 	}
3293 	
3294 	/** gets number of locks for rounding down of a special type */
3295 	int SCIPvarGetNLocksDownType(
3296 	   SCIP_VAR*             var,                /**< problem variable */
3297 	   SCIP_LOCKTYPE         locktype            /**< type of variable locks */
3298 	   )
3299 	{
3300 	   int nlocks;
3301 	   int i;
3302 	
3303 	   assert(var != NULL);
3304 	   assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3305 	   assert(var->nlocksdown[locktype] >= 0);
3306 	
3307 	   switch( SCIPvarGetStatus(var) )
3308 	   {
3309 	   case SCIP_VARSTATUS_ORIGINAL:
3310 	      if( var->data.original.transvar != NULL )
3311 	         return SCIPvarGetNLocksDownType(var->data.original.transvar, locktype);
3312 	      else
3313 	         return var->nlocksdown[locktype];
3314 	
3315 	   case SCIP_VARSTATUS_LOOSE:
3316 	   case SCIP_VARSTATUS_COLUMN:
3317 	   case SCIP_VARSTATUS_FIXED:
3318 	      return var->nlocksdown[locktype];
3319 	
3320 	   case SCIP_VARSTATUS_AGGREGATED:
3321 	      assert(!var->donotaggr);
3322 	      if( var->data.aggregate.scalar > 0.0 )
3323 	         return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
3324 	      else
3325 	         return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
3326 	
3327 	   case SCIP_VARSTATUS_MULTAGGR:
3328 	      assert(!var->donotmultaggr);
3329 	      nlocks = 0;
3330 	      for( i = 0; i < var->data.multaggr.nvars; ++i )
3331 	      {
3332 	         if( var->data.multaggr.scalars[i] > 0.0 )
3333 	            nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
3334 	         else
3335 	            nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
3336 	      }
3337 	      return nlocks;
3338 	
3339 	   case SCIP_VARSTATUS_NEGATED:
3340 	      assert(var->negatedvar != NULL);
3341 	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
3342 	      assert(var->negatedvar->negatedvar == var);
3343 	      return SCIPvarGetNLocksUpType(var->negatedvar, locktype);
3344 	
3345 	   default:
3346 	      SCIPerrorMessage("unknown variable status\n");
3347 	      SCIPABORT();
3348 	      return INT_MAX; /*lint !e527*/
3349 	   }
3350 	}
3351 	
3352 	/** gets number of locks for rounding up of a special type */
3353 	int SCIPvarGetNLocksUpType(
3354 	   SCIP_VAR*             var,                /**< problem variable */
3355 	   SCIP_LOCKTYPE         locktype            /**< type of variable locks */
3356 	   )
3357 	{
3358 	   int nlocks;
3359 	   int i;
3360 	
3361 	   assert(var != NULL);
3362 	   assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3363 	   assert(var->nlocksup[locktype] >= 0);
3364 	
3365 	   switch( SCIPvarGetStatus(var) )
3366 	   {
3367 	   case SCIP_VARSTATUS_ORIGINAL:
3368 	      if( var->data.original.transvar != NULL )
3369 	         return SCIPvarGetNLocksUpType(var->data.original.transvar, locktype);
3370 	      else
3371 	         return var->nlocksup[locktype];
3372 	
3373 	   case SCIP_VARSTATUS_LOOSE:
3374 	   case SCIP_VARSTATUS_COLUMN:
3375 	   case SCIP_VARSTATUS_FIXED:
3376 	      return var->nlocksup[locktype];
3377 	
3378 	   case SCIP_VARSTATUS_AGGREGATED:
3379 	      assert(!var->donotaggr);
3380 	      if( var->data.aggregate.scalar > 0.0 )
3381 	         return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
3382 	      else
3383 	         return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
3384 	
3385 	   case SCIP_VARSTATUS_MULTAGGR:
3386 	      assert(!var->donotmultaggr);
3387 	      nlocks = 0;
3388 	      for( i = 0; i < var->data.multaggr.nvars; ++i )
3389 	      {
3390 	         if( var->data.multaggr.scalars[i] > 0.0 )
3391 	            nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
3392 	         else
3393 	            nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
3394 	      }
3395 	      return nlocks;
3396 	
3397 	   case SCIP_VARSTATUS_NEGATED:
3398 	      assert(var->negatedvar != NULL);
3399 	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
3400 	      assert(var->negatedvar->negatedvar == var);
3401 	      return SCIPvarGetNLocksDownType(var->negatedvar, locktype);
3402 	
3403 	   default:
3404 	      SCIPerrorMessage("unknown variable status\n");
3405 	      SCIPABORT();
3406 	      return INT_MAX; /*lint !e527*/
3407 	   }
3408 	}
3409 	
3410 	/** gets number of locks for rounding down
3411 	 *
3412 	 *  @note This method will always return variable locks of type model
3413 	 *
3414 	 *  @note It is recommented to use SCIPvarGetNLocksDownType()
3415 	 */
3416 	int SCIPvarGetNLocksDown(
3417 	   SCIP_VAR*             var                 /**< problem variable */
3418 	   )
3419 	{
3420 	   return SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL);
3421 	}
3422 	
3423 	/** gets number of locks for rounding up
3424 	 *
3425 	 *  @note This method will always return variable locks of type model
3426 	 *
3427 	 *  @note It is recommented to use SCIPvarGetNLocksUpType()
3428 	 */
3429 	int SCIPvarGetNLocksUp(
3430 	   SCIP_VAR*             var                 /**< problem variable */
3431 	   )
3432 	{
3433 	   return SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL);
3434 	}
3435 	
3436 	/** is it possible, to round variable down and stay feasible?
3437 	 *
3438 	 *  @note This method will always check w.r.t variable locks of type model
3439 	 */
3440 	SCIP_Bool SCIPvarMayRoundDown(
3441 	   SCIP_VAR*             var                 /**< problem variable */
3442 	   )
3443 	{
3444 	   return (SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 0);
3445 	}
3446 	
3447 	/** is it possible, to round variable up and stay feasible?
3448 	 *
3449 	 *  @note This method will always check w.r.t. variable locks of type model
3450 	 */
3451 	SCIP_Bool SCIPvarMayRoundUp(
3452 	   SCIP_VAR*             var                 /**< problem variable */
3453 	   )
3454 	{
3455 	   return (SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 0);
3456 	}
3457 	
3458 	/** gets and captures transformed variable of a given variable; if the variable is not yet transformed,
3459 	 *  a new transformed variable for this variable is created
3460 	 */
3461 	SCIP_RETCODE SCIPvarTransform(
3462 	   SCIP_VAR*             origvar,            /**< original problem variable */
3463 	   BMS_BLKMEM*           blkmem,             /**< block memory of transformed problem */
3464 	   SCIP_SET*             set,                /**< global SCIP settings */
3465 	   SCIP_STAT*            stat,               /**< problem statistics */
3466 	   SCIP_OBJSENSE         objsense,           /**< objective sense of original problem; transformed is always MINIMIZE */
3467 	   SCIP_VAR**            transvar            /**< pointer to store the transformed variable */
3468 	   )
3469 	{
3470 	   char name[SCIP_MAXSTRLEN];
3471 	
3472 	   assert(origvar != NULL);
3473 	   assert(origvar->scip == set->scip);
3474 	   assert(SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_ORIGINAL);
3475 	   assert(SCIPsetIsEQ(set, origvar->glbdom.lb, origvar->locdom.lb));
3476 	   assert(SCIPsetIsEQ(set, origvar->glbdom.ub, origvar->locdom.ub));
3477 	   assert(origvar->vlbs == NULL);
3478 	   assert(origvar->vubs == NULL);
3479 	   assert(transvar != NULL);
3480 	
3481 	   /* check if variable is already transformed */
3482 	   if( origvar->data.original.transvar != NULL )
3483 	   {
3484 	      *transvar = origvar->data.original.transvar;
3485 	      SCIPvarCapture(*transvar);
3486 	   }
3487 	   else
3488 	   {
3489 	      int i;
3490 	
3491 	      /* create transformed variable */
3492 	      (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "t_%s", origvar->name);
3493 	      SCIP_CALL( SCIPvarCreateTransformed(transvar, blkmem, set, stat, name,
3494 	            origvar->glbdom.lb, origvar->glbdom.ub, (SCIP_Real)objsense * origvar->obj,
3495 	            SCIPvarGetType(origvar), origvar->initial, origvar->removable,
3496 	            origvar->vardelorig, origvar->vartrans, origvar->vardeltrans, origvar->varcopy, NULL) );
3497 	
3498 	      /* copy the branch factor and priority */
3499 	      (*transvar)->branchfactor = origvar->branchfactor;
3500 	      (*transvar)->branchpriority = origvar->branchpriority;
3501 	      (*transvar)->branchdirection = origvar->branchdirection; /*lint !e732*/
3502 	
3503 	      /* duplicate hole lists */
3504 	      SCIP_CALL( holelistDuplicate(&(*transvar)->glbdom.holelist, blkmem, set, origvar->glbdom.holelist) );
3505 	      SCIP_CALL( holelistDuplicate(&(*transvar)->locdom.holelist, blkmem, set, origvar->locdom.holelist) );
3506 	
3507 	      /* link original and transformed variable */
3508 	      origvar->data.original.transvar = *transvar;
3509 	      SCIP_CALL( varAddParent(*transvar, blkmem, set, origvar) );
3510 	
3511 	      /* copy rounding locks */
3512 	      for( i = 0; i < NLOCKTYPES; i++ )
3513 	      {
3514 	         (*transvar)->nlocksdown[i] = origvar->nlocksdown[i];
3515 	         (*transvar)->nlocksup[i] = origvar->nlocksup[i];
3516 	         assert((*transvar)->nlocksdown[i] >= 0);
3517 	         assert((*transvar)->nlocksup[i] >= 0);
3518 	      }
3519 	
3520 	      /* copy donot(mult)aggr status */
3521 	      (*transvar)->donotaggr = origvar->donotaggr;
3522 	      (*transvar)->donotmultaggr = origvar->donotmultaggr;
3523 	
3524 	      /* copy lazy bounds */
3525 	      (*transvar)->lazylb = origvar->lazylb;
3526 	      (*transvar)->lazyub = origvar->lazyub;
3527 	
3528 	      /* transfer eventual variable statistics; do not update global statistics, because this has been done
3529 	       * when original variable was created
3530 	       */
3531 	      SCIPhistoryUnite((*transvar)->history, origvar->history, FALSE);
3532 	
3533 	      /* transform user data */
3534 	      if( origvar->vartrans != NULL )
3535 	      {
3536 	         SCIP_CALL( origvar->vartrans(set->scip, origvar, origvar->vardata, *transvar, &(*transvar)->vardata) );
3537 	      }
3538 	      else
3539 	         (*transvar)->vardata = origvar->vardata;
3540 	   }
3541 	
3542 	   SCIPsetDebugMsg(set, "transformed variable: <%s>[%p] -> <%s>[%p]\n", origvar->name, (void*)origvar, (*transvar)->name, (void*)*transvar);
3543 	
3544 	   return SCIP_OKAY;
3545 	}
3546 	
3547 	/** gets corresponding transformed variable of an original or negated original variable */
3548 	SCIP_RETCODE SCIPvarGetTransformed(
3549 	   SCIP_VAR*             origvar,            /**< original problem variable */
3550 	   BMS_BLKMEM*           blkmem,             /**< block memory of transformed problem */
3551 	   SCIP_SET*             set,                /**< global SCIP settings */
3552 	   SCIP_STAT*            stat,               /**< problem statistics */
3553 	   SCIP_VAR**            transvar            /**< pointer to store the transformed variable, or NULL if not existing yet */
3554 	   )
3555 	{
3556 	   assert(origvar != NULL);
3557 	   assert(SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_ORIGINAL || SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_NEGATED);
3558 	   assert(origvar->scip == set->scip);
3559 	
3560 	   if( SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_NEGATED )
3561 	   {
3562 	      assert(origvar->negatedvar != NULL);
3563 	      assert(SCIPvarGetStatus(origvar->negatedvar) == SCIP_VARSTATUS_ORIGINAL);
3564 	
3565 	      if( origvar->negatedvar->data.original.transvar == NULL )
3566 	         *transvar = NULL;
3567 	      else
3568 	      {
3569 	         SCIP_CALL( SCIPvarNegate(origvar->negatedvar->data.original.transvar, blkmem, set, stat, transvar) );
3570 	      }
3571 	   }
3572 	   else 
3573 	      *transvar = origvar->data.original.transvar;
3574 	
3575 	   return SCIP_OKAY;
3576 	}
3577 	
3578 	/** converts loose transformed variable into column variable, creates LP column */
3579 	SCIP_RETCODE SCIPvarColumn(
3580 	   SCIP_VAR*             var,                /**< problem variable */
3581 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3582 	   SCIP_SET*             set,                /**< global SCIP settings */
3583 	   SCIP_STAT*            stat,               /**< problem statistics */
3584 	   SCIP_PROB*            prob,               /**< problem data */
3585 	   SCIP_LP*              lp                  /**< current LP data */
3586 	   )
3587 	{
3588 	   assert(var != NULL);
3589 	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
3590 	   assert(var->scip == set->scip);
3591 	
3592 	   SCIPsetDebugMsg(set, "creating column for variable <%s>\n", var->name);
3593 	
3594 	   /* switch variable status */
3595 	   var->varstatus = SCIP_VARSTATUS_COLUMN; /*lint !e641*/
3596 	
3597 	   /* create column of variable */
3598 	   SCIP_CALL( SCIPcolCreate(&var->data.col, blkmem, set, stat, var, 0, NULL, NULL, var->removable) );
3599 	
3600 	   if( var->probindex != -1 )
3601 	   {
3602 	      /* inform problem about the variable's status change */
3603 	      SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3604 	
3605 	      /* inform LP, that problem variable is now a column variable and no longer loose */
3606 	      SCIP_CALL( SCIPlpUpdateVarColumn(lp, set, var) );
3607 	   }
3608 	
3609 	   return SCIP_OKAY;
3610 	}
3611 	
3612 	/** converts column transformed variable back into loose variable, frees LP column */
3613 	SCIP_RETCODE SCIPvarLoose(
3614 	   SCIP_VAR*             var,                /**< problem variable */
3615 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3616 	   SCIP_SET*             set,                /**< global SCIP settings */
3617 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
3618 	   SCIP_PROB*            prob,               /**< problem data */
3619 	   SCIP_LP*              lp                  /**< current LP data */
3620 	   )
3621 	{
3622 	   assert(var != NULL);
3623 	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
3624 	   assert(var->scip == set->scip);
3625 	   assert(var->data.col != NULL);
3626 	   assert(var->data.col->lppos == -1);
3627 	   assert(var->data.col->lpipos == -1);
3628 	
3629 	   SCIPsetDebugMsg(set, "deleting column for variable <%s>\n", var->name);
3630 	
3631 	   /* free column of variable */
3632 	   SCIP_CALL( SCIPcolFree(&var->data.col, blkmem, set, eventqueue, lp) );
3633 	
3634 	   /* switch variable status */
3635 	   var->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
3636 	
3637 	   if( var->probindex != -1 )
3638 	   {
3639 	      /* inform problem about the variable's status change */
3640 	      SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3641 	
3642 	      /* inform LP, that problem variable is now a loose variable and no longer a column */
3643 	      SCIP_CALL( SCIPlpUpdateVarLoose(lp, set, var) );
3644 	   }
3645 	
3646 	   return SCIP_OKAY;
3647 	}
3648 	
3649 	/** issues a VARFIXED event on the given variable and all its parents (except ORIGINAL parents);
3650 	 *  the event issuing on the parents is necessary, because unlike with bound changes, the parent variables
3651 	 *  are not informed about a fixing of an active variable they are pointing to
3652 	 */
3653 	static
3654 	SCIP_RETCODE varEventVarFixed(
3655 	   SCIP_VAR*             var,                /**< problem variable to change */
3656 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3657 	   SCIP_SET*             set,                /**< global SCIP settings */
3658 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
3659 	   int                   fixeventtype        /**< is this event a fixation(0), an aggregation(1), or a
3660 						      *   multi-aggregation(2)
3661 						      */
3662 	   )
3663 	{
3664 	   SCIP_EVENT* event;
3665 	   SCIP_VARSTATUS varstatus;
3666 	   int i;
3667 	
3668 	   assert(var != NULL);
3669 	   assert(var->scip == set->scip);
3670 	   assert(0 <= fixeventtype && fixeventtype <= 2);
3671 	
3672 	   /* issue VARFIXED event on variable */
3673 	   SCIP_CALL( SCIPeventCreateVarFixed(&event, blkmem, var) );
3674 	   SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3675 	
3676 	#ifndef NDEBUG
3677 	   for( i = var->nparentvars -1; i >= 0; --i )
3678 	   {
3679 	      assert(SCIPvarGetStatus(var->parentvars[i]) != SCIP_VARSTATUS_MULTAGGR);
3680 	   }
3681 	#endif
3682 	
3683 	   switch( fixeventtype )
3684 	   {
3685 	   case 0:
3686 	      /* process all parents of a fixed variable */
3687 	      for( i = var->nparentvars - 1; i >= 0; --i )
3688 	      {
3689 		 varstatus = SCIPvarGetStatus(var->parentvars[i]);
3690 	
3691 		 assert(varstatus != SCIP_VARSTATUS_FIXED);
3692 	
3693 		 /* issue event on all not yet fixed parent variables, (that should already issued this event) except the original
3694 		  * one
3695 		  */
3696 		 if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3697 		 {
3698 		    SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3699 		 }
3700 	      }
3701 	      break;
3702 	   case 1:
3703 	      /* process all parents of a aggregated variable */
3704 	      for( i = var->nparentvars - 1; i >= 0; --i )
3705 	      {
3706 		 varstatus = SCIPvarGetStatus(var->parentvars[i]);
3707 	
3708 		 assert(varstatus != SCIP_VARSTATUS_FIXED);
3709 	
3710 		 /* issue event for not aggregated parent variable, because for these and its parents the var event was already
3711 	          * issued(, except the original one)
3712 	          *
3713 	          * @note that even before an aggregated parent variable, there might be variables, for which the vent was not
3714 	          *       yet issued
3715 		  */
3716 	         if( varstatus == SCIP_VARSTATUS_AGGREGATED )
3717 	            continue;
3718 	
3719 		 if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3720 		 {
3721 		    SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3722 		 }
3723 	      }
3724 	      break;
3725 	   case 2:
3726 	      /* process all parents of a aggregated variable */
3727 	      for( i = var->nparentvars - 1; i >= 0; --i )
3728 	      {
3729 		 varstatus = SCIPvarGetStatus(var->parentvars[i]);
3730 	
3731 		 assert(varstatus != SCIP_VARSTATUS_FIXED);
3732 	
3733 		 /* issue event on all parent variables except the original one */
3734 		 if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3735 		 {
3736 		    SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3737 		 }
3738 	      }
3739 	      break;
3740 	   default:
3741 	      SCIPerrorMessage("unknown variable fixation event origin\n");
3742 	      return SCIP_INVALIDDATA;
3743 	   }
3744 	
3745 	   return SCIP_OKAY;
3746 	}
3747 	
3748 	/** converts variable into fixed variable */
3749 	SCIP_RETCODE SCIPvarFix(
3750 	   SCIP_VAR*             var,                /**< problem variable */
3751 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3752 	   SCIP_SET*             set,                /**< global SCIP settings */
3753 	   SCIP_STAT*            stat,               /**< problem statistics */
3754 	   SCIP_PROB*            transprob,          /**< tranformed problem data */
3755 	   SCIP_PROB*            origprob,           /**< original problem data */
3756 	   SCIP_PRIMAL*          primal,             /**< primal data */
3757 	   SCIP_TREE*            tree,               /**< branch and bound tree */
3758 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
3759 	   SCIP_LP*              lp,                 /**< current LP data */
3760 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
3761 	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter for global (not variable dependent) events */
3762 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
3763 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
3764 	   SCIP_Real             fixedval,           /**< value to fix variable at */
3765 	   SCIP_Bool*            infeasible,         /**< pointer to store whether the fixing is infeasible */
3766 	   SCIP_Bool*            fixed               /**< pointer to store whether the fixing was performed (variable was unfixed) */
3767 	   )
3768 	{
3769 	   SCIP_Real obj;
3770 	   SCIP_Real childfixedval;
3771 	
3772 	   assert(var != NULL);
3773 	   assert(var->scip == set->scip);
3774 	   assert(SCIPsetIsEQ(set, var->glbdom.lb, var->locdom.lb));
3775 	   assert(SCIPsetIsEQ(set, var->glbdom.ub, var->locdom.ub));
3776 	   assert(infeasible != NULL);
3777 	   assert(fixed != NULL);
3778 	
3779 	   SCIPsetDebugMsg(set, "fix variable <%s>[%g,%g] to %g\n", var->name, var->glbdom.lb, var->glbdom.ub, fixedval);
3780 	
3781 	   *infeasible = FALSE;
3782 	   *fixed = FALSE;
3783 	
3784 	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED )
3785 	   {
3786 	      *infeasible = !SCIPsetIsFeasEQ(set, fixedval, var->locdom.lb);
3787 	      SCIPsetDebugMsg(set, " -> variable already fixed to %g (fixedval=%g): infeasible=%u\n", var->locdom.lb, fixedval, *infeasible);
3788 	      return SCIP_OKAY;
3789 	   }
3790 	   else if( (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPsetIsFeasIntegral(set, fixedval))
3791 	      || SCIPsetIsFeasLT(set, fixedval, var->locdom.lb)
3792 	      || SCIPsetIsFeasGT(set, fixedval, var->locdom.ub) )
3793 	   {
3794 	      SCIPsetDebugMsg(set, " -> fixing infeasible: locdom=[%g,%g], fixedval=%g\n", var->locdom.lb, var->locdom.ub, fixedval);
3795 	      *infeasible = TRUE;
3796 	      return SCIP_OKAY;
3797 	   }
3798 	
3799 	   switch( SCIPvarGetStatus(var) )
3800 	   {
3801 	   case SCIP_VARSTATUS_ORIGINAL:
3802 	      if( var->data.original.transvar == NULL )
3803 	      {
3804 	         SCIPerrorMessage("cannot fix an untransformed original variable\n");
3805 	         return SCIP_INVALIDDATA;
3806 	      }
3807 	      SCIP_CALL( SCIPvarFix(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
3808 	            lp, branchcand, eventfilter, eventqueue, cliquetable, fixedval, infeasible, fixed) );
3809 	      break;
3810 	
3811 	   case SCIP_VARSTATUS_LOOSE:
3812 	      assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
3813 	
3814 	      /* set the fixed variable's objective value to 0.0 */
3815 	      obj = var->obj;
3816 	      SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
3817 	
3818 	      /* since we change the variable type form loose to fixed, we have to adjust the number of loose
3819 	       * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
3820 	       * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
3821 	       * objective of this variable is set to zero
3822 	       */
3823 	      SCIPlpDecNLoosevars(lp);
3824 	
3825 	      /* change variable's bounds to fixed value (thereby removing redundant implications and variable bounds) */
3826 	      holelistFree(&var->glbdom.holelist, blkmem);
3827 	      holelistFree(&var->locdom.holelist, blkmem);
3828 	      SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3829 	      SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3830 	
3831 	      if( var->glbdom.lb != var->glbdom.ub )  /*lint !e777*/
3832 	      {
3833 	         /* explicitly set variable's bounds if the fixed value was in epsilon range of the old bound (so above call didn't set bound) */
3834 	         if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS )
3835 	         {
3836 	            /* if not continuous variable, then make sure variable is fixed to integer value */
3837 	            assert(SCIPsetIsIntegral(set, fixedval));
3838 	            fixedval = SCIPsetRound(set, fixedval);
3839 	         }
3840 	         var->glbdom.lb = fixedval;
3841 	         var->glbdom.ub = fixedval;
3842 	      }
3843 	
3844 	      /* ensure local domain is fixed to same value as global domain */
3845 	      var->locdom.lb = var->glbdom.lb;
3846 	      var->locdom.ub = var->glbdom.ub;
3847 	
3848 	      /* delete implications and variable bounds information */
3849 	      SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
3850 	      assert(var->vlbs == NULL);
3851 	      assert(var->vubs == NULL);
3852 	      assert(var->implics == NULL);
3853 	
3854 	      /* clear the history of the variable */
3855 	      SCIPhistoryReset(var->history);
3856 	      SCIPhistoryReset(var->historycrun);
3857 	
3858 	      /* convert variable into fixed variable */
3859 	      var->varstatus = SCIP_VARSTATUS_FIXED; /*lint !e641*/
3860 	
3861 	      /* inform problem about the variable's status change */
3862 	      if( var->probindex != -1 )
3863 	      {
3864 	         SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
3865 	      }
3866 	
3867 	      /* reset the objective value of the fixed variable, thus adjusting the problem's objective offset */
3868 	      SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
3869 	
3870 	      /* issue VARFIXED event */
3871 	      SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 0) );
3872 	
3873 	      *fixed = TRUE;
3874 	      break;
3875 	
3876 	   case SCIP_VARSTATUS_COLUMN:
3877 	      SCIPerrorMessage("cannot fix a column variable\n");
3878 	      return SCIP_INVALIDDATA;
3879 	
3880 	   case SCIP_VARSTATUS_FIXED:
3881 	      SCIPerrorMessage("cannot fix a fixed variable again\n");  /*lint !e527*/
3882 	      SCIPABORT(); /* case is already handled in earlier if condition */
3883 	      return SCIP_INVALIDDATA;  /*lint !e527*/
3884 	
3885 	   case SCIP_VARSTATUS_AGGREGATED:
3886 	      /* fix aggregation variable y in x = a*y + c, instead of fixing x directly */
3887 	      assert(SCIPsetIsZero(set, var->obj));
3888 	      assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
3889 	      if( SCIPsetIsInfinity(set, fixedval) || SCIPsetIsInfinity(set, -fixedval) )
3890 	         childfixedval = (var->data.aggregate.scalar < 0.0 ? -fixedval : fixedval);
3891 	      else
3892 	         childfixedval = (fixedval - var->data.aggregate.constant)/var->data.aggregate.scalar;
3893 	      SCIP_CALL( SCIPvarFix(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3894 	            branchcand, eventfilter, eventqueue, cliquetable, childfixedval, infeasible, fixed) );
3895 	      break;
3896 	
3897 	   case SCIP_VARSTATUS_MULTAGGR:
3898 	      SCIPerrorMessage("cannot fix a multiple aggregated variable\n");
3899 	      SCIPABORT();
3900 	      return SCIP_INVALIDDATA;  /*lint !e527*/
3901 	
3902 	   case SCIP_VARSTATUS_NEGATED:
3903 	      /* fix negation variable x in x' = offset - x, instead of fixing x' directly */
3904 	      assert(SCIPsetIsZero(set, var->obj));
3905 	      assert(var->negatedvar != NULL);
3906 	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
3907 	      assert(var->negatedvar->negatedvar == var);
3908 	      SCIP_CALL( SCIPvarFix(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3909 	            branchcand, eventfilter, eventqueue, cliquetable, var->data.negate.constant - fixedval, infeasible, fixed) );
3910 	      break;
3911 	
3912 	   default:
3913 	      SCIPerrorMessage("unknown variable status\n");
3914 	      return SCIP_INVALIDDATA;
3915 	   }
3916 	
3917 	   return SCIP_OKAY;
3918 	}
3919 	
3920 	/** transforms given variables, scalars and constant to the corresponding active variables, scalars and constant
3921 	 *
3922 	 * If the number of needed active variables is greater than the available slots in the variable array, nothing happens except
3923 	 * that the required size is stored in the corresponding variable; hence, if afterwards the required size is greater than the
3924 	 * available slots (varssize), nothing happens; otherwise, the active variable representation is stored in the arrays.
3925 	 *
3926 	 * The reason for this approach is that we cannot reallocate memory, since we do not know how the
3927 	 * memory has been allocated (e.g., by a C++ 'new' or SCIP functions).
3928 	 */
3929 	SCIP_RETCODE SCIPvarGetActiveRepresentatives(
3930 	   SCIP_SET*             set,                /**< global SCIP settings */
3931 	   SCIP_VAR**            vars,               /**< variable array to get active variables */
3932 	   SCIP_Real*            scalars,            /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
3933 	   int*                  nvars,              /**< pointer to number of variables and values in vars and scalars array */
3934 	   int                   varssize,           /**< available slots in vars and scalars array */
3935 	   SCIP_Real*            constant,           /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c  */
3936 	   int*                  requiredsize,       /**< pointer to store the required array size for the active variables */
3937 	   SCIP_Bool             mergemultiples      /**< should multiple occurrences of a var be replaced by a single coeff? */
3938 	   )
3939 	{
3940 	   SCIP_VAR** activevars;
3941 	   SCIP_Real* activescalars;
3942 	   int nactivevars;
3943 	   SCIP_Real activeconstant;
3944 	   SCIP_Bool activeconstantinf;
3945 	   int activevarssize;
3946 	
3947 	   SCIP_VAR* var;
3948 	   SCIP_Real scalar;
3949 	   int v;
3950 	   int k;
3951 	
3952 	   SCIP_VAR** tmpvars;
3953 	   SCIP_VAR** multvars;
3954 	   SCIP_Real* tmpscalars;
3955 	   SCIP_Real* multscalars;
3956 	   int tmpvarssize;
3957 	   int ntmpvars;
3958 	   int nmultvars;
3959 	
3960 	   SCIP_VAR* multvar;
3961 	   SCIP_Real multscalar;
3962 	   SCIP_Real multconstant;
3963 	   int pos;
3964 	
3965 	   int noldtmpvars;
3966 	
3967 	   SCIP_VAR** tmpvars2;
3968 	   SCIP_Real* tmpscalars2;
3969 	   int tmpvarssize2;
3970 	   int ntmpvars2;
3971 	
3972 	   SCIP_Bool sortagain = FALSE;
3973 	
3974 	   assert(set != NULL);
3975 	   assert(nvars != NULL);
3976 	   assert(scalars != NULL || *nvars == 0);
3977 	   assert(constant != NULL);
3978 	   assert(requiredsize != NULL);
3979 	   assert(*nvars <= varssize);
3980 	
3981 	   *requiredsize = 0;
3982 	
3983 	   if( *nvars == 0 )
3984 	      return SCIP_OKAY;
3985 	
3986 	   assert(vars != NULL);
3987 	
3988 	   /* handle the "easy" case of just one variable and avoid memory allocation if the variable is already active */
3989 	   if( *nvars == 1 && (vars[0]->varstatus == ((int) SCIP_VARSTATUS_COLUMN) || vars[0]->varstatus == ((int) SCIP_VARSTATUS_LOOSE)) )
3990 	   {
3991 	      *requiredsize = 1;
3992 	
3993 	      return SCIP_OKAY;
3994 	   }
3995 	
3996 	   nactivevars = 0;
3997 	   activeconstant = 0.0;
3998 	   activeconstantinf = FALSE;
3999 	   activevarssize = (*nvars) * 2;
4000 	   ntmpvars = *nvars;
4001 	   tmpvarssize = *nvars;
4002 	
4003 	   tmpvarssize2 = 1;
4004 	
4005 	   /* allocate temporary memory */
4006 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpvars2, tmpvarssize2) );
4007 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpscalars2, tmpvarssize2) );
4008 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
4009 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &activescalars, activevarssize) );
4010 	   SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
4011 	   SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpscalars, scalars, ntmpvars) );
4012 	
4013 	   /* to avoid unnecessary expanding of variable arrays while disaggregating several variables multiple times combine same variables
4014 	    * first, first get all corresponding variables with status loose, column, multaggr or fixed
4015 	    */
4016 	   for( v = ntmpvars - 1; v >= 0; --v )
4017 	   {
4018 	      var = tmpvars[v];
4019 	      scalar = tmpscalars[v];
4020 	
4021 	      assert(var != NULL);
4022 	      /* transforms given variable, scalar and constant to the corresponding active, fixed, or
4023 	       * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed
4024 	       * variable, "scalar" will be 0.0 and the value of the sum will be stored in "constant".
4025 	       */
4026 	      SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &activeconstant) );
4027 	      assert(var != NULL);
4028 	
4029 	      assert(SCIPsetIsInfinity(set, activeconstant) == (activeconstant == SCIPsetInfinity(set))); /*lint !e777*/
4030 	      assert(SCIPsetIsInfinity(set, -activeconstant) == (activeconstant == -SCIPsetInfinity(set))); /*lint !e777*/
4031 	
4032 	      activeconstantinf = SCIPsetIsInfinity(set, activeconstant) || SCIPsetIsInfinity(set, -activeconstant);
4033 	
4034 	      assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
4035 	         || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
4036 	         || SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR
4037 	         || SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED);
4038 	
4039 	      tmpvars[v] = var;
4040 	      tmpscalars[v] = scalar;
4041 	   }
4042 	   noldtmpvars = ntmpvars;
4043 	
4044 	   /* sort all variables to combine equal variables easily */
4045 	   SCIPsortPtrReal((void**)tmpvars, tmpscalars, SCIPvarComp, noldtmpvars);
4046 	   ntmpvars = 0;
4047 	   for( v = 1; v < noldtmpvars; ++v )
4048 	   {
4049 	      /* combine same variables */
4050 	      if( SCIPvarCompare(tmpvars[v], tmpvars[ntmpvars]) == 0 )
4051 	      {
4052 	         tmpscalars[ntmpvars] += tmpscalars[v];
4053 	      }
4054 	      else
4055 	      {
4056 	         ++ntmpvars;
4057 	         if( v > ntmpvars )
4058 	         {
4059 	            tmpscalars[ntmpvars] = tmpscalars[v];
4060 	            tmpvars[ntmpvars] = tmpvars[v];
4061 	         }
4062 	      }
4063 	   }
4064 	   ++ntmpvars;
4065 	
4066 	#ifdef SCIP_MORE_DEBUG
4067 	   for( v = 1; v < ntmpvars; ++v )
4068 	      assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4069 	#endif
4070 	
4071 	   /* collect for each variable the representation in active variables */
4072 	   while( ntmpvars >= 1 )
4073 	   {
4074 	      --ntmpvars;
4075 	      ntmpvars2 = 0;
4076 	      var = tmpvars[ntmpvars];
4077 	      scalar = tmpscalars[ntmpvars];
4078 	
4079 	      assert(var != NULL);
4080 	
4081 	      /* TODO: maybe we should test here on SCIPsetIsZero() instead of 0.0 */
4082 	      if( scalar == 0.0 )
4083 	         continue;
4084 	
4085 	      assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
4086 	         || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
4087 	         || SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR
4088 	         || SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED);
4089 	
4090 	      switch( SCIPvarGetStatus(var) )
4091 	      {
4092 	      case SCIP_VARSTATUS_LOOSE:
4093 	      case SCIP_VARSTATUS_COLUMN:
4094 	         /* x = a*y + c */
4095 	         if( nactivevars >= activevarssize )
4096 	         {
4097 	            activevarssize *= 2;
4098 	            SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
4099 	            SCIP_CALL( SCIPsetReallocBufferArray(set, &activescalars, activevarssize) );
4100 	            assert(nactivevars < activevarssize);
4101 	         }
4102 	         activevars[nactivevars] = var;
4103 	         activescalars[nactivevars] = scalar;
4104 	         nactivevars++;
4105 	         break;
4106 	
4107 	      case SCIP_VARSTATUS_MULTAGGR:
4108 	         /* x = a_1*y_1 + ... + a_n*y_n + c */
4109 	         nmultvars = var->data.multaggr.nvars;
4110 	         multvars = var->data.multaggr.vars;
4111 	         multscalars = var->data.multaggr.scalars;
4112 	         sortagain = TRUE;
4113 	
4114 	         if( nmultvars + ntmpvars > tmpvarssize )
4115 	         {
4116 	            while( nmultvars + ntmpvars > tmpvarssize )
4117 	               tmpvarssize *= 2;
4118 	            SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
4119 	            SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars, tmpvarssize) );
4120 	            assert(nmultvars + ntmpvars <= tmpvarssize);
4121 	         }
4122 	
4123 	         if( nmultvars > tmpvarssize2 )
4124 	         {
4125 	            while( nmultvars > tmpvarssize2 )
4126 	               tmpvarssize2 *= 2;
4127 	            SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars2, tmpvarssize2) );
4128 	            SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars2, tmpvarssize2) );
4129 	            assert(nmultvars <= tmpvarssize2);
4130 	         }
4131 	
4132 	         --nmultvars;
4133 	
4134 	         for( ; nmultvars >= 0; --nmultvars )
4135 	         {
4136 	            multvar = multvars[nmultvars];
4137 	            multscalar = multscalars[nmultvars];
4138 	            multconstant = 0;
4139 	
4140 	            assert(multvar != NULL);
4141 	            SCIP_CALL( SCIPvarGetProbvarSum(&multvar, set, &multscalar, &multconstant) );
4142 	            assert(multvar != NULL);
4143 	
4144 	            assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
4145 	               || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
4146 	               || SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR
4147 	               || SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED);
4148 	
4149 	            if( !activeconstantinf )
4150 	            {
4151 	               assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4152 	
4153 	               if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4154 	               {
4155 	                  assert(scalar != 0.0);
4156 	                  if( scalar * multconstant > 0.0 )
4157 	                  {
4158 	                     activeconstant = SCIPsetInfinity(set);
4159 	                     activeconstantinf = TRUE;
4160 	                  }
4161 	                  else
4162 	                  {
4163 	                     activeconstant = -SCIPsetInfinity(set);
4164 	                     activeconstantinf = TRUE;
4165 	                  }
4166 	               }
4167 	               else
4168 	                  activeconstant += scalar * multconstant;
4169 	            }
4170 	#ifndef NDEBUG
4171 	            else
4172 	            {
4173 	               assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4174 	                     (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4175 	               assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4176 	                     (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4177 	            }
4178 	#endif
4179 	
4180 	            if( SCIPsortedvecFindPtr((void**)tmpvars, SCIPvarComp, multvar, ntmpvars, &pos) )
4181 	            {
4182 	               assert(SCIPvarCompare(tmpvars[pos], multvar) == 0);
4183 	               tmpscalars[pos] += scalar * multscalar;
4184 	            }
4185 	            else
4186 	            {
4187 	               tmpvars2[ntmpvars2] = multvar;
4188 	               tmpscalars2[ntmpvars2] = scalar * multscalar;
4189 	               ++(ntmpvars2);
4190 	               assert(ntmpvars2 <= tmpvarssize2);
4191 	            }
4192 	         }
4193 	
4194 	         if( ntmpvars2 > 0 )
4195 	         {
4196 	            /* sort all variables to combine equal variables easily */
4197 	            SCIPsortPtrReal((void**)tmpvars2, tmpscalars2, SCIPvarComp, ntmpvars2);
4198 	            pos = 0;
4199 	            for( v = 1; v < ntmpvars2; ++v )
4200 	            {
4201 	               /* combine same variables */
4202 	               if( SCIPvarCompare(tmpvars2[v], tmpvars2[pos]) == 0 )
4203 	               {
4204 	                  tmpscalars2[pos] += tmpscalars2[v];
4205 	               }
4206 	               else
4207 	               {
4208 	                  ++pos;
4209 	                  if( v > pos )
4210 	                  {
4211 	                     tmpscalars2[pos] = tmpscalars2[v];
4212 	                     tmpvars2[pos] = tmpvars2[v];
4213 	                  }
4214 	               }
4215 	            }
4216 	            ntmpvars2 = pos + 1;
4217 	#ifdef SCIP_MORE_DEBUG
4218 	            for( v = 1; v < ntmpvars2; ++v )
4219 	            {
4220 	               assert(SCIPvarCompare(tmpvars2[v], tmpvars2[v-1]) > 0);
4221 	            }
4222 	            for( v = 1; v < ntmpvars; ++v )
4223 	            {
4224 	               assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4225 	            }
4226 	#endif
4227 	            v = ntmpvars - 1;
4228 	            k = ntmpvars2 - 1;
4229 	            pos = ntmpvars + ntmpvars2 - 1;
4230 	            ntmpvars += ntmpvars2;
4231 	
4232 	            while( v >= 0 && k >= 0 )
4233 	            {
4234 	               assert(pos >= 0);
4235 	               assert(SCIPvarCompare(tmpvars[v], tmpvars2[k]) != 0);
4236 	               if( SCIPvarCompare(tmpvars[v], tmpvars2[k]) >= 0 )
4237 	               {
4238 	                  tmpvars[pos] = tmpvars[v];
4239 	                  tmpscalars[pos] = tmpscalars[v];
4240 	                  --v;
4241 	               }
4242 	               else
4243 	               {
4244 	                  tmpvars[pos] = tmpvars2[k];
4245 	                  tmpscalars[pos] = tmpscalars2[k];
4246 	                  --k;
4247 	               }
4248 	               --pos;
4249 	               assert(pos >= 0);
4250 	            }
4251 	            while( v >= 0 )
4252 	            {
4253 	               assert(pos >= 0);
4254 	               tmpvars[pos] = tmpvars[v];
4255 	               tmpscalars[pos] = tmpscalars[v];
4256 	               --v;
4257 	               --pos;
4258 	            }
4259 	            while( k >= 0 )
4260 	            {
4261 	               assert(pos >= 0);
4262 	               tmpvars[pos] = tmpvars2[k];
4263 	               tmpscalars[pos] = tmpscalars2[k];
4264 	               --k;
4265 	               --pos;
4266 	            }
4267 	         }
4268 	#ifdef SCIP_MORE_DEBUG
4269 	         for( v = 1; v < ntmpvars; ++v )
4270 	         {
4271 	            assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4272 	         }
4273 	#endif
4274 	
4275 	         if( !activeconstantinf )
4276 	         {
4277 	            assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4278 	
4279 	            multconstant = SCIPvarGetMultaggrConstant(var);
4280 	
4281 	            if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4282 	            {
4283 	               assert(scalar != 0.0);
4284 	               if( scalar * multconstant > 0.0 )
4285 	               {
4286 	                  activeconstant = SCIPsetInfinity(set);
4287 	                  activeconstantinf = TRUE;
4288 	               }
4289 	               else
4290 	               {
4291 	                  activeconstant = -SCIPsetInfinity(set);
4292 	                  activeconstantinf = TRUE;
4293 	               }
4294 	            }
4295 	            else
4296 	               activeconstant += scalar * multconstant;
4297 	         }
4298 	#ifndef NDEBUG
4299 	         else
4300 	         {
4301 	            multconstant = SCIPvarGetMultaggrConstant(var);
4302 	            assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4303 	                  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4304 	            assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4305 	                  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4306 	         }
4307 	#endif
4308 	         break;
4309 	
4310 	      case SCIP_VARSTATUS_FIXED:
4311 	      case SCIP_VARSTATUS_ORIGINAL:
4312 	      case SCIP_VARSTATUS_AGGREGATED:
4313 	      case SCIP_VARSTATUS_NEGATED:
4314 	      default:
4315 	         /* case x = c, but actually we should not be here, since SCIPvarGetProbvarSum() returns a scalar of 0.0 for
4316 	          * fixed variables and is handled already
4317 	          */
4318 	         assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED);
4319 	         assert(SCIPsetIsZero(set, var->glbdom.lb) && SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub));
4320 	      }
4321 	   }
4322 	
4323 	   if( mergemultiples )
4324 	   {
4325 	      if( sortagain )
4326 	      {
4327 	         /* sort variable and scalar array by variable index */
4328 	         SCIPsortPtrReal((void**)activevars, activescalars, SCIPvarComp, nactivevars);
4329 	
4330 	         /* eliminate duplicates and count required size */
4331 	         v = nactivevars - 1;
4332 	         while( v > 0 )
4333 	         {
4334 	            /* combine both variable since they are the same */
4335 	            if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
4336 	            {
4337 	               if( activescalars[v - 1] + activescalars[v] != 0.0 )
4338 	               {
4339 	                  activescalars[v - 1] += activescalars[v];
4340 	                  --nactivevars;
4341 	                  activevars[v] = activevars[nactivevars];
4342 	                  activescalars[v] = activescalars[nactivevars];
4343 	               }
4344 	               else
4345 	               {
4346 	                  --nactivevars;
4347 	                  activevars[v] = activevars[nactivevars];
4348 	                  activescalars[v] = activescalars[nactivevars];
4349 	                  --nactivevars;
4350 	                  --v;
4351 	                  activevars[v] = activevars[nactivevars];
4352 	                  activescalars[v] = activescalars[nactivevars];
4353 	               }
4354 	            }
4355 	            --v;
4356 	         }
4357 	      }
4358 	      /* the variables were added in reverse order, we revert the order now;
4359 	       * this should not be necessary, but not doing this changes the behavior sometimes
4360 	       */
4361 	      else
4362 	      {
4363 	         SCIP_VAR* tmpvar;
4364 	         SCIP_Real tmpscalar;
4365 	
4366 	         for( v = 0; v < nactivevars / 2; ++v )
4367 	         {
4368 	            tmpvar = activevars[v];
4369 	            tmpscalar = activescalars[v];
4370 	            activevars[v] = activevars[nactivevars - 1 - v];
4371 	            activescalars[v] = activescalars[nactivevars - 1 - v];
4372 	            activevars[nactivevars - 1 - v] = tmpvar;
4373 	            activescalars[nactivevars - 1 - v] = tmpscalar;
4374 	         }
4375 	      }
4376 	   }
4377 	   *requiredsize = nactivevars;
4378 	
4379 	   if( varssize >= *requiredsize )
4380 	   {
4381 	      assert(vars != NULL);
4382 	
4383 	      *nvars = *requiredsize;
4384 	
4385 	      if( !SCIPsetIsInfinity(set, *constant) && !SCIPsetIsInfinity(set, -(*constant)) )
4386 	      {
4387 	         /* if the activeconstant is infinite, the constant pointer gets the same value, otherwise add the value */
4388 	         if( activeconstantinf )
4389 	            (*constant) = activeconstant;
4390 	         else
4391 	            (*constant) += activeconstant;
4392 	      }
4393 	#ifndef NDEBUG
4394 	      else
4395 	      {
4396 	         assert(!SCIPsetIsInfinity(set, (*constant)) || !SCIPsetIsInfinity(set, -activeconstant));
4397 	         assert(!SCIPsetIsInfinity(set, -(*constant)) || !SCIPsetIsInfinity(set, activeconstant));
4398 	      }
4399 	#endif
4400 	
4401 	      /* copy active variable and scalar array to the given arrays */
4402 	      for( v = 0; v < *nvars; ++v )
4403 	      {
4404 	         vars[v] = activevars[v];
4405 	         scalars[v] = activescalars[v]; /*lint !e613*/
4406 	      }
4407 	   }
4408 	
4409 	   assert(SCIPsetIsInfinity(set, *constant) == ((*constant) == SCIPsetInfinity(set))); /*lint !e777*/
4410 	   assert(SCIPsetIsInfinity(set, -(*constant)) == ((*constant) == -SCIPsetInfinity(set))); /*lint !e777*/
4411 	
4412 	   SCIPsetFreeBufferArray(set, &tmpscalars);
4413 	   SCIPsetFreeBufferArray(set, &tmpvars);
4414 	   SCIPsetFreeBufferArray(set, &activescalars);
4415 	   SCIPsetFreeBufferArray(set, &activevars);
4416 	   SCIPsetFreeBufferArray(set, &tmpscalars2);
4417 	   SCIPsetFreeBufferArray(set, &tmpvars2);
4418 	
4419 	   return SCIP_OKAY;
4420 	}
4421 	
4422 	
4423 	/** flattens aggregation graph of multi-aggregated variable in order to avoid exponential recursion later on */
4424 	SCIP_RETCODE SCIPvarFlattenAggregationGraph(
4425 	   SCIP_VAR*             var,                /**< problem variable */
4426 	   BMS_BLKMEM*           blkmem,             /**< block memory */
4427 	   SCIP_SET*             set,                /**< global SCIP settings */
4428 	   SCIP_EVENTQUEUE*      eventqueue          /**< event queue */
4429 	   )
4430 	{
4431 	   int nlocksup[NLOCKTYPES];
4432 	   int nlocksdown[NLOCKTYPES];
4433 	   SCIP_Real multconstant;
4434 	   int multvarssize;
4435 	   int nmultvars;
4436 	   int multrequiredsize;
4437 	   int i;
4438 	
4439 	   assert( var != NULL );
4440 	   assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR );
4441 	   assert(var->scip == set->scip);
4442 	
4443 	   /* in order to update the locks on the active representation of the multi-aggregated variable, we remove all locks
4444 	    * on the current representation now and re-add the locks once the variable graph has been flattened, which
4445 	    * may lead to duplicate occurences of the same variable being merged
4446 	    *
4447 	    * Here is an example. Assume we have the multi-aggregation z = x + y.
4448 	    * z occures with positive coefficient in a <= constraint c1, so it has an uplock from there.
4449 	    * When the multi-aggregation is performed, all locks are added to the active representation,
4450 	    * so x and y both get an uplock from c1. However, z was not yet replaced by x + y in c1.
4451 	    * Next, a negation y = 1 - x is identified. Again, locks are moved, so that the uplock of y originating
4452 	    * from c1 is added to x as a downlock. Thus, x has both an up- and downlock from c1.
4453 	    * The multi-aggregation changes to z = x + 1 - x, which corresponds to the locks.
4454 	    * However, before z is replaced by that sum, SCIPvarFlattenAggregationGraph() is called
4455 	    * which changes z = x + y = x + 1 - x = 1, since it merges multiple occurences of the same variable.
4456 	    * The up- and downlock of x, however, is not removed when replacing z in c1 by its active representation,
4457 	    * because it is just 1 now. Therefore, we need to update locks when flattening the aggregation graph.
4458 	    * For this, the multi-aggregated variable knows its locks in addition to adding them to the active
4459 	    * representation, which corresponds to the locks from constraints where the variable was not replaced yet.
4460 	    * By removing the locks here, based on the old representation and adding them again after flattening,
4461 	    * we ensure that the locks are correct afterwards if coefficients were merged.
4462 	    */
4463 	   for( i = 0; i < NLOCKTYPES; ++i )
4464 	   {
4465 	      nlocksup[i] = var->nlocksup[i];
4466 	      nlocksdown[i] = var->nlocksdown[i];
4467 	
4468 	      SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, -nlocksdown[i], -nlocksup[i]) );
4469 	   }
4470 	
4471 	   multconstant = var->data.multaggr.constant;
4472 	   nmultvars = var->data.multaggr.nvars;
4473 	   multvarssize = var->data.multaggr.varssize;
4474 	
4475 	   SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4476 	
4477 	   if( multrequiredsize > multvarssize )
4478 	   {
4479 	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.vars), multvarssize, multrequiredsize) );
4480 	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.scalars), multvarssize, multrequiredsize) );
4481 	      multvarssize = multrequiredsize;
4482 	      SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4483 	      assert( multrequiredsize <= multvarssize );
4484 	   }
4485 	   /**@note After the flattening the multi aggregation might resolve to be in fact an aggregation (or even a fixing?).
4486 	    * This issue is not resolved right now, since var->data.multaggr.nvars < 2 should not cause troubles. However, one
4487 	    * may loose performance hereby, since aggregated variables are easier to handle.
4488 	    *
4489 	    * Note, that there are two cases where SCIPvarFlattenAggregationGraph() is called: The easier one is that it is
4490 	    * called while installing the multi-aggregation. in principle, the described issue could be handled straightforward
4491 	    * in this case by aggregating or fixing the variable instead.  The more complicated case is the one, when the
4492 	    * multi-aggregation is used, e.g., in linear presolving (and the variable is already declared to be multi-aggregated).
4493 	    *
4494 	    * By now, it is not allowed to fix or aggregate multi-aggregated variables which would be necessary in this case.
4495 	    *
4496 	    * The same issue appears in the SCIPvarGetProbvar...() methods.
4497 	    */
4498 	
4499 	   var->data.multaggr.constant = multconstant;
4500 	   var->data.multaggr.nvars = nmultvars;
4501 	   var->data.multaggr.varssize = multvarssize;
4502 	
4503 	   for( i = 0; i < NLOCKTYPES; ++i )
4504 	   {
4505 	      SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
4506 	   }
4507 	
4508 	   return SCIP_OKAY;
4509 	}
4510 	
4511 	/** merge two variable histories together; a typical use case is that \p othervar is an image of the target variable
4512 	 *  in a SCIP copy. Method should be applied with care, especially because no internal checks are performed whether
4513 	 *  the history merge is reasonable
4514 	 *
4515 	 *  @note Do not use this method if the two variables originate from two SCIP's with different objective functions, since
4516 	 *        this corrupts the variable pseudo costs
4517 	 *  @note Apply with care; no internal checks are performed if the two variables should be merged
4518 	 */
4519 	void SCIPvarMergeHistories(
4520 	   SCIP_VAR*             targetvar,          /**< the variable that should contain both histories afterwards */
4521 	   SCIP_VAR*             othervar,           /**< the variable whose history is to be merged with that of the target variable */
4522 	   SCIP_STAT*            stat                /**< problem statistics */
4523 	   )
4524 	{
4525 	   /* merge only the history of the current run into the target history */
4526 	   SCIPhistoryUnite(targetvar->history, othervar->historycrun, FALSE);
4527 	
4528 	   /* apply the changes also to the global history */
4529 	   SCIPhistoryUnite(stat->glbhistory, othervar->historycrun, FALSE);
4530 	}
4531 	
4532 	/** sets the history of a variable; this method is typically used within reoptimization to keep and update the variable
4533 	 *  history over several iterations
4534 	 */
4535 	void SCIPvarSetHistory(
4536 	   SCIP_VAR*             var,                /**< variable */
4537 	   SCIP_HISTORY*         history,            /**< the history which is to set */
4538 	   SCIP_STAT*            stat                /**< problem statistics */
4539 	   )
4540 	{
4541 	   /* merge only the history of the current run into the target history */
4542 	   SCIPhistoryUnite(var->history, history, FALSE);
4543 	
4544 	   /* apply the changes also to the global history */
4545 	   SCIPhistoryUnite(stat->glbhistory, history, FALSE);
4546 	}
4547 	
4548 	/** tightens the bounds of both variables in aggregation x = a*y + c */
4549 	static
4550 	SCIP_RETCODE varUpdateAggregationBounds(
4551 	   SCIP_VAR*             var,                /**< problem variable */
4552 	   BMS_BLKMEM*           blkmem,             /**< block memory */
4553 	   SCIP_SET*             set,                /**< global SCIP settings */
4554 	   SCIP_STAT*            stat,               /**< problem statistics */
4555 	   SCIP_PROB*            transprob,          /**< tranformed problem data */
4556 	   SCIP_PROB*            origprob,           /**< original problem data */
4557 	   SCIP_PRIMAL*          primal,             /**< primal data */
4558 	   SCIP_TREE*            tree,               /**< branch and bound tree */
4559 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
4560 	   SCIP_LP*              lp,                 /**< current LP data */
4561 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
4562 	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter for global (not variable dependent) events */
4563 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
4564 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
4565 	   SCIP_VAR*             aggvar,             /**< variable y in aggregation x = a*y + c */
4566 	   SCIP_Real             scalar,             /**< multiplier a in aggregation x = a*y + c */
4567 	   SCIP_Real             constant,           /**< constant shift c in aggregation x = a*y + c */
4568 	   SCIP_Bool*            infeasible,         /**< pointer to store whether the aggregation is infeasible */
4569 	   SCIP_Bool*            fixed               /**< pointer to store whether the variables were fixed */
4570 	   )
4571 	{
4572 	   SCIP_Real varlb;
4573 	   SCIP_Real varub;
4574 	   SCIP_Real aggvarlb;
4575 	   SCIP_Real aggvarub;
4576 	   SCIP_Bool aggvarbdschanged;
4577 	
4578 	   assert(var != NULL);
4579 	   assert(var->scip == set->scip);
4580 	   assert(aggvar != NULL);
4581 	   assert(!SCIPsetIsZero(set, scalar));
4582 	   assert(infeasible != NULL);
4583 	   assert(fixed != NULL);
4584 	
4585 	   *infeasible = FALSE;
4586 	   *fixed = FALSE;
4587 	
4588 	   SCIPsetDebugMsg(set, "updating bounds of variables in aggregation <%s> == %g*<%s> %+g\n", var->name, scalar, aggvar->name, constant);
4589 	   SCIPsetDebugMsg(set, "  old bounds: <%s> [%g,%g]   <%s> [%g,%g]\n",
4590 	      var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4591 	
4592 	   /* loop as long additional changes may be found */
4593 	   do
4594 	   {
4595 	      aggvarbdschanged = FALSE;
4596 	
4597 	      /* update the bounds of the aggregated variable x in x = a*y + c */
4598 	      if( scalar > 0.0 )
4599 	      {
4600 	         if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4601 	            varlb = -SCIPsetInfinity(set);
4602 	         else
4603 	            varlb = aggvar->glbdom.lb * scalar + constant;
4604 	         if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4605 	            varub = SCIPsetInfinity(set);
4606 	         else
4607 	            varub = aggvar->glbdom.ub * scalar + constant;
4608 	      }
4609 	      else
4610 	      {
4611 	         if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4612 	            varub = SCIPsetInfinity(set);
4613 	         else
4614 	            varub = aggvar->glbdom.lb * scalar + constant;
4615 	         if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4616 	            varlb = -SCIPsetInfinity(set);
4617 	         else
4618 	            varlb = aggvar->glbdom.ub * scalar + constant;
4619 	      }
4620 	      varlb = MAX(varlb, var->glbdom.lb);
4621 	      varub = MIN(varub, var->glbdom.ub);
4622 	      SCIPvarAdjustLb(var, set, &varlb);
4623 	      SCIPvarAdjustUb(var, set, &varub);
4624 	
4625 	      /* check the new bounds */
4626 	      if( SCIPsetIsGT(set, varlb, varub) )
4627 	      {
4628 	         /* the aggregation is infeasible */
4629 	         *infeasible = TRUE;
4630 	         return SCIP_OKAY;
4631 	      }
4632 	      else if( SCIPsetIsEQ(set, varlb, varub) )
4633 	      {
4634 	         /* the aggregated variable is fixed -> fix both variables */
4635 	         SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4636 	               eventfilter, eventqueue, cliquetable, varlb, infeasible, fixed) );
4637 	         if( !(*infeasible) )
4638 	         {
4639 	            SCIP_Bool aggfixed;
4640 	
4641 	            SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4642 	                  eventfilter, eventqueue, cliquetable, (varlb-constant)/scalar, infeasible, &aggfixed) );
4643 	            assert(*fixed == aggfixed);
4644 	         }
4645 	         return SCIP_OKAY;
4646 	      }
4647 	      else
4648 	      {
4649 	         if( SCIPsetIsGT(set, varlb, var->glbdom.lb) )
4650 	         {
4651 	            SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varlb) );
4652 	         }
4653 	         if( SCIPsetIsLT(set, varub, var->glbdom.ub) )
4654 	         {
4655 	            SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varub) );
4656 	         }
4657 	
4658 	         /* update the hole list of the aggregation variable */
4659 	         /**@todo update hole list of aggregation variable */
4660 	      }
4661 	
4662 	      /* update the bounds of the aggregation variable y in x = a*y + c  ->  y = (x-c)/a */
4663 	      if( scalar > 0.0 )
4664 	      {
4665 	         if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4666 	            aggvarlb = -SCIPsetInfinity(set);
4667 	         else
4668 	            aggvarlb = (var->glbdom.lb - constant) / scalar;
4669 	         if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4670 	            aggvarub = SCIPsetInfinity(set);
4671 	         else
4672 	            aggvarub = (var->glbdom.ub - constant) / scalar;
4673 	      }
4674 	      else
4675 	      {
4676 	         if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4677 	            aggvarub = SCIPsetInfinity(set);
4678 	         else
4679 	            aggvarub = (var->glbdom.lb - constant) / scalar;
4680 	         if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4681 	            aggvarlb = -SCIPsetInfinity(set);
4682 	         else
4683 	            aggvarlb = (var->glbdom.ub - constant) / scalar;
4684 	      }
4685 	      aggvarlb = MAX(aggvarlb, aggvar->glbdom.lb);
4686 	      aggvarub = MIN(aggvarub, aggvar->glbdom.ub);
4687 	      SCIPvarAdjustLb(aggvar, set, &aggvarlb);
4688 	      SCIPvarAdjustUb(aggvar, set, &aggvarub);
4689 	
4690 	      /* check the new bounds */
4691 	      if( SCIPsetIsGT(set, aggvarlb, aggvarub) )
4692 	      {
4693 	         /* the aggregation is infeasible */
4694 	         *infeasible = TRUE;
4695 	         return SCIP_OKAY;
4696 	      }
4697 	      else if( SCIPsetIsEQ(set, aggvarlb, aggvarub) )
4698 	      {
4699 	         /* the aggregation variable is fixed -> fix both variables */
4700 	         SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4701 	               eventfilter, eventqueue, cliquetable, aggvarlb, infeasible, fixed) );
4702 	         if( !(*infeasible) )
4703 	         {
4704 	            SCIP_Bool varfixed;
4705 	
4706 	            SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4707 	                  eventfilter, eventqueue, cliquetable, aggvarlb * scalar + constant, infeasible, &varfixed) );
4708 	            assert(*fixed == varfixed);
4709 	         }
4710 	         return SCIP_OKAY;
4711 	      }
4712 	      else
4713 	      {
4714 	         SCIP_Real oldbd;
4715 	         if( SCIPsetIsGT(set, aggvarlb, aggvar->glbdom.lb) )
4716 	         {
4717 	            oldbd = aggvar->glbdom.lb;
4718 	            SCIP_CALL( SCIPvarChgLbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarlb) );
4719 	            aggvarbdschanged = !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.lb);
4720 	         }
4721 	         if( SCIPsetIsLT(set, aggvarub, aggvar->glbdom.ub) )
4722 	         {
4723 	            oldbd = aggvar->glbdom.ub;
4724 	            SCIP_CALL( SCIPvarChgUbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarub) );
4725 	            aggvarbdschanged = aggvarbdschanged || !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.ub);
4726 	         }
4727 	
4728 	         /* update the hole list of the aggregation variable */
4729 	         /**@todo update hole list of aggregation variable */
4730 	      }
4731 	   }
4732 	   while( aggvarbdschanged );
4733 	
4734 	   SCIPsetDebugMsg(set, "  new bounds: <%s> [%g,%g]   <%s> [%g,%g]\n",
4735 	      var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4736 	
4737 	   return SCIP_OKAY;
4738 	}
4739 	
4740 	/** converts loose variable into aggregated variable */
4741 	SCIP_RETCODE SCIPvarAggregate(
4742 	   SCIP_VAR*             var,                /**< loose problem variable */
4743 	   BMS_BLKMEM*           blkmem,             /**< block memory */
4744 	   SCIP_SET*             set,                /**< global SCIP settings */
4745 	   SCIP_STAT*            stat,               /**< problem statistics */
4746 	   SCIP_PROB*            transprob,          /**< tranformed problem data */
4747 	   SCIP_PROB*            origprob,           /**< original problem data */
4748 	   SCIP_PRIMAL*          primal,             /**< primal data */
4749 	   SCIP_TREE*            tree,               /**< branch and bound tree */
4750 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
4751 	   SCIP_LP*              lp,                 /**< current LP data */
4752 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
4753 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
4754 	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter for global (not variable dependent) events */
4755 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
4756 	   SCIP_VAR*             aggvar,             /**< loose variable y in aggregation x = a*y + c */
4757 	   SCIP_Real             scalar,             /**< multiplier a in aggregation x = a*y + c */
4758 	   SCIP_Real             constant,           /**< constant shift c in aggregation x = a*y + c */
4759 	   SCIP_Bool*            infeasible,         /**< pointer to store whether the aggregation is infeasible */
4760 	   SCIP_Bool*            aggregated          /**< pointer to store whether the aggregation was successful */
4761 	   )
4762 	{
4763 	   SCIP_VAR** vars;
4764 	   SCIP_Real* coefs;
4765 	   SCIP_Real* constants;
4766 	   SCIP_Real obj;
4767 	   SCIP_Real branchfactor;
4768 	   SCIP_Bool fixed;
4769 	   int branchpriority;
4770 	   int nlocksdown[NLOCKTYPES];
4771 	   int nlocksup[NLOCKTYPES];
4772 	   int nvbds;
4773 	   int i;
4774 	   int j;
4775 	
4776 	   assert(var != NULL);
4777 	   assert(aggvar != NULL);
4778 	   assert(var->scip == set->scip);
4779 	   assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
4780 	   assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
4781 	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
4782 	   assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
4783 	   assert(infeasible != NULL);
4784 	   assert(aggregated != NULL);
4785 	
4786 	   *infeasible = FALSE;
4787 	   *aggregated = FALSE;
4788 	
4789 	   /* get active problem variable of aggregation variable */
4790 	   SCIP_CALL( SCIPvarGetProbvarSum(&aggvar, set, &scalar, &constant) );
4791 	
4792 	   /* aggregation is a fixing, if the scalar is zero */
4793 	   if( SCIPsetIsZero(set, scalar) )
4794 	   {
4795 	      SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventfilter,
4796 	            eventqueue, cliquetable, constant, infeasible, aggregated) );
4797 	      goto TERMINATE;
4798 	   }
4799 	
4800 	   /* don't perform the aggregation if the aggregation variable is multi-aggregated itself */
4801 	   if( SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_MULTAGGR )
4802 	      return SCIP_OKAY;
4803 	
4804 	   /**@todo currently we don't perform the aggregation if the aggregation variable has a non-empty hole list; this
4805 	    *  should be changed in the future
4806 	    */
4807 	   if( SCIPvarGetHolelistGlobal(var) != NULL )
4808 	      return SCIP_OKAY;
4809 	
4810 	   /* if the variable is not allowed to be aggregated */
4811 	   if( SCIPvarDoNotAggr(var) )
4812 	   {
4813 	      SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
4814 	      return SCIP_OKAY;
4815 	   }
4816 	
4817 	   assert(aggvar->glbdom.lb == aggvar->locdom.lb); /*lint !e777*/
4818 	   assert(aggvar->glbdom.ub == aggvar->locdom.ub); /*lint !e777*/
4819 	   assert(SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_LOOSE);
4820 	
4821 	   SCIPsetDebugMsg(set, "aggregate variable <%s>[%g,%g] == %g*<%s>[%g,%g] %+g\n", var->name, var->glbdom.lb, var->glbdom.ub,
4822 	      scalar, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub, constant);
4823 	
4824 	   /* if variable and aggregation variable are equal, the variable can be fixed: x == a*x + c  =>  x == c/(1-a) */
4825 	   if( var == aggvar )
4826 	   {
4827 	      if( SCIPsetIsEQ(set, scalar, 1.0) )
4828 	         *infeasible = !SCIPsetIsZero(set, constant);
4829 	      else
4830 	      {
4831 	         SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4832 	               eventfilter, eventqueue, cliquetable, constant/(1.0-scalar), infeasible, aggregated) );
4833 	      }
4834 	      goto TERMINATE;
4835 	   }
4836 	
4837 	   /* tighten the bounds of aggregated and aggregation variable */
4838 	   SCIP_CALL( varUpdateAggregationBounds(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
4839 	         branchcand, eventfilter, eventqueue, cliquetable, aggvar, scalar, constant, infeasible, &fixed) );
4840 	   if( *infeasible || fixed )
4841 	   {
4842 	      *aggregated = fixed;
4843 	      goto TERMINATE;
4844 	   }
4845 	
4846 	   /* delete implications and variable bounds of the aggregated variable from other variables, but keep them in the
4847 	    * aggregated variable
4848 	    */
4849 	   SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, FALSE) );
4850 	
4851 	   /* set the aggregated variable's objective value to 0.0 */
4852 	   obj = var->obj;
4853 	   SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
4854 	
4855 	   /* unlock all locks */
4856 	   for( i = 0; i < NLOCKTYPES; i++ )
4857 	   {
4858 	      nlocksdown[i] = var->nlocksdown[i];
4859 	      nlocksup[i] = var->nlocksup[i];
4860 	
4861 	      var->nlocksdown[i] = 0;
4862 	      var->nlocksup[i] = 0;
4863 	   }
4864 	
4865 	   /* check, if variable should be used as NEGATED variable of the aggregation variable */
4866 	   if( SCIPvarIsBinary(var) && SCIPvarIsBinary(aggvar)
4867 	      && var->negatedvar == NULL && aggvar->negatedvar == NULL
4868 	      && SCIPsetIsEQ(set, scalar, -1.0) && SCIPsetIsEQ(set, constant, 1.0) )
4869 	   {
4870 	      /* link both variables as negation pair */
4871 	      var->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
4872 	      var->data.negate.constant = 1.0;
4873 	      var->negatedvar = aggvar;
4874 	      aggvar->negatedvar = var;
4875 	
4876 	      /* copy donot(mult)aggr status */
4877 	      aggvar->donotaggr |= var->donotaggr;
4878 	      aggvar->donotmultaggr |= var->donotmultaggr;
4879 	
4880 	      /* mark both variables to be non-deletable */
4881 	      SCIPvarMarkNotDeletable(var);
4882 	      SCIPvarMarkNotDeletable(aggvar);
4883 	   }
4884 	   else
4885 	   {
4886 	      /* convert variable into aggregated variable */
4887 	      var->varstatus = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
4888 	      var->data.aggregate.var = aggvar;
4889 	      var->data.aggregate.scalar = scalar;
4890 	      var->data.aggregate.constant = constant;
4891 	
4892 	      /* copy donot(mult)aggr status */
4893 	      aggvar->donotaggr |= var->donotaggr;
4894 	      aggvar->donotmultaggr |= var->donotmultaggr;
4895 	
4896 	      /* mark both variables to be non-deletable */
4897 	      SCIPvarMarkNotDeletable(var);
4898 	      SCIPvarMarkNotDeletable(aggvar);
4899 	   }
4900 	
4901 	   /* make aggregated variable a parent of the aggregation variable */
4902 	   SCIP_CALL( varAddParent(aggvar, blkmem, set, var) );
4903 	
4904 	   /* relock the variable, thus increasing the locks of the aggregation variable */
4905 	   for( i = 0; i < NLOCKTYPES; i++ )
4906 	   {
4907 	      SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
4908 	   }
4909 	
4910 	   /* move the variable bounds to the aggregation variable:
4911 	    *  - add all variable bounds again to the variable, thus adding it to the aggregation variable
4912 	    *  - free the variable bounds data structures
4913 	    */
4914 	   if( var->vlbs != NULL )
4915 	   {
4916 	      nvbds = SCIPvboundsGetNVbds(var->vlbs);
4917 	      vars = SCIPvboundsGetVars(var->vlbs);
4918 	      coefs = SCIPvboundsGetCoefs(var->vlbs);
4919 	      constants = SCIPvboundsGetConstants(var->vlbs);
4920 	      for( i = 0; i < nvbds && !(*infeasible); ++i )
4921 	      {
4922 	         SCIP_CALL( SCIPvarAddVlb(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4923 	               eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4924 	      }
4925 	   }
4926 	   if( var->vubs != NULL )
4927 	   {
4928 	      nvbds = SCIPvboundsGetNVbds(var->vubs);
4929 	      vars = SCIPvboundsGetVars(var->vubs);
4930 	      coefs = SCIPvboundsGetCoefs(var->vubs);
4931 	      constants = SCIPvboundsGetConstants(var->vubs);
4932 	      for( i = 0; i < nvbds && !(*infeasible); ++i )
4933 	      {
4934 	         SCIP_CALL( SCIPvarAddVub(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4935 	               eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4936 	      }
4937 	   }
4938 	   SCIPvboundsFree(&var->vlbs, blkmem);
4939 	   SCIPvboundsFree(&var->vubs, blkmem);
4940 	
4941 	   /* move the implications to the aggregation variable:
4942 	    *  - add all implications again to the variable, thus adding it to the aggregation variable
4943 	    *  - free the implications data structures
4944 	    */
4945 	   if( var->implics != NULL && SCIPvarGetType(aggvar) == SCIP_VARTYPE_BINARY )
4946 	   {
4947 	      assert(SCIPvarIsBinary(var));
4948 	      for( i = 0; i < 2; ++i )
4949 	      {
4950 	         SCIP_VAR** implvars;
4951 	         SCIP_BOUNDTYPE* impltypes;
4952 	         SCIP_Real* implbounds;
4953 	         int nimpls;
4954 	
4955 	         nimpls = SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i);
4956 	         implvars = SCIPimplicsGetVars(var->implics, (SCIP_Bool)i);
4957 	         impltypes = SCIPimplicsGetTypes(var->implics, (SCIP_Bool)i);
4958 	         implbounds = SCIPimplicsGetBounds(var->implics, (SCIP_Bool)i);
4959 	
4960 	         for( j = 0; j < nimpls && !(*infeasible); ++j )
4961 	         {
4962 	            /* @todo can't we omit transitive closure, because it should already have been done when adding the
4963 	             *       implication to the aggregated variable?
4964 	             */
4965 	            SCIP_CALL( SCIPvarAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
4966 	                  branchcand, eventqueue, (SCIP_Bool)i, implvars[j], impltypes[j], implbounds[j], FALSE, infeasible,
4967 	                  NULL) );
4968 	            assert(nimpls == SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i));
4969 	         }
4970 	      }
4971 	   }
4972 	   SCIPimplicsFree(&var->implics, blkmem);
4973 	
4974 	   /* add the history entries to the aggregation variable and clear the history of the aggregated variable */
4975 	   SCIPhistoryUnite(aggvar->history, var->history, scalar < 0.0);
4976 	   SCIPhistoryUnite(aggvar->historycrun, var->historycrun, scalar < 0.0);
4977 	   SCIPhistoryReset(var->history);
4978 	   SCIPhistoryReset(var->historycrun);
4979 	
4980 	   /* update flags of aggregation variable */
4981 	   aggvar->removable &= var->removable;
4982 	
4983 	   /* update branching factors and priorities of both variables to be the maximum of both variables */
4984 	   branchfactor = MAX(aggvar->branchfactor, var->branchfactor);
4985 	   branchpriority = MAX(aggvar->branchpriority, var->branchpriority);
4986 	   SCIP_CALL( SCIPvarChgBranchFactor(aggvar, set, branchfactor) );
4987 	   SCIP_CALL( SCIPvarChgBranchPriority(aggvar, branchpriority) );
4988 	   SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
4989 	   SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
4990 	
4991 	   /* update branching direction of both variables to agree to a single direction */
4992 	   if( scalar >= 0.0 )
4993 	   {
4994 	      if( (SCIP_BRANCHDIR)var->branchdirection == SCIP_BRANCHDIR_AUTO )
4995 	      {
4996 	         SCIP_CALL( SCIPvarChgBranchDirection(var, (SCIP_BRANCHDIR)aggvar->branchdirection) );
4997 	      }
4998 	      else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
4999 	      {
5000 	         SCIP_CALL( SCIPvarChgBranchDirection(aggvar, (SCIP_BRANCHDIR)var->branchdirection) );
5001 	      }
5002 	      else if( var->branchdirection != aggvar->branchdirection )
5003 	      {
5004 	         SCIP_CALL( SCIPvarChgBranchDirection(var, SCIP_BRANCHDIR_AUTO) );
5005 	      }
5006 	   }
5007 	   else
5008 	   {
5009 	      if( (SCIP_BRANCHDIR)var->branchdirection == SCIP_BRANCHDIR_AUTO )
5010 	      {
5011 	         SCIP_CALL( SCIPvarChgBranchDirection(var, SCIPbranchdirOpposite((SCIP_BRANCHDIR)aggvar->branchdirection)) );
5012 	      }
5013 	      else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
5014 	      {
5015 	         SCIP_CALL( SCIPvarChgBranchDirection(aggvar, SCIPbranchdirOpposite((SCIP_BRANCHDIR)var->branchdirection)) );
5016 	      }
5017 	      else if( var->branchdirection != aggvar->branchdirection )
5018 	      {
5019 	         SCIP_CALL( SCIPvarChgBranchDirection(var, SCIP_BRANCHDIR_AUTO) );
5020 	      }
5021 	   }
5022 	
5023 	   if( var->probindex != -1 )
5024 	   {
5025 	      /* inform problem about the variable's status change */
5026 	      SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5027 	   }
5028 	
5029 	   /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5030 	    * variable and the problem's objective offset
5031 	    */
5032 	   SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
5033 	
5034 	   /* issue VARFIXED event */
5035 	   SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 1) );
5036 	
5037 	   *aggregated = TRUE;
5038 	
5039 	TERMINATE:
5040 	   /* check aggregation on debugging solution */
5041 	   if( *infeasible || *aggregated )
5042 	      SCIP_CALL( SCIPdebugCheckAggregation(set, var, &aggvar, &scalar, constant, 1) ); /*lint !e506 !e774*/
5043 	
5044 	   return SCIP_OKAY;
5045 	}
5046 	
5047 	/** Tries to aggregate an equality a*x + b*y == c consisting of two (implicit) integral active problem variables x and
5048 	 *  y. An integer aggregation (i.e. integral coefficients a' and b', such that a'*x + b'*y == c') is searched.
5049 	 *
5050 	 *  This can lead to the detection of infeasibility (e.g. if c' is fractional), or to a rejection of the aggregation
5051 	 *  (denoted by aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
5052 	 */
5053 	static
5054 	SCIP_RETCODE tryAggregateIntVars(
5055 	   SCIP_SET*             set,                /**< global SCIP settings */
5056 	   BMS_BLKMEM*           blkmem,             /**< block memory */
5057 	   SCIP_STAT*            stat,               /**< problem statistics */
5058 	   SCIP_PROB*            transprob,          /**< tranformed problem data */
5059 	   SCIP_PROB*            origprob,           /**< original problem data */
5060 	   SCIP_PRIMAL*          primal,             /**< primal data */
5061 	   SCIP_TREE*            tree,               /**< branch and bound tree */
5062 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
5063 	   SCIP_LP*              lp,                 /**< current LP data */
5064 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
5065 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
5066 	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter for global (not variable dependent) events */
5067 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
5068 	   SCIP_VAR*             varx,               /**< integral variable x in equality a*x + b*y == c */
5069 	   SCIP_VAR*             vary,               /**< integral variable y in equality a*x + b*y == c */
5070 	   SCIP_Real             scalarx,            /**< multiplier a in equality a*x + b*y == c */
5071 	   SCIP_Real             scalary,            /**< multiplier b in equality a*x + b*y == c */
5072 	   SCIP_Real             rhs,                /**< right hand side c in equality a*x + b*y == c */
5073 	   SCIP_Bool*            infeasible,         /**< pointer to store whether the aggregation is infeasible */
5074 	   SCIP_Bool*            aggregated          /**< pointer to store whether the aggregation was successful */
5075 	   )
5076 	{
5077 	   SCIP_VAR* aggvar;
5078 	   char aggvarname[SCIP_MAXSTRLEN];
5079 	   SCIP_Longint scalarxn = 0;
5080 	   SCIP_Longint scalarxd = 0;
5081 	   SCIP_Longint scalaryn = 0;
5082 	   SCIP_Longint scalaryd = 0;
5083 	   SCIP_Longint a;
5084 	   SCIP_Longint b;
5085 	   SCIP_Longint c;
5086 	   SCIP_Longint scm;
5087 	   SCIP_Longint gcd;
5088 	   SCIP_Longint currentclass;
5089 	   SCIP_Longint classstep;
5090 	   SCIP_Longint xsol;
5091 	   SCIP_Longint ysol;
5092 	   SCIP_Bool success;
5093 	   SCIP_VARTYPE vartype;
5094 	
5095 	#define MAXDNOM 1000000LL
5096 	
5097 	   assert(set != NULL);
5098 	   assert(blkmem != NULL);
5099 	   assert(stat != NULL);
5100 	   assert(transprob != NULL);
5101 	   assert(origprob != NULL);
5102 	   assert(tree != NULL);
5103 	   assert(lp != NULL);
5104 	   assert(cliquetable != NULL);
5105 	   assert(branchcand != NULL);
5106 	   assert(eventqueue != NULL);
5107 	   assert(varx != NULL);
5108 	   assert(vary != NULL);
5109 	   assert(varx != vary);
5110 	   assert(infeasible != NULL);
5111 	   assert(aggregated != NULL);
5112 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
5113 	   assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
5114 	   assert(SCIPvarGetType(varx) == SCIP_VARTYPE_INTEGER || SCIPvarGetType(varx) == SCIP_VARTYPE_IMPLINT);
5115 	   assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
5116 	   assert(SCIPvarGetType(vary) == SCIP_VARTYPE_INTEGER || SCIPvarGetType(vary) == SCIP_VARTYPE_IMPLINT);
5117 	   assert(!SCIPsetIsZero(set, scalarx));
5118 	   assert(!SCIPsetIsZero(set, scalary));
5119 	
5120 	   *infeasible = FALSE;
5121 	   *aggregated = FALSE;
5122 	
5123 	   /* if the variable is not allowed to be aggregated */
5124 	   if( SCIPvarDoNotAggr(varx) )
5125 	   {
5126 	      SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
5127 	      return SCIP_OKAY;
5128 	   }
5129 	
5130 	   /* get rational representation of coefficients */
5131 	   success = SCIPrealToRational(scalarx, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalarxn, &scalarxd);
5132 	   if( success )
5133 	      success = SCIPrealToRational(scalary, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalaryn, &scalaryd);
5134 	   if( !success )
5135 	      return SCIP_OKAY;
5136 	   assert(scalarxd >= 1);
5137 	   assert(scalaryd >= 1);
5138 	
5139 	   /* multiply equality with smallest common denominator */
5140 	   scm = SCIPcalcSmaComMul(scalarxd, scalaryd);
5141 	   a = (scm/scalarxd)*scalarxn;
5142 	   b = (scm/scalaryd)*scalaryn;
5143 	   rhs *= scm;
5144 	
5145 	   /* divide equality by the greatest common divisor of a and b */
5146 	   gcd = SCIPcalcGreComDiv(ABS(a), ABS(b));
5147 	   a /= gcd;
5148 	   b /= gcd;
5149 	   rhs /= gcd;
5150 	   assert(a != 0);
5151 	   assert(b != 0);
5152 	
5153 	   /* check, if right hand side is integral */
5154 	   if( !SCIPsetIsFeasIntegral(set, rhs) )
5155 	   {
5156 	      *infeasible = TRUE;
5157 	      return SCIP_OKAY;
5158 	   }
5159 	   c = (SCIP_Longint)(SCIPsetFeasFloor(set, rhs));
5160 	
5161 	   /* check that the scalar and constant in the aggregation are not too large to avoid numerical problems */
5162 	   if( REALABS((SCIP_Real)(c/a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
5163 	      || REALABS((SCIP_Real)(b)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
5164 	      || REALABS((SCIP_Real)(a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
5165 	   {
5166 	      return SCIP_OKAY;
5167 	   }
5168 	
5169 	   /* check, if we are in an easy case with either |a| = 1 or |b| = 1 */
5170 	   if( (a == 1 || a == -1) && SCIPvarGetType(vary) == SCIP_VARTYPE_INTEGER )
5171 	   {
5172 	      /* aggregate x = - b/a*y + c/a */
5173 	      /*lint --e{653}*/
5174 	      SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5175 	            branchcand, eventfilter, eventqueue, vary, (SCIP_Real)(-b/a), (SCIP_Real)(c/a), infeasible, aggregated) );
5176 	      assert(*aggregated);
5177 	      return SCIP_OKAY;
5178 	   }
5179 	   if( (b == 1 || b == -1) && SCIPvarGetType(varx) == SCIP_VARTYPE_INTEGER )
5180 	   {
5181 	      /* aggregate y = - a/b*x + c/b */
5182 	      /*lint --e{653}*/
5183 	      SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5184 	            branchcand, eventfilter, eventqueue, varx, (SCIP_Real)(-a/b), (SCIP_Real)(c/b), infeasible, aggregated) );
5185 	      assert(*aggregated);
5186 	      return SCIP_OKAY;
5187 	   }
5188 	
5189 	   /* Both variables are integers, their coefficients are not multiples of each other, and they don't have any
5190 	    * common divisor. Let (x',y') be a solution of the equality
5191 	    *   a*x + b*y == c    ->   a*x == c - b*y
5192 	    * Then x = -b*z + x', y = a*z + y' with z integral gives all solutions to the equality.
5193 	    */
5194 	
5195 	   /* find initial solution (x',y'):
5196 	    *  - find y' such that c - b*y' is a multiple of a
5197 	    *    - start in equivalence class c%a
5198 	    *    - step through classes, where each step increases class number by (-b)%a, until class 0 is visited
5199 	    *    - if equivalence class 0 is visited, we are done: y' equals the number of steps taken
5200 	    *    - 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
5201 	    *  - calculate x' with x' = (c - b*y')/a (which must be integral)
5202 	    *
5203 	    * Algorithm works for a > 0 only.
5204 	    */
5205 	   if( a < 0 )
5206 	   {
5207 	      a = -a;
5208 	      b = -b;
5209 	      c = -c;
5210 	   }
5211 	   assert(a > 0);
5212 	
5213 	   /* search upwards from ysol = 0 */
5214 	   ysol = 0;
5215 	   currentclass = c % a;
5216 	   if( currentclass < 0 )
5217 	      currentclass += a;
5218 	   assert(0 <= currentclass && currentclass < a);
5219 	
5220 	   classstep = (-b) % a;
5221 	
5222 	   if( classstep < 0 )
5223 	      classstep += a;
5224 	   assert(0 <= classstep && classstep < a);
5225 	
5226 	   while( currentclass != 0 )
5227 	   {
5228 	      assert(0 <= currentclass && currentclass < a);
5229 	      currentclass += classstep;
5230 	      if( currentclass >= a )
5231 	         currentclass -= a;
5232 	      ysol++;
5233 	   }
5234 	   assert(ysol < a);
5235 	   assert(((c - b*ysol) % a) == 0);
5236 	
5237 	   xsol = (c - b*ysol)/a;
5238 	
5239 	   /* determine variable type for new artificial variable:
5240 	    *
5241 	    * if both variables are implicit integer the new variable can be implicit too, because the integer implication on
5242 	    * these both variables should be enforced by some other variables, otherwise the new variable needs to be of
5243 	    * integral type
5244 	    */
5245 	   vartype = ((SCIPvarGetType(varx) == SCIP_VARTYPE_INTEGER || SCIPvarGetType(vary) == SCIP_VARTYPE_INTEGER)
5246 	      ? SCIP_VARTYPE_INTEGER : SCIP_VARTYPE_IMPLINT);
5247 	
5248 	   /* feasible solutions are (x,y) = (x',y') + z*(-b,a)
5249 	    * - create new integer variable z with infinite bounds
5250 	    * - aggregate variable x = -b*z + x'
5251 	    * - aggregate variable y =  a*z + y'
5252 	    * - the bounds of z are calculated automatically during aggregation
5253 	    */
5254 	   (void) SCIPsnprintf(aggvarname, SCIP_MAXSTRLEN, "agg%d", stat->nvaridx);
5255 	   SCIP_CALL( SCIPvarCreateTransformed(&aggvar, blkmem, set, stat,
5256 	         aggvarname, -SCIPsetInfinity(set), SCIPsetInfinity(set), 0.0, vartype,
5257 	         SCIPvarIsInitial(varx) || SCIPvarIsInitial(vary), SCIPvarIsRemovable(varx) && SCIPvarIsRemovable(vary),
5258 	         NULL, NULL, NULL, NULL, NULL) );
5259 	
5260 	   SCIP_CALL( SCIPprobAddVar(transprob, blkmem, set, lp, branchcand, eventfilter, eventqueue, aggvar) );
5261 	
5262 	   SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5263 	         branchcand, eventfilter, eventqueue, aggvar, (SCIP_Real)(-b), (SCIP_Real)xsol, infeasible, aggregated) );
5264 	   assert(*aggregated || *infeasible);
5265 	
5266 	   if( !(*infeasible) )
5267 	   {
5268 	      SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5269 	            branchcand, eventfilter, eventqueue, aggvar, (SCIP_Real)a, (SCIP_Real)ysol, infeasible, aggregated) );
5270 	      assert(*aggregated || *infeasible);
5271 	   }
5272 	
5273 	   /* release z */
5274 	   SCIP_CALL( SCIPvarRelease(&aggvar, blkmem, set, eventqueue, lp) );
5275 	
5276 	   return SCIP_OKAY;  /*lint !e438*/
5277 	}
5278 	
5279 	/** performs second step of SCIPaggregateVars():
5280 	 *  the variable to be aggregated is chosen among active problem variables x' and y', preferring a less strict variable
5281 	 *  type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
5282 	 *  or integers over binaries). If none of the variables is continuous, it is tried to find an integer
5283 	 *  aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
5284 	 *  the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
5285 	 *  aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
5286 	 *
5287 	 *  @todo check for fixings, infeasibility, bound changes, or domain holes:
5288 	 *     a) if there is no easy aggregation and we have one binary variable and another integer/implicit/binary variable
5289 	 *     b) for implicit integer variables with fractional aggregation scalar (we cannot (for technical reasons) and do
5290 	 *        not want to aggregate implicit integer variables, since we loose the corresponding divisibility property)
5291 	 */
5292 	SCIP_RETCODE SCIPvarTryAggregateVars(
5293 	   SCIP_SET*             set,                /**< global SCIP settings */
5294 	   BMS_BLKMEM*           blkmem,             /**< block memory */
5295 	   SCIP_STAT*            stat,               /**< problem statistics */
5296 	   SCIP_PROB*            transprob,          /**< tranformed problem data */
5297 	   SCIP_PROB*            origprob,           /**< original problem data */
5298 	   SCIP_PRIMAL*          primal,             /**< primal data */
5299 	   SCIP_TREE*            tree,               /**< branch and bound tree */
5300 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
5301 	   SCIP_LP*              lp,                 /**< current LP data */
5302 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
5303 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
5304 	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter for global (not variable dependent) events */
5305 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
5306 	   SCIP_VAR*             varx,               /**< variable x in equality a*x + b*y == c */
5307 	   SCIP_VAR*             vary,               /**< variable y in equality a*x + b*y == c */
5308 	   SCIP_Real             scalarx,            /**< multiplier a in equality a*x + b*y == c */
5309 	   SCIP_Real             scalary,            /**< multiplier b in equality a*x + b*y == c */
5310 	   SCIP_Real             rhs,                /**< right hand side c in equality a*x + b*y == c */
5311 	   SCIP_Bool*            infeasible,         /**< pointer to store whether the aggregation is infeasible */
5312 	   SCIP_Bool*            aggregated          /**< pointer to store whether the aggregation was successful */
5313 	   )
5314 	{
5315 	   SCIP_Bool easyaggr;
5316 	
5317 	   assert(set != NULL);
5318 	   assert(blkmem != NULL);
5319 	   assert(stat != NULL);
5320 	   assert(transprob != NULL);
5321 	   assert(origprob != NULL);
5322 	   assert(tree != NULL);
5323 	   assert(lp != NULL);
5324 	   assert(cliquetable != NULL);
5325 	   assert(branchcand != NULL);
5326 	   assert(eventqueue != NULL);
5327 	   assert(varx != NULL);
5328 	   assert(vary != NULL);
5329 	   assert(varx != vary);
5330 	   assert(infeasible != NULL);
5331 	   assert(aggregated != NULL);
5332 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
5333 	   assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
5334 	   assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
5335 	   assert(!SCIPsetIsZero(set, scalarx));
5336 	   assert(!SCIPsetIsZero(set, scalary));
5337 	
5338 	   *infeasible = FALSE;
5339 	   *aggregated = FALSE;
5340 	
5341 	   if( SCIPsetIsZero(set, scalarx / scalary) || SCIPsetIsZero(set, scalary / scalarx) )
5342 	      return SCIP_OKAY;
5343 	
5344 	   /* prefer aggregating the variable of more general type (preferred aggregation variable is varx) */
5345 	   if( SCIPvarGetType(vary) > SCIPvarGetType(varx) ||
5346 	         (SCIPvarGetType(vary) == SCIPvarGetType(varx) && !SCIPvarIsBinary(vary) && SCIPvarIsBinary(varx))  )
5347 	   {
5348 	      SCIP_VAR* var;
5349 	      SCIP_Real scalar;
5350 	
5351 	      /* switch the variables, such that varx is the variable of more general type (cont > implint > int > bin) */
5352 	      var = vary;
5353 	      vary = varx;
5354 	      varx = var;
5355 	      scalar = scalary;
5356 	      scalary = scalarx;
5357 	      scalarx = scalar;
5358 	   }
5359 	
5360 	   /* don't aggregate if the aggregation would lead to a binary variable aggregated to a non-binary variable */
5361 	   if( SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary) )
5362 	      return SCIP_OKAY;
5363 	
5364 	   assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5365 	
5366 	   /* figure out, which variable should be aggregated */
5367 	   easyaggr = FALSE;
5368 	
5369 	   /* check if it is an easy aggregation */
5370 	   if( SCIPvarGetType(varx) == SCIP_VARTYPE_CONTINUOUS && SCIPvarGetType(vary) < SCIP_VARTYPE_CONTINUOUS )
5371 	   {
5372 	      easyaggr = TRUE;
5373 	   }
5374 	   else if( SCIPsetIsFeasIntegral(set, scalary/scalarx) )
5375 	   {
5376 	      easyaggr = TRUE;
5377 	   }
5378 	   else if( SCIPsetIsFeasIntegral(set, scalarx/scalary) && SCIPvarGetType(vary) == SCIPvarGetType(varx) )
5379 	   {
5380 	      /* we have an easy aggregation if we flip the variables x and y */
5381 	      SCIP_VAR* var;
5382 	      SCIP_Real scalar;
5383 	
5384 	      /* switch the variables, such that varx is the aggregated variable */
5385 	      var = vary;
5386 	      vary = varx;
5387 	      varx = var;
5388 	      scalar = scalary;
5389 	      scalary = scalarx;
5390 	      scalarx = scalar;
5391 	      easyaggr = TRUE;
5392 	   }
5393 	   else if( SCIPvarGetType(varx) == SCIP_VARTYPE_CONTINUOUS )
5394 	   {
5395 	      /* the aggregation is still easy if both variables are continuous */
5396 	      assert(SCIPvarGetType(vary) == SCIP_VARTYPE_CONTINUOUS); /* otherwise we are in the first case */
5397 	      easyaggr = TRUE;
5398 	   }
5399 	
5400 	   /* did we find an "easy" aggregation? */
5401 	   if( easyaggr )
5402 	   {
5403 	      SCIP_Real scalar;
5404 	      SCIP_Real constant;
5405 	
5406 	      assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5407 	
5408 	      /* calculate aggregation scalar and constant: a*x + b*y == c  =>  x == -b/a * y + c/a */
5409 	      scalar = -scalary/scalarx;
5410 	      constant = rhs/scalarx;
5411 	
5412 	      if( REALABS(constant) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
5413 	         return SCIP_OKAY;
5414 	
5415 	      /* check aggregation for integer feasibility */
5416 	      if( SCIPvarGetType(varx) != SCIP_VARTYPE_CONTINUOUS
5417 	         && SCIPvarGetType(vary) != SCIP_VARTYPE_CONTINUOUS
5418 	         && SCIPsetIsFeasIntegral(set, scalar) && !SCIPsetIsFeasIntegral(set, constant) )
5419 	      {
5420 	         *infeasible = TRUE;
5421 	         return SCIP_OKAY;
5422 	      }
5423 	
5424 	      /* if the aggregation scalar is fractional, we cannot (for technical reasons) and do not want to aggregate implicit integer variables,
5425 	       * since then we would loose the corresponding divisibility property
5426 	       */
5427 	      assert(SCIPvarGetType(varx) != SCIP_VARTYPE_IMPLINT || SCIPsetIsFeasIntegral(set, scalar));
5428 	
5429 	      /* aggregate the variable */
5430 	      SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5431 	            branchcand, eventfilter, eventqueue, vary, scalar, constant, infeasible, aggregated) );
5432 	      assert(*aggregated || *infeasible || SCIPvarDoNotAggr(varx));
5433 	   }
5434 	   else if( (SCIPvarGetType(varx) == SCIP_VARTYPE_INTEGER || SCIPvarGetType(varx) == SCIP_VARTYPE_IMPLINT)
5435 	      && (SCIPvarGetType(vary) == SCIP_VARTYPE_INTEGER || SCIPvarGetType(vary) == SCIP_VARTYPE_IMPLINT) )
5436 	   {
5437 	      /* the variables are both integral: we have to try to find an integer aggregation */
5438 	      SCIP_CALL( tryAggregateIntVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5439 	            branchcand, eventfilter, eventqueue, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
5440 	   }
5441 	
5442 	   return SCIP_OKAY;
5443 	}
5444 	
5445 	/** converts variable into multi-aggregated variable */
5446 	SCIP_RETCODE SCIPvarMultiaggregate(
5447 	   SCIP_VAR*             var,                /**< problem variable */
5448 	   BMS_BLKMEM*           blkmem,             /**< block memory */
5449 	   SCIP_SET*             set,                /**< global SCIP settings */
5450 	   SCIP_STAT*            stat,               /**< problem statistics */
5451 	   SCIP_PROB*            transprob,          /**< tranformed problem data */
5452 	   SCIP_PROB*            origprob,           /**< original problem data */
5453 	   SCIP_PRIMAL*          primal,             /**< primal data */
5454 	   SCIP_TREE*            tree,               /**< branch and bound tree */
5455 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
5456 	   SCIP_LP*              lp,                 /**< current LP data */
5457 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
5458 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
5459 	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter for global (not variable dependent) events */
5460 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
5461 	   int                   naggvars,           /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5462 	   SCIP_VAR**            aggvars,            /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5463 	   SCIP_Real*            scalars,            /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5464 	   SCIP_Real             constant,           /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5465 	   SCIP_Bool*            infeasible,         /**< pointer to store whether the aggregation is infeasible */
5466 	   SCIP_Bool*            aggregated          /**< pointer to store whether the aggregation was successful */
5467 	   )
5468 	{
5469 	   SCIP_VAR** tmpvars;
5470 	   SCIP_Real* tmpscalars;
5471 	   SCIP_Real obj;
5472 	   SCIP_Real branchfactor;
5473 	   int branchpriority;
5474 	   SCIP_BRANCHDIR branchdirection;
5475 	   int nlocksdown[NLOCKTYPES];
5476 	   int nlocksup[NLOCKTYPES];
5477 	   int v;
5478 	   SCIP_Real tmpconstant;
5479 	   SCIP_Real tmpscalar;
5480 	   int ntmpvars;
5481 	   int tmpvarssize;
5482 	   int tmprequiredsize;
5483 	   int i;
5484 	
5485 	   assert(var != NULL);
5486 	   assert(var->scip == set->scip);
5487 	   assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
5488 	   assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
5489 	   assert(naggvars == 0 || aggvars != NULL);
5490 	   assert(naggvars == 0 || scalars != NULL);
5491 	   assert(infeasible != NULL);
5492 	   assert(aggregated != NULL);
5493 	
5494 	   SCIPsetDebugMsg(set, "trying multi-aggregating variable <%s> == ...%d vars... %+g\n", var->name, naggvars, constant);
5495 	
5496 	   *infeasible = FALSE;
5497 	   *aggregated = FALSE;
5498 	
5499 	   switch( SCIPvarGetStatus(var) )
5500 	   {
5501 	   case SCIP_VARSTATUS_ORIGINAL:
5502 	      if( var->data.original.transvar == NULL )
5503 	      {
5504 	         SCIPerrorMessage("cannot multi-aggregate an untransformed original variable\n");
5505 	         return SCIP_INVALIDDATA;
5506 	      }
5507 	      SCIP_CALL( SCIPvarMultiaggregate(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
5508 	            reopt, lp, cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
5509 	      break;
5510 	
5511 	   case SCIP_VARSTATUS_LOOSE:
5512 	      assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
5513 	
5514 	      /* check if we would create a self-reference */
5515 	      ntmpvars = naggvars;
5516 	      tmpvarssize = naggvars;
5517 	      tmpconstant = constant;
5518 	      SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpvars, aggvars, ntmpvars) );
5519 	      SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpscalars, scalars, ntmpvars) );
5520 	
5521 	      /* get all active variables for multi-aggregation */
5522 	      SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5523 	      if( tmprequiredsize > tmpvarssize )
5524 	      {
5525 	         SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpvars, tmpvarssize, tmprequiredsize) );
5526 	         SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize, tmprequiredsize) );
5527 	         tmpvarssize = tmprequiredsize;
5528 	         SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5529 	         assert( tmprequiredsize <= tmpvarssize );
5530 	      }
5531 	
5532 	      tmpscalar = 0.0;
5533 	
5534 	      /* iterate over all active variables of the multi-aggregation and filter all variables which are equal to the
5535 	       * possible multi-aggregated variable
5536 	       */
5537 	      for( v = ntmpvars - 1; v >= 0; --v )
5538 	      {
5539 	         assert(tmpvars[v] != NULL);
5540 	         assert(SCIPvarGetStatus(tmpvars[v]) == SCIP_VARSTATUS_LOOSE);
5541 	
5542 	         if( tmpvars[v]->index == var->index )
5543 	         {
5544 	            tmpscalar += tmpscalars[v];
5545 	            tmpvars[v] = tmpvars[ntmpvars - 1];
5546 	            tmpscalars[v] = tmpscalars[ntmpvars - 1];
5547 	            --ntmpvars;
5548 	         }
5549 	      }
5550 	
5551 	      /* this means that x = x + a_1*y_1 + ... + a_n*y_n + c */
5552 	      if( SCIPsetIsEQ(set, tmpscalar, 1.0) )
5553 	      {
5554 	         if( ntmpvars == 0 )
5555 	         {
5556 	            if( SCIPsetIsZero(set, tmpconstant) ) /* x = x */
5557 	            {
5558 	               SCIPsetDebugMsg(set, "Possible multi-aggregation was completely resolved and detected to be redundant.\n");
5559 	               goto TERMINATE;
5560 	            }
5561 	            else /* 0 = c and c != 0 */
5562 	            {
5563 	               SCIPsetDebugMsg(set, "Multi-aggregation was completely resolved and led to infeasibility.\n");
5564 	               *infeasible = TRUE;
5565 	               goto TERMINATE;
5566 	            }
5567 	         }
5568 	         else if( ntmpvars == 1 ) /* 0 = a*y + c => y = -c/a */
5569 	         {
5570 	            assert(tmpscalars[0] != 0.0);
5571 	            assert(tmpvars[0] != NULL);
5572 	
5573 	            SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(tmpvars[0]), -constant/tmpscalars[0]);
5574 	            SCIP_CALL( SCIPvarFix(tmpvars[0], blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5575 	                  branchcand, eventfilter, eventqueue, cliquetable, -constant/tmpscalars[0], infeasible, aggregated) );
5576 	            goto TERMINATE;
5577 	         }
5578 	         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 */
5579 	         {
5580 	            /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
5581 	            SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5582 	                  SCIPvarGetName(tmpvars[0]), SCIPvarGetName(tmpvars[1]), tmpscalars[0], tmpscalars[1], -tmpconstant);
5583 	
5584 	            SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5585 	                  cliquetable, branchcand, eventfilter, eventqueue, tmpvars[0], tmpvars[1], tmpscalars[0],
5586 	                  tmpscalars[1], -tmpconstant, infeasible, aggregated) );
5587 	
5588 	            goto TERMINATE;
5589 	         }
5590 	         else
5591 	            /* @todo: it is possible to multi-aggregate another variable, does it make sense?,
5592 	             *        rest looks like 0 = a_1*y_1 + ... + a_n*y_n + c and has at least three variables
5593 	             */
5594 	            goto TERMINATE;
5595 	      }
5596 	      /* this means that x = b*x + a_1*y_1 + ... + a_n*y_n + c */
5597 	      else if( !SCIPsetIsZero(set, tmpscalar) )
5598 	      {
5599 	         tmpscalar = 1 - tmpscalar;
5600 	         tmpconstant /= tmpscalar;
5601 	         for( v = ntmpvars - 1; v >= 0; --v )
5602 	            tmpscalars[v] /= tmpscalar;
5603 	      }
5604 	
5605 	      /* check, if we are in one of the simple cases */
5606 	      if( ntmpvars == 0 )
5607 	      {
5608 	         SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(var), tmpconstant);
5609 	         SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
5610 	               eventfilter, eventqueue, cliquetable, tmpconstant, infeasible, aggregated) );
5611 	         goto TERMINATE;
5612 	      }
5613 	
5614 	      /* if only one aggregation variable is left, we perform a normal aggregation instead of a multi-aggregation */
5615 	      if( ntmpvars == 1 )
5616 	      {
5617 	         SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5618 	            SCIPvarGetName(var), SCIPvarGetName(tmpvars[0]), 1.0, -tmpscalars[0], tmpconstant);
5619 	
5620 	         SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5621 	               cliquetable, branchcand, eventfilter, eventqueue, var, tmpvars[0], 1.0, -tmpscalars[0], tmpconstant,
5622 	               infeasible, aggregated) );
5623 	
5624 	         goto TERMINATE;
5625 	      }
5626 	
5627 	      /**@todo currently we don't perform the multi aggregation if the multi aggregation variable has a non
5628 	       *  empty hole list; this should be changed in the future  */
5629 	      if( SCIPvarGetHolelistGlobal(var) != NULL )
5630 	         goto TERMINATE;
5631 	
5632 	      /* if the variable is not allowed to be multi-aggregated */
5633 	      if( SCIPvarDoNotMultaggr(var) )
5634 	      {
5635 	         SCIPsetDebugMsg(set, "variable is not allowed to be multi-aggregated.\n");
5636 	         goto TERMINATE;
5637 	      }
5638 	
5639 	      /* if the variable to be multi-aggregated has implications or variable bounds (i.e. is the implied variable or
5640 	       * variable bound variable of another variable), we have to remove it from the other variables implications or
5641 	       * variable bounds
5642 	       */
5643 	      SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5644 	      assert(var->vlbs == NULL);
5645 	      assert(var->vubs == NULL);
5646 	      assert(var->implics == NULL);
5647 	
5648 	      /* set the aggregated variable's objective value to 0.0 */
5649 	      obj = var->obj;
5650 	      SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
5651 	
5652 	      /* since we change the variable type form loose to multi aggregated, we have to adjust the number of loose
5653 	       * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
5654 	       * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
5655 	       * objective of this variable is set to zero
5656 	       */
5657 	      SCIPlpDecNLoosevars(lp);
5658 	
5659 	      /* unlock all rounding locks */
5660 	      for( i = 0; i < NLOCKTYPES; i++ )
5661 	      {
5662 	         nlocksdown[i] = var->nlocksdown[i];
5663 	         nlocksup[i] = var->nlocksup[i];
5664 	
5665 	         var->nlocksdown[i] = 0;
5666 	         var->nlocksup[i] = 0;
5667 	      }
5668 	
5669 	      /* convert variable into multi-aggregated variable */
5670 	      var->varstatus = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
5671 	      SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.vars, tmpvars, ntmpvars) );
5672 	      SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.scalars, tmpscalars, ntmpvars) );
5673 	      var->data.multaggr.constant = tmpconstant;
5674 	      var->data.multaggr.nvars = ntmpvars;
5675 	      var->data.multaggr.varssize = ntmpvars;
5676 	
5677 	      /* mark variable to be non-deletable */
5678 	      SCIPvarMarkNotDeletable(var);
5679 	
5680 	      /* relock the variable, thus increasing the locks of the aggregation variables */
5681 	      for( i = 0; i < NLOCKTYPES; i++ )
5682 	      {
5683 	         SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
5684 	      }
5685 	
5686 	      /* update flags and branching factors and priorities of aggregation variables;
5687 	       * update preferred branching direction of all aggregation variables that don't have a preferred direction yet
5688 	       */
5689 	      branchfactor = var->branchfactor;
5690 	      branchpriority = var->branchpriority;
5691 	      branchdirection = (SCIP_BRANCHDIR)var->branchdirection;
5692 	
5693 	      for( v = 0; v < ntmpvars; ++v )
5694 	      {
5695 	         assert(tmpvars[v] != NULL);
5696 	         tmpvars[v]->removable &= var->removable;
5697 	         branchfactor = MAX(tmpvars[v]->branchfactor, branchfactor);
5698 	         branchpriority = MAX(tmpvars[v]->branchpriority, branchpriority);
5699 	
5700 	         /* mark variable to be non-deletable */
5701 	         SCIPvarMarkNotDeletable(tmpvars[v]);
5702 	      }
5703 	      for( v = 0; v < ntmpvars; ++v )
5704 	      {
5705 	         SCIP_CALL( SCIPvarChgBranchFactor(tmpvars[v], set, branchfactor) );
5706 	         SCIP_CALL( SCIPvarChgBranchPriority(tmpvars[v], branchpriority) );
5707 	         if( (SCIP_BRANCHDIR)tmpvars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
5708 	         {
5709 	            if( tmpscalars[v] >= 0.0 )
5710 	            {
5711 	               SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], branchdirection) );
5712 	            }
5713 	            else
5714 	            {
5715 	               SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], SCIPbranchdirOpposite(branchdirection)) );
5716 	            }
5717 	         }
5718 	      }
5719 	      SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
5720 	      SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
5721 	
5722 	      if( var->probindex != -1 )
5723 	      {
5724 	         /* inform problem about the variable's status change */
5725 	         SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5726 	      }
5727 	
5728 	      /* issue VARFIXED event */
5729 	      SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 2) );
5730 	
5731 	      /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5732 	       * variables and the problem's objective offset
5733 	       */
5734 	      SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
5735 	
5736 	      *aggregated = TRUE;
5737 	
5738 	   TERMINATE:
5739 	      BMSfreeBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize);
5740 	      BMSfreeBlockMemoryArray(blkmem, &tmpvars, tmpvarssize);
5741 	
5742 	      break;
5743 	
5744 	   case SCIP_VARSTATUS_COLUMN:
5745 	      SCIPerrorMessage("cannot multi-aggregate a column variable\n");
5746 	      return SCIP_INVALIDDATA;
5747 	
5748 	   case SCIP_VARSTATUS_FIXED:
5749 	      SCIPerrorMessage("cannot multi-aggregate a fixed variable\n");
5750 	      return SCIP_INVALIDDATA;
5751 	
5752 	   case SCIP_VARSTATUS_AGGREGATED:
5753 	      SCIPerrorMessage("cannot multi-aggregate an aggregated variable\n");
5754 	      return SCIP_INVALIDDATA;
5755 	
5756 	   case SCIP_VARSTATUS_MULTAGGR:
5757 	      SCIPerrorMessage("cannot multi-aggregate a multiple aggregated variable again\n");
5758 	      return SCIP_INVALIDDATA;
5759 	
5760 	   case SCIP_VARSTATUS_NEGATED:
5761 	      /* aggregate negation variable x in x' = offset - x, instead of aggregating x' directly:
5762 	       *   x' = a_1*y_1 + ... + a_n*y_n + c  ->  x = offset - x' = offset - a_1*y_1 - ... - a_n*y_n - c
5763 	       */
5764 	      assert(SCIPsetIsZero(set, var->obj));
5765 	      assert(var->negatedvar != NULL);
5766 	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
5767 	      assert(var->negatedvar->negatedvar == var);
5768 	
5769 	      /* switch the signs of the aggregation scalars */
5770 	      for( v = 0; v < naggvars; ++v )
5771 	         scalars[v] *= -1.0;
5772 	
5773 	      /* perform the multi aggregation on the negation variable */
5774 	      SCIP_CALL( SCIPvarMultiaggregate(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5775 	            cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars,
5776 	            var->data.negate.constant - constant, infeasible, aggregated) );
5777 	
5778 	      /* switch the signs of the aggregation scalars again, to reset them to their original values */
5779 	      for( v = 0; v < naggvars; ++v )
5780 	         scalars[v] *= -1.0;
5781 	      break;
5782 	
5783 	   default:
5784 	      SCIPerrorMessage("unknown variable status\n");
5785 	      return SCIP_INVALIDDATA;
5786 	   }
5787 	
5788 	   /* check multi-aggregation on debugging solution */
5789 	   if( *infeasible || *aggregated )
5790 	      SCIP_CALL( SCIPdebugCheckAggregation(set, var, aggvars, scalars, constant, naggvars) ); /*lint !e506 !e774*/
5791 	
5792 	   return SCIP_OKAY;
5793 	}
5794 	
5795 	/** transformed variables are resolved to their active, fixed, or multi-aggregated problem variable of a variable,
5796 	 * or for original variables the same variable is returned
5797 	 */
5798 	static
5799 	SCIP_VAR* varGetActiveVar(
5800 	   SCIP_VAR*             var                 /**< problem variable */
5801 	   )
5802 	{
5803 	   SCIP_VAR* retvar;
5804 	
5805 	   assert(var != NULL);
5806 	
5807 	   retvar = var;
5808 	
5809 	   SCIPdebugMessage("get active variable of <%s>\n", var->name);
5810 	
5811 	   while( TRUE ) /*lint !e716 */
5812 	   {
5813 	      assert(retvar != NULL);
5814 	
5815 	      switch( SCIPvarGetStatus(retvar) )
5816 	      {
5817 	      case SCIP_VARSTATUS_ORIGINAL:
5818 	      case SCIP_VARSTATUS_LOOSE:
5819 	      case SCIP_VARSTATUS_COLUMN:
5820 	      case SCIP_VARSTATUS_FIXED:
5821 		 return retvar;
5822 	
5823 	      case SCIP_VARSTATUS_MULTAGGR:
5824 		 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
5825 		 if ( retvar->data.multaggr.nvars == 1 )
5826 		    retvar = retvar->data.multaggr.vars[0];
5827 		 else
5828 		    return retvar;
5829 		 break;
5830 	
5831 	      case SCIP_VARSTATUS_AGGREGATED:
5832 		 retvar = retvar->data.aggregate.var;
5833 		 break;
5834 	
5835 	      case SCIP_VARSTATUS_NEGATED:
5836 		 retvar = retvar->negatedvar;
5837 		 break;
5838 	
5839 	      default:
5840 		 SCIPerrorMessage("unknown variable status\n");
5841 		 SCIPABORT();
5842 		 return NULL; /*lint !e527*/
5843 	      }
5844 	   }
5845 	}
5846 	
5847 	/** returns whether variable is not allowed to be aggregated */
5848 	SCIP_Bool SCIPvarDoNotAggr(
5849 	   SCIP_VAR*             var                 /**< problem variable */
5850 	   )
5851 	{
5852 	   SCIP_VAR* retvar;
5853 	
5854 	   assert(var != NULL);
5855 	
5856 	   retvar = varGetActiveVar(var);
5857 	   assert(retvar != NULL);
5858 	
5859 	   switch( SCIPvarGetStatus(retvar) )
5860 	   {
5861 	   case SCIP_VARSTATUS_ORIGINAL:
5862 	   case SCIP_VARSTATUS_LOOSE:
5863 	   case SCIP_VARSTATUS_COLUMN:
5864 	   case SCIP_VARSTATUS_FIXED:
5865 	      return retvar->donotaggr;
5866 	
5867 	   case SCIP_VARSTATUS_MULTAGGR:
5868 	      return FALSE;
5869 	
5870 	   case SCIP_VARSTATUS_AGGREGATED:
5871 	   case SCIP_VARSTATUS_NEGATED:
5872 	   default:
5873 	      /* aggregated and negated variables should be resolved by varGetActiveVar() */
5874 	      SCIPerrorMessage("wrong variable status\n");
5875 	      SCIPABORT();
5876 	      return FALSE; /*lint !e527 */
5877 	   }
5878 	}
5879 	
5880 	/** returns whether variable is not allowed to be multi-aggregated */
5881 	SCIP_Bool SCIPvarDoNotMultaggr(
5882 	   SCIP_VAR*             var                 /**< problem variable */
5883 	   )
5884 	{
5885 	   SCIP_VAR* retvar;
5886 	
5887 	   assert(var != NULL);
5888 	
5889 	   retvar = varGetActiveVar(var);
5890 	   assert(retvar != NULL);
5891 	
5892 	   switch( SCIPvarGetStatus(retvar) )
5893 	   {
5894 	   case SCIP_VARSTATUS_ORIGINAL:
5895 	   case SCIP_VARSTATUS_LOOSE:
5896 	   case SCIP_VARSTATUS_COLUMN:
5897 	   case SCIP_VARSTATUS_FIXED:
5898 	      return retvar->donotmultaggr;
5899 	
5900 	   case SCIP_VARSTATUS_MULTAGGR:
5901 	      return FALSE;
5902 	
5903 	   case SCIP_VARSTATUS_AGGREGATED:
5904 	   case SCIP_VARSTATUS_NEGATED:
5905 	   default:
5906 	      /* aggregated and negated variables should be resolved by varGetActiveVar() */
5907 	      SCIPerrorMessage("wrong variable status\n");
5908 	      SCIPABORT();
5909 	      return FALSE; /*lint !e527 */
5910 	   }
5911 	}
5912 	
5913 	/** gets negated variable x' = offset - x of problem variable x; the negated variable is created if not yet existing;
5914 	 *  the negation offset of binary variables is always 1, the offset of other variables is fixed to lb + ub when the
5915 	 *  negated variable is created
5916 	 */
5917 	SCIP_RETCODE SCIPvarNegate(
5918 	   SCIP_VAR*             var,                /**< problem variable to negate */
5919 	   BMS_BLKMEM*           blkmem,             /**< block memory of transformed problem */
5920 	   SCIP_SET*             set,                /**< global SCIP settings */
5921 	   SCIP_STAT*            stat,               /**< problem statistics */
5922 	   SCIP_VAR**            negvar              /**< pointer to store the negated variable */
5923 	   )
5924 	{
5925 	   assert(var != NULL);
5926 	   assert(var->scip == set->scip);
5927 	   assert(negvar != NULL);
5928 	
5929 	   /* check, if we already created the negated variable */
5930 	   if( var->negatedvar == NULL )
5931 	   {
5932 	      char negvarname[SCIP_MAXSTRLEN];
5933 	
5934 	      assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED);
5935 	
5936 	      SCIPsetDebugMsg(set, "creating negated variable of <%s>\n", var->name);
5937 	
5938 	      /* negation is only possible for bounded variables */
5939 	      if( SCIPsetIsInfinity(set, -var->glbdom.lb) || SCIPsetIsInfinity(set, var->glbdom.ub) )
5940 	      {
5941 	         SCIPerrorMessage("cannot negate unbounded variable\n");
5942 	         return SCIP_INVALIDDATA;
5943 	      }
5944 	
5945 	      (void) SCIPsnprintf(negvarname, SCIP_MAXSTRLEN, "%s_neg", var->name);
5946 	
5947 	      /* create negated variable */
5948 	      SCIP_CALL( varCreate(negvar, blkmem, set, stat, negvarname, var->glbdom.lb, var->glbdom.ub, 0.0,
5949 	            SCIPvarGetType(var), var->initial, var->removable, NULL, NULL, NULL, NULL, NULL) );
5950 	      (*negvar)->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
5951 	      if( SCIPvarIsBinary(var) )
5952 	         (*negvar)->data.negate.constant = 1.0;
5953 	      else
5954 	         (*negvar)->data.negate.constant = var->glbdom.lb + var->glbdom.ub;
5955 	
5956 	      /* create event filter for transformed variable */
5957 	      if( SCIPvarIsTransformed(var) )
5958 	      {
5959 	         SCIP_CALL( SCIPeventfilterCreate(&(*negvar)->eventfilter, blkmem) );
5960 	      }
5961 	
5962 	      /* set the bounds corresponding to the negation variable */
5963 	      (*negvar)->glbdom.lb = (*negvar)->data.negate.constant - var->glbdom.ub;
5964 	      (*negvar)->glbdom.ub = (*negvar)->data.negate.constant - var->glbdom.lb;
5965 	      (*negvar)->locdom.lb = (*negvar)->data.negate.constant - var->locdom.ub;
5966 	      (*negvar)->locdom.ub = (*negvar)->data.negate.constant - var->locdom.lb;
5967 	      /**@todo create holes in the negated variable corresponding to the holes of the negation variable */
5968 	
5969 	      /* link the variables together */
5970 	      var->negatedvar = *negvar;
5971 	      (*negvar)->negatedvar = var;
5972 	
5973 	      /* mark both variables to be non-deletable */
5974 	      SCIPvarMarkNotDeletable(var);
5975 	      SCIPvarMarkNotDeletable(*negvar);
5976 	
5977 	      /* copy the branch factor and priority, and use the negative preferred branching direction */
5978 	      (*negvar)->branchfactor = var->branchfactor;
5979 	      (*negvar)->branchpriority = var->branchpriority;
5980 	      (*negvar)->branchdirection = SCIPbranchdirOpposite((SCIP_BRANCHDIR)var->branchdirection); /*lint !e641*/
5981 	
5982 	      /* copy donot(mult)aggr status */
5983 	      (*negvar)->donotaggr = var->donotaggr;
5984 	      (*negvar)->donotmultaggr = var->donotmultaggr;
5985 	
5986 	      /* copy lazy bounds (they have to be flipped) */
5987 	      (*negvar)->lazylb = (*negvar)->data.negate.constant - var->lazyub;
5988 	      (*negvar)->lazyub = (*negvar)->data.negate.constant - var->lazylb;
5989 	
5990 	      /* make negated variable a parent of the negation variable (negated variable is captured as a parent) */
5991 	      SCIP_CALL( varAddParent(var, blkmem, set, *negvar) );
5992 	      assert((*negvar)->nuses == 1);
5993 	   }
5994 	   assert(var->negatedvar != NULL);
5995 	
5996 	   /* return the negated variable */
5997 	   *negvar = var->negatedvar;
5998 	
5999 	   /* exactly one variable of the negation pair has to be marked as negated variable */
6000 	   assert((SCIPvarGetStatus(*negvar) == SCIP_VARSTATUS_NEGATED) != (SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED));
6001 	
6002 	   return SCIP_OKAY;
6003 	}
6004 	
6005 	/** informs variable that its position in problem's vars array changed */
6006 	static
6007 	void varSetProbindex(
6008 	   SCIP_VAR*             var,                /**< problem variable */
6009 	   int                   probindex           /**< new problem index of variable (-1 for removal) */
6010 	   )
6011 	{
6012 	   assert(var != NULL);
6013 	   assert(probindex >= 0 || var->vlbs == NULL);
6014 	   assert(probindex >= 0 || var->vubs == NULL);
6015 	   assert(probindex >= 0 || var->implics == NULL);
6016 	
6017 	   var->probindex = probindex;
6018 	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN )
6019 	   {
6020 	      assert(var->data.col != NULL);
6021 	      var->data.col->var_probindex = probindex;
6022 	   }
6023 	}
6024 	
6025 	/** informs variable that its position in problem's vars array changed */
6026 	void SCIPvarSetProbindex(
6027 	   SCIP_VAR*             var,                /**< problem variable */
6028 	   int                   probindex           /**< new problem index of variable */
6029 	   )
6030 	{
6031 	   assert(var != NULL);
6032 	   assert(probindex >= 0);
6033 	
6034 	   varSetProbindex(var, probindex);
6035 	}
6036 	
6037 	/** gives the variable a new name
6038 	 *
6039 	 *  @note the old pointer is overwritten, which might result in a memory leakage
6040 	 */
6041 	void SCIPvarSetNamePointer(
6042 	   SCIP_VAR*             var,                /**< problem variable */
6043 	   const char*           name                /**< new name of variable */
6044 	   )
6045 	{
6046 	   assert(var != NULL);
6047 	   assert(name != NULL);
6048 	
6049 	   var->name = (char*)name;
6050 	}
6051 	
6052 	/** informs variable that it will be removed from the problem; adjusts probindex and removes variable from the
6053 	 *  implication graph;
6054 	 *  If 'final' is TRUE, the thorough implication graph removal is not performed. Instead, only the
6055 	 *  variable bounds and implication data structures of the variable are freed. Since in the final removal
6056 	 *  of all variables from the transformed problem, this deletes the implication graph completely and is faster
6057 	 *  than removing the variables one by one, each time updating all lists of the other variables.
6058 	 */
6059 	SCIP_RETCODE SCIPvarRemove(
6060 	   SCIP_VAR*             var,                /**< problem variable */
6061 	   BMS_BLKMEM*           blkmem,             /**< block memory buffer */
6062 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
6063 	   SCIP_SET*             set,                /**< global SCIP settings */
6064 	   SCIP_Bool             final               /**< is this the final removal of all problem variables? */
6065 	   )
6066 	{
6067 	   assert(SCIPvarGetProbindex(var) >= 0);
6068 	   assert(var->scip == set->scip);
6069 	
6070 	   /* if the variable is active in the transformed problem, remove it from the implication graph */
6071 	   if( SCIPvarIsTransformed(var)
6072 	      && (SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN) )
6073 	   {
6074 	      if( final )
6075 	      {
6076 	         /* just destroy the data structures */
6077 	         SCIPvboundsFree(&var->vlbs, blkmem);
6078 	         SCIPvboundsFree(&var->vubs, blkmem);
6079 	         SCIPimplicsFree(&var->implics, blkmem);
6080 	      }
6081 	      else
6082 	      {
6083 	         /* unlink the variable from all other variables' lists and free the data structures */
6084 	         SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
6085 	      }
6086 	   }
6087 	
6088 	   /* mark the variable to be no longer a member of the problem */
6089 	   varSetProbindex(var, -1);
6090 	
6091 	   return SCIP_OKAY;
6092 	}
6093 	
6094 	/** marks the variable to be deleted from the problem */
6095 	void SCIPvarMarkDeleted(
6096 	   SCIP_VAR*             var                 /**< problem variable */
6097 	   )
6098 	{
6099 	   assert(var != NULL);
6100 	   assert(var->probindex != -1);
6101 	
6102 	   var->deleted = TRUE;
6103 	}
6104 	
6105 	/** marks the variable to not to be aggregated */
6106 	SCIP_RETCODE SCIPvarMarkDoNotAggr(
6107 	   SCIP_VAR*             var                 /**< problem variable */
6108 	   )
6109 	{
6110 	   SCIP_VAR* retvar;
6111 	
6112 	   assert(var != NULL);
6113 	
6114 	   retvar = varGetActiveVar(var);
6115 	   assert(retvar != NULL);
6116 	
6117 	   switch( SCIPvarGetStatus(retvar) )
6118 	   {
6119 	   case SCIP_VARSTATUS_ORIGINAL:
6120 	   case SCIP_VARSTATUS_LOOSE:
6121 	   case SCIP_VARSTATUS_COLUMN:
6122 	   case SCIP_VARSTATUS_FIXED:
6123 	      retvar->donotaggr = TRUE;
6124 	      break;
6125 	
6126 	   case SCIP_VARSTATUS_MULTAGGR:
6127 	      SCIPerrorMessage("cannot mark a multi-aggregated variable to not be aggregated.\n");
6128 	      return SCIP_INVALIDDATA;
6129 	
6130 	   case SCIP_VARSTATUS_AGGREGATED:
6131 	   case SCIP_VARSTATUS_NEGATED:
6132 	   default:
6133 	      /* aggregated and negated variables should be resolved by varGetActiveVar() */
6134 	      SCIPerrorMessage("wrong variable status\n");
6135 	      return SCIP_INVALIDDATA;
6136 	   }
6137 	
6138 	   return SCIP_OKAY;
6139 	}
6140 	
6141 	/** marks the variable to not to be multi-aggregated */
6142 	SCIP_RETCODE SCIPvarMarkDoNotMultaggr(
6143 	   SCIP_VAR*             var                 /**< problem variable */
6144 	   )
6145 	{
6146 	   SCIP_VAR* retvar;
6147 	
6148 	   assert(var != NULL);
6149 	
6150 	   retvar = varGetActiveVar(var);
6151 	   assert(retvar != NULL);
6152 	
6153 	   switch( SCIPvarGetStatus(retvar) )
6154 	   {
6155 	   case SCIP_VARSTATUS_ORIGINAL:
6156 	   case SCIP_VARSTATUS_LOOSE:
6157 	   case SCIP_VARSTATUS_COLUMN:
6158 	   case SCIP_VARSTATUS_FIXED:
6159 	      retvar->donotmultaggr = TRUE;
6160 	      break;
6161 	
6162 	   case SCIP_VARSTATUS_MULTAGGR:
6163 	      SCIPerrorMessage("cannot mark a multi-aggregated variable to not be multi-aggregated.\n");
6164 	      return SCIP_INVALIDDATA;
6165 	
6166 	   case SCIP_VARSTATUS_AGGREGATED:
6167 	   case SCIP_VARSTATUS_NEGATED:
6168 	   default:
6169 	      /* aggregated and negated variables should be resolved by varGetActiveVar() */
6170 	      SCIPerrorMessage("wrong variable status\n");
6171 	      return SCIP_INVALIDDATA;
6172 	   }
6173 	
6174 	   return SCIP_OKAY;
6175 	}
6176 	
6177 	/** changes type of variable; cannot be called, if var belongs to a problem */
6178 	SCIP_RETCODE SCIPvarChgType(
6179 	   SCIP_VAR*             var,                /**< problem variable to change */
6180 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6181 	   SCIP_SET*             set,                /**< global SCIP settings */
6182 	   SCIP_PRIMAL*          primal,             /**< primal data */
6183 	   SCIP_LP*              lp,                 /**< current LP data */
6184 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
6185 	   SCIP_VARTYPE          vartype             /**< new type of variable */
6186 	   )
6187 	{
6188 	   SCIP_EVENT* event;
6189 	   SCIP_VARTYPE oldtype;
6190 	
6191 	   assert(var != NULL);
6192 	
6193 	   SCIPdebugMessage("change type of <%s> from %d to %d\n", var->name, SCIPvarGetType(var), vartype);
6194 	
6195 	   if( var->probindex >= 0 )
6196 	   {
6197 	      SCIPerrorMessage("cannot change type of variable already in the problem\n");
6198 	      return SCIP_INVALIDDATA;
6199 	   }
6200 	
6201 	   oldtype = (SCIP_VARTYPE)var->vartype;
6202 	   var->vartype = vartype; /*lint !e641*/
6203 	
6204 	   if( SCIPsetGetStage(set) > SCIP_STAGE_TRANSFORMING )
6205 	   {
6206 	      SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var, oldtype, vartype) );
6207 	      SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6208 	   }
6209 	
6210 	   if( var->negatedvar != NULL )
6211 	   {
6212 	      assert(oldtype == (SCIP_VARTYPE)var->negatedvar->vartype
6213 	            || SCIPvarIsBinary(var) == SCIPvarIsBinary(var->negatedvar));
6214 	
6215 	      var->negatedvar->vartype = vartype; /*lint !e641*/
6216 	
6217 	      if( SCIPsetGetStage(set) > SCIP_STAGE_TRANSFORMING )
6218 	      {
6219 	         SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var->negatedvar, oldtype, vartype) );
6220 	         SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6221 	      }
6222 	   }
6223 	
6224 	   return SCIP_OKAY;
6225 	}
6226 	
6227 	/** appends OBJCHANGED event to the event queue */
6228 	static
6229 	SCIP_RETCODE varEventObjChanged(
6230 	   SCIP_VAR*             var,                /**< problem variable to change */
6231 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6232 	   SCIP_SET*             set,                /**< global SCIP settings */
6233 	   SCIP_PRIMAL*          primal,             /**< primal data */
6234 	   SCIP_LP*              lp,                 /**< current LP data */
6235 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
6236 	   SCIP_Real             oldobj,             /**< old objective value for variable */
6237 	   SCIP_Real             newobj              /**< new objective value for variable */
6238 	   )
6239 	{
6240 	   SCIP_EVENT* event;
6241 	
6242 	   assert(var != NULL);
6243 	   assert(var->scip == set->scip);
6244 	   assert(var->eventfilter != NULL);
6245 	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
6246 	   assert(SCIPvarIsTransformed(var));
6247 	
6248 	   /* In the case where the objcetive value of a variable is very close to epsilon, and it is aggregated
6249 	   * into a variable with a big objective value, round-off errors might make the assert oldobj != newobj fail.
6250 	   * Hence, we relax it by letting it pass if the variables are percieved the same and we use very large values
6251 	   * that make comparison with values close to epsilon inaccurate.
6252 	   */
6253 	   assert(!SCIPsetIsEQ(set, oldobj, newobj) ||
6254 	          (SCIPsetIsEQ(set, oldobj, newobj) && REALABS(newobj) > 1e+15 * SCIPsetEpsilon(set))
6255 	   );
6256 	
6257 	   SCIP_CALL( SCIPeventCreateObjChanged(&event, blkmem, var, oldobj, newobj) );
6258 	   SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6259 	
6260 	   return SCIP_OKAY;
6261 	}
6262 	
6263 	/** changes objective value of variable */
6264 	SCIP_RETCODE SCIPvarChgObj(
6265 	   SCIP_VAR*             var,                /**< variable to change */
6266 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6267 	   SCIP_SET*             set,                /**< global SCIP settings */
6268 	   SCIP_PROB*            prob,               /**< problem data */
6269 	   SCIP_PRIMAL*          primal,             /**< primal data */
6270 	   SCIP_LP*              lp,                 /**< current LP data */
6271 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
6272 	   SCIP_Real             newobj              /**< new objective value for variable */
6273 	   )
6274 	{
6275 	   SCIP_Real oldobj;
6276 	
6277 	   assert(var != NULL);
6278 	   assert(set != NULL);
6279 	   assert(var->scip == set->scip);
6280 	
6281 	   SCIPsetDebugMsg(set, "changing objective value of <%s> from %g to %g\n", var->name, var->obj, newobj);
6282 	
6283 	   if( !SCIPsetIsEQ(set, var->obj, newobj) )
6284 	   {
6285 	      switch( SCIPvarGetStatus(var) )
6286 	      {
6287 	      case SCIP_VARSTATUS_ORIGINAL:
6288 	         if( var->data.original.transvar != NULL )
6289 	         {
6290 	            assert(SCIPprobIsTransformed(prob));
6291 	
6292 	            SCIP_CALL( SCIPvarChgObj(var->data.original.transvar, blkmem, set, prob, primal, lp, eventqueue,
6293 	                  (SCIP_Real) prob->objsense * newobj/prob->objscale) );
6294 	         }
6295 	         else
6296 	            assert(set->stage == SCIP_STAGE_PROBLEM);
6297 	
6298 	         var->obj = newobj;
6299 	         var->unchangedobj = newobj;
6300 	
6301 	         break;
6302 	
6303 	      case SCIP_VARSTATUS_LOOSE:
6304 	      case SCIP_VARSTATUS_COLUMN:
6305 	         oldobj = var->obj;
6306 	         var->obj = newobj;
6307 	
6308 	         /* update unchanged objective value of variable */
6309 	         if( !lp->divingobjchg )
6310 	            var->unchangedobj = newobj;
6311 	
6312 	         /* update the number of variables with non-zero objective coefficient;
6313 	          * we only want to do the update, if the variable is added to the problem;
6314 	          * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6315 	          */
6316 	         if( SCIPvarIsActive(var) )
6317 	            SCIPprobUpdateNObjVars(prob, set, oldobj, var->obj);
6318 	
6319 	         SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6320 	         break;
6321 	
6322 	      case SCIP_VARSTATUS_FIXED:
6323 	      case SCIP_VARSTATUS_AGGREGATED:
6324 	      case SCIP_VARSTATUS_MULTAGGR:
6325 	      case SCIP_VARSTATUS_NEGATED:
6326 	         SCIPerrorMessage("cannot change objective value of a fixed, aggregated, multi-aggregated, or negated variable\n");
6327 	         return SCIP_INVALIDDATA;
6328 	
6329 	      default:
6330 	         SCIPerrorMessage("unknown variable status\n");
6331 	         return SCIP_INVALIDDATA;
6332 	      }
6333 	   }
6334 	
6335 	   return SCIP_OKAY;
6336 	}
6337 	
6338 	/** adds value to objective value of variable */
6339 	SCIP_RETCODE SCIPvarAddObj(
6340 	   SCIP_VAR*             var,                /**< variable to change */
6341 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6342 	   SCIP_SET*             set,                /**< global SCIP settings */
6343 	   SCIP_STAT*            stat,               /**< problem statistics */
6344 	   SCIP_PROB*            transprob,          /**< transformed problem data */
6345 	   SCIP_PROB*            origprob,           /**< original problem data */
6346 	   SCIP_PRIMAL*          primal,             /**< primal data */
6347 	   SCIP_TREE*            tree,               /**< branch and bound tree */
6348 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
6349 	   SCIP_LP*              lp,                 /**< current LP data */
6350 	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter for global (not variable dependent) events */
6351 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
6352 	   SCIP_Real             addobj              /**< additional objective value for variable */
6353 	   )
6354 	{
6355 	   assert(var != NULL);
6356 	   assert(set != NULL);
6357 	   assert(var->scip == set->scip);
6358 	   assert(set->stage < SCIP_STAGE_INITSOLVE);
6359 	
6360 	   SCIPsetDebugMsg(set, "adding %g to objective value %g of <%s>\n", addobj, var->obj, var->name);
6361 	
6362 	   if( !SCIPsetIsZero(set, addobj) )
6363 	   {
6364 	      SCIP_Real oldobj;
6365 	      int i;
6366 	
6367 	      switch( SCIPvarGetStatus(var) )
6368 	      {
6369 	      case SCIP_VARSTATUS_ORIGINAL:
6370 	         if( var->data.original.transvar != NULL )
6371 	         {
6372 	            SCIP_CALL( SCIPvarAddObj(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
6373 	                  reopt, lp, eventfilter, eventqueue, (SCIP_Real) transprob->objsense * addobj/transprob->objscale) );
6374 	         }
6375 	         else
6376 	            assert(set->stage == SCIP_STAGE_PROBLEM);
6377 	
6378 	         var->obj += addobj;
6379 	         var->unchangedobj += addobj;
6380 	         assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6381 	
6382 	         break;
6383 	
6384 	      case SCIP_VARSTATUS_LOOSE:
6385 	      case SCIP_VARSTATUS_COLUMN:
6386 	         oldobj = var->obj;
6387 	         var->obj += addobj;
6388 	
6389 	         /* update unchanged objective value of variable */
6390 	         if( !lp->divingobjchg )
6391 	         {
6392 	            var->unchangedobj += addobj;
6393 	            assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6394 	         }
6395 	
6396 	         /* update the number of variables with non-zero objective coefficient;
6397 	          * we only want to do the update, if the variable is added to the problem;
6398 	          * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6399 	          */
6400 	         if( SCIPvarIsActive(var) )
6401 		    SCIPprobUpdateNObjVars(transprob, set, oldobj, var->obj);
6402 	
6403 	         SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6404 	         break;
6405 	
6406 	      case SCIP_VARSTATUS_FIXED:
6407 	         assert(SCIPsetIsEQ(set, var->locdom.lb, var->locdom.ub));
6408 	         SCIPprobAddObjoffset(transprob, var->locdom.lb * addobj);
6409 	         SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6410 	         break;
6411 	
6412 	      case SCIP_VARSTATUS_AGGREGATED:
6413 	         assert(!var->donotaggr);
6414 	         /* x = a*y + c  ->  add a*addobj to obj. val. of y, and c*addobj to obj. offset of problem */
6415 	         SCIPprobAddObjoffset(transprob, var->data.aggregate.constant * addobj);
6416 	         SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6417 	         SCIP_CALL( SCIPvarAddObj(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
6418 	               lp, eventfilter, eventqueue, var->data.aggregate.scalar * addobj) );
6419 	         break;
6420 	
6421 	      case SCIP_VARSTATUS_MULTAGGR:
6422 	         assert(!var->donotmultaggr);
6423 	         /* 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 */
6424 	         SCIPprobAddObjoffset(transprob, var->data.multaggr.constant * addobj);
6425 	         SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6426 	         for( i = 0; i < var->data.multaggr.nvars; ++i )
6427 	         {
6428 	            SCIP_CALL( SCIPvarAddObj(var->data.multaggr.vars[i], blkmem, set, stat, transprob, origprob, primal, tree,
6429 	                  reopt, lp, eventfilter, eventqueue, var->data.multaggr.scalars[i] * addobj) );
6430 	         }
6431 	         break;
6432 	
6433 	      case SCIP_VARSTATUS_NEGATED:
6434 	         /* x' = offset - x  ->  add -addobj to obj. val. of x and offset*addobj to obj. offset of problem */
6435 	         assert(var->negatedvar != NULL);
6436 	         assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
6437 	         assert(var->negatedvar->negatedvar == var);
6438 	         SCIPprobAddObjoffset(transprob, var->data.negate.constant * addobj);
6439 	         SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6440 	         SCIP_CALL( SCIPvarAddObj(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
6441 	               eventfilter, eventqueue, -addobj) );
6442 	         break;
6443 	
6444 	      default:
6445 	         SCIPerrorMessage("unknown variable status\n");
6446 	         return SCIP_INVALIDDATA;
6447 	      }
6448 	   }
6449 	
6450 	   return SCIP_OKAY;
6451 	}
6452 	
6453 	/** changes objective value of variable in current dive */
6454 	SCIP_RETCODE SCIPvarChgObjDive(
6455 	   SCIP_VAR*             var,                /**< problem variable to change */
6456 	   SCIP_SET*             set,                /**< global SCIP settings */
6457 	   SCIP_LP*              lp,                 /**< current LP data */
6458 	   SCIP_Real             newobj              /**< new objective value for variable */
6459 	   )
6460 	{
6461 	   assert(var != NULL);
6462 	   assert(set != NULL);
6463 	   assert(var->scip == set->scip);
6464 	   assert(lp != NULL);
6465 	
6466 	   SCIPsetDebugMsg(set, "changing objective of <%s> to %g in current dive\n", var->name, newobj);
6467 	
6468 	   if( SCIPsetIsZero(set, newobj) )
6469 	      newobj = 0.0;
6470 	
6471 	   /* change objective value of attached variables */
6472 	   switch( SCIPvarGetStatus(var) )
6473 	   {
6474 	   case SCIP_VARSTATUS_ORIGINAL:
6475 	      assert(var->data.original.transvar != NULL);
6476 	      SCIP_CALL( SCIPvarChgObjDive(var->data.original.transvar, set, lp, newobj) );
6477 	      break;
6478 	
6479 	   case SCIP_VARSTATUS_COLUMN:
6480 	      assert(var->data.col != NULL);
6481 	      SCIP_CALL( SCIPcolChgObj(var->data.col, set, lp, newobj) );
6482 	      break;
6483 	
6484 	   case SCIP_VARSTATUS_LOOSE:
6485 	   case SCIP_VARSTATUS_FIXED:
6486 	      /* nothing to do here: only the constant shift in objective function would change */
6487 	      break;
6488 	
6489 	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
6490 	      assert(var->data.aggregate.var != NULL);
6491 	      assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
6492 	      SCIP_CALL( SCIPvarChgObjDive(var->data.aggregate.var, set, lp, newobj / var->data.aggregate.scalar) );
6493 	      /* the constant can be ignored, because it would only affect the objective shift */
6494 	      break;
6495 	
6496 	   case SCIP_VARSTATUS_MULTAGGR:
6497 	      SCIPerrorMessage("cannot change diving objective value of a multi-aggregated variable\n");
6498 	      return SCIP_INVALIDDATA;
6499 	
6500 	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
6501 	      assert(var->negatedvar != NULL);
6502 	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
6503 	      assert(var->negatedvar->negatedvar == var);
6504 	      SCIP_CALL( SCIPvarChgObjDive(var->negatedvar, set, lp, -newobj) );
6505 	      /* the offset can be ignored, because it would only affect the objective shift */
6506 	      break;
6507 	
6508 	   default:
6509 	      SCIPerrorMessage("unknown variable status\n");
6510 	      return SCIP_INVALIDDATA;
6511 	   }
6512 	
6513 	   return SCIP_OKAY;
6514 	}
6515 	
6516 	/** adjust lower bound to integral value, if variable is integral */
6517 	void SCIPvarAdjustLb(
6518 	   SCIP_VAR*             var,                /**< problem variable */
6519 	   SCIP_SET*             set,                /**< global SCIP settings */
6520 	   SCIP_Real*            lb                  /**< pointer to lower bound to adjust */
6521 	   )
6522 	{
6523 	   assert(var != NULL);
6524 	   assert(set != NULL);
6525 	   assert(var->scip == set->scip);
6526 	   assert(lb != NULL);
6527 	
6528 	   SCIPsetDebugMsg(set, "adjust lower bound %g of <%s>\n", *lb, var->name);
6529 	
6530 	   *lb = adjustedLb(set, SCIPvarGetType(var), *lb);
6531 	}
6532 	
6533 	/** adjust upper bound to integral value, if variable is integral */
6534 	void SCIPvarAdjustUb(
6535 	   SCIP_VAR*             var,                /**< problem variable */
6536 	   SCIP_SET*             set,                /**< global SCIP settings */
6537 	   SCIP_Real*            ub                  /**< pointer to upper bound to adjust */
6538 	   )
6539 	{
6540 	   assert(var != NULL);
6541 	   assert(set != NULL);
6542 	   assert(var->scip == set->scip);
6543 	   assert(ub != NULL);
6544 	
6545 	   SCIPsetDebugMsg(set, "adjust upper bound %g of <%s>\n", *ub, var->name);
6546 	
6547 	   *ub = adjustedUb(set, SCIPvarGetType(var), *ub);
6548 	}
6549 	
6550 	/** adjust lower or upper bound to integral value, if variable is integral */
6551 	void SCIPvarAdjustBd(
6552 	   SCIP_VAR*             var,                /**< problem variable */
6553 	   SCIP_SET*             set,                /**< global SCIP settings */
6554 	   SCIP_BOUNDTYPE        boundtype,          /**< type of bound to adjust */
6555 	   SCIP_Real*            bd                  /**< pointer to bound to adjust */
6556 	   )
6557 	{
6558 	   assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
6559 	
6560 	   if( boundtype == SCIP_BOUNDTYPE_LOWER )
6561 	      SCIPvarAdjustLb(var, set, bd);
6562 	   else
6563 	      SCIPvarAdjustUb(var, set, bd);
6564 	}
6565 	
6566 	/** changes lower bound of original variable in original problem */
6567 	SCIP_RETCODE SCIPvarChgLbOriginal(
6568 	   SCIP_VAR*             var,                /**< problem variable to change */
6569 	   SCIP_SET*             set,                /**< global SCIP settings */
6570 	   SCIP_Real             newbound            /**< new bound for variable */
6571 	   )
6572 	{
6573 	   int i;
6574 	
6575 	   assert(var != NULL);
6576 	   assert(!SCIPvarIsTransformed(var));
6577 	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL || SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
6578 	   assert(set != NULL);
6579 	   assert(var->scip == set->scip);
6580 	   assert(set->stage == SCIP_STAGE_PROBLEM);
6581 	
6582 	   /* check that the bound is feasible */
6583 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, SCIPvarGetUbOriginal(var)));
6584 	   /* adjust bound to integral value if variable is of integral type */
6585 	   newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6586 	
6587 	   if( SCIPsetIsZero(set, newbound) )
6588 	      newbound = 0.0;
6589 	
6590 	   /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6591 	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL )
6592 	   {
6593 	      SCIPsetDebugMsg(set, "changing original lower bound of <%s> from %g to %g\n",
6594 	         var->name, var->data.original.origdom.lb, newbound);
6595 	
6596 	      if( SCIPsetIsEQ(set, var->data.original.origdom.lb, newbound) )
6597 	         return SCIP_OKAY;
6598 	
6599 	      /* change the bound */
6600 	      var->data.original.origdom.lb = newbound;
6601 	   }
6602 	   else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6603 	   {
6604 	      assert( var->negatedvar != NULL );
6605 	      SCIP_CALL( SCIPvarChgUbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6606 	   }
6607 	
6608 	   /* process parent variables */
6609 	   for( i = 0; i < var->nparentvars; ++i )
6610 	   {
6611 	      SCIP_VAR* parentvar;
6612 	
6613 	      parentvar = var->parentvars[i];
6614 	      assert(parentvar != NULL);
6615 	      assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6616 	      assert(parentvar->negatedvar == var);
6617 	      assert(var->negatedvar == parentvar);
6618 	
6619 	      SCIP_CALL( SCIPvarChgUbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6620 	   }
6621 	
6622 	   return SCIP_OKAY;
6623 	}
6624 	
6625 	/** changes upper bound of original variable in original problem */
6626 	SCIP_RETCODE SCIPvarChgUbOriginal(
6627 	   SCIP_VAR*             var,                /**< problem variable to change */
6628 	   SCIP_SET*             set,                /**< global SCIP settings */
6629 	   SCIP_Real             newbound            /**< new bound for variable */
6630 	   )
6631 	{
6632 	   int i;
6633 	
6634 	   assert(var != NULL);
6635 	   assert(!SCIPvarIsTransformed(var));
6636 	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL || SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
6637 	   assert(set != NULL);
6638 	   assert(var->scip == set->scip);
6639 	   assert(set->stage == SCIP_STAGE_PROBLEM);
6640 	
6641 	   /* check that the bound is feasible */
6642 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, SCIPvarGetLbOriginal(var)));
6643 	   /* adjust bound to integral value if variable is of integral type */
6644 	   newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6645 	
6646 	   if( SCIPsetIsZero(set, newbound) )
6647 	      newbound = 0.0;
6648 	
6649 	   /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6650 	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL )
6651 	   {
6652 	      SCIPsetDebugMsg(set, "changing original upper bound of <%s> from %g to %g\n",
6653 	         var->name, var->data.original.origdom.ub, newbound);
6654 	
6655 	      if( SCIPsetIsEQ(set, var->data.original.origdom.ub, newbound) )
6656 	         return SCIP_OKAY;
6657 	
6658 	      /* change the bound */
6659 	      var->data.original.origdom.ub = newbound;
6660 	   }
6661 	   else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6662 	   {
6663 	      assert( var->negatedvar != NULL );
6664 	      SCIP_CALL( SCIPvarChgLbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6665 	   }
6666 	
6667 	   /* process parent variables */
6668 	   for( i = 0; i < var->nparentvars; ++i )
6669 	   {
6670 	      SCIP_VAR* parentvar;
6671 	
6672 	      parentvar = var->parentvars[i];
6673 	      assert(parentvar != NULL);
6674 	      assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6675 	      assert(parentvar->negatedvar == var);
6676 	      assert(var->negatedvar == parentvar);
6677 	
6678 	      SCIP_CALL( SCIPvarChgLbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6679 	   }
6680 	
6681 	   return SCIP_OKAY;
6682 	}
6683 	
6684 	/** appends GLBCHANGED event to the event queue */
6685 	static
6686 	SCIP_RETCODE varEventGlbChanged(
6687 	   SCIP_VAR*             var,                /**< problem variable to change */
6688 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6689 	   SCIP_SET*             set,                /**< global SCIP settings */
6690 	   SCIP_LP*              lp,                 /**< current LP data */
6691 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
6692 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
6693 	   SCIP_Real             oldbound,           /**< old lower bound for variable */
6694 	   SCIP_Real             newbound            /**< new lower bound for variable */
6695 	   )
6696 	{
6697 	   assert(var != NULL);
6698 	   assert(var->eventfilter != NULL);
6699 	   assert(SCIPvarIsTransformed(var));
6700 	   assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
6701 	   assert(set != NULL);
6702 	   assert(var->scip == set->scip);
6703 	
6704 	   /* check, if the variable is being tracked for bound changes
6705 	    * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6706 	    */
6707 	   if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GLBCHANGED) != 0)
6708 	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
6709 	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE )
6710 	   {
6711 	      SCIP_EVENT* event;
6712 	
6713 	      SCIPsetDebugMsg(set, "issue GLBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6714 	
6715 	      SCIP_CALL( SCIPeventCreateGlbChanged(&event, blkmem, var, oldbound, newbound) );
6716 	      SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6717 	   }
6718 	
6719 	   return SCIP_OKAY;
6720 	}
6721 	
6722 	/** appends GUBCHANGED event to the event queue */
6723 	static
6724 	SCIP_RETCODE varEventGubChanged(
6725 	   SCIP_VAR*             var,                /**< problem variable to change */
6726 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6727 	   SCIP_SET*             set,                /**< global SCIP settings */
6728 	   SCIP_LP*              lp,                 /**< current LP data */
6729 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
6730 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
6731 	   SCIP_Real             oldbound,           /**< old lower bound for variable */
6732 	   SCIP_Real             newbound            /**< new lower bound for variable */
6733 	   )
6734 	{
6735 	   assert(var != NULL);
6736 	   assert(var->eventfilter != NULL);
6737 	   assert(SCIPvarIsTransformed(var));
6738 	   assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
6739 	   assert(set != NULL);
6740 	   assert(var->scip == set->scip);
6741 	
6742 	   /* check, if the variable is being tracked for bound changes
6743 	    * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6744 	    */
6745 	   if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GUBCHANGED) != 0)
6746 	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
6747 	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE )
6748 	   {
6749 	      SCIP_EVENT* event;
6750 	
6751 	      SCIPsetDebugMsg(set, "issue GUBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6752 	
6753 	      SCIP_CALL( SCIPeventCreateGubChanged(&event, blkmem, var, oldbound, newbound) );
6754 	      SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6755 	   }
6756 	
6757 	   return SCIP_OKAY;
6758 	}
6759 	
6760 	/** appends GHOLEADDED event to the event queue */
6761 	static
6762 	SCIP_RETCODE varEventGholeAdded(
6763 	   SCIP_VAR*             var,                /**< problem variable to change */
6764 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6765 	   SCIP_SET*             set,                /**< global SCIP settings */
6766 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
6767 	   SCIP_Real             left,               /**< left bound of open interval in new hole */
6768 	   SCIP_Real             right               /**< right bound of open interval in new hole */
6769 	   )
6770 	{
6771 	   assert(var != NULL);
6772 	   assert(var->eventfilter != NULL);
6773 	   assert(SCIPvarIsTransformed(var));
6774 	   assert(set != NULL);
6775 	   assert(var->scip == set->scip);
6776 	   assert(SCIPsetIsLT(set, left, right));
6777 	
6778 	   /* check, if the variable is being tracked for bound changes */
6779 	   if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GHOLEADDED) != 0) )
6780 	   {
6781 	      SCIP_EVENT* event;
6782 	
6783 	      SCIPsetDebugMsg(set, "issue GHOLEADDED event for variable <%s>: (%.15g,%.15g)\n", var->name, left, right);
6784 	
6785 	      SCIP_CALL( SCIPeventCreateGholeAdded(&event, blkmem, var, left, right) );
6786 	      SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
6787 	   }
6788 	
6789 	   return SCIP_OKAY;
6790 	}
6791 	
6792 	/** increases root bound change statistics after a global bound change */
6793 	static
6794 	void varIncRootboundchgs(
6795 	   SCIP_VAR*             var,                /**< problem variable to change */
6796 	   SCIP_SET*             set,                /**< global SCIP settings */
6797 	   SCIP_STAT*            stat                /**< problem statistics */
6798 	   )
6799 	{
6800 	   assert(var != NULL);
6801 	   assert(set != NULL);
6802 	   assert(var->scip == set->scip);
6803 	   assert(stat != NULL);
6804 	
6805 	   if( SCIPvarIsActive(var) && SCIPvarIsTransformed(var) && set->stage == SCIP_STAGE_SOLVING )
6806 	   {
6807 	      stat->nrootboundchgs++;
6808 	      stat->nrootboundchgsrun++;
6809 	      if( SCIPvarIsIntegral(var) && SCIPvarGetLbGlobal(var) + 0.5 > SCIPvarGetUbGlobal(var) )
6810 	      {
6811 	         stat->nrootintfixings++;
6812 	         stat->nrootintfixingsrun++;
6813 	      }
6814 	   }
6815 	}
6816 	
6817 	/* forward declaration, because both methods call each other recursively */
6818 	
6819 	/* performs the current change in upper bound, changes all parents accordingly */
6820 	static
6821 	SCIP_RETCODE varProcessChgUbGlobal(
6822 	   SCIP_VAR*             var,                /**< problem variable to change */
6823 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6824 	   SCIP_SET*             set,                /**< global SCIP settings */
6825 	   SCIP_STAT*            stat,               /**< problem statistics */
6826 	   SCIP_LP*              lp,                 /**< current LP data, may be NULL for original variables */
6827 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage, may be NULL for original variables */
6828 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
6829 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
6830 	   SCIP_Real             newbound            /**< new bound for variable */
6831 	   );
6832 	
6833 	/** performs the current change in lower bound, changes all parents accordingly */
6834 	static
6835 	SCIP_RETCODE varProcessChgLbGlobal(
6836 	   SCIP_VAR*             var,                /**< problem variable to change */
6837 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6838 	   SCIP_SET*             set,                /**< global SCIP settings */
6839 	   SCIP_STAT*            stat,               /**< problem statistics */
6840 	   SCIP_LP*              lp,                 /**< current LP data, may be NULL for original variables */
6841 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage, may be NULL for original variables */
6842 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
6843 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
6844 	   SCIP_Real             newbound            /**< new bound for variable */
6845 	   )
6846 	{
6847 	   SCIP_VAR* parentvar;
6848 	   SCIP_Real oldbound;
6849 	   int i;
6850 	
6851 	   assert(var != NULL);
6852 	   /* local domains can violate global bounds but not more than feasibility epsilon */
6853 	   assert(SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb));
6854 	   assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6855 	   assert(blkmem != NULL);
6856 	   assert(set != NULL);
6857 	   assert(var->scip == set->scip);
6858 	   assert(stat != NULL);
6859 	
6860 	   /* adjust bound to integral value if variable is of integral type */
6861 	   newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6862 	
6863 	   /* check that the bound is feasible */
6864 	   if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound > var->glbdom.ub )
6865 	   {
6866 	      /* due to numerics we only want to be feasible in feasibility tolerance */
6867 	      assert(SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6868 	      newbound = var->glbdom.ub;
6869 	   }
6870 	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6871 	
6872 	   assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0));  /*lint !e641*/
6873 	
6874 	   SCIPsetDebugMsg(set, "process changing global lower bound of <%s> from %f to %f\n", var->name, var->glbdom.lb, newbound);
6875 	
6876 	   if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) )  /*lint !e777*/
6877 	      return SCIP_OKAY;
6878 	
6879 	   /* check bound on debugging solution */
6880 	   SCIP_CALL( SCIPdebugCheckLbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6881 	
6882 	   /* change the bound */
6883 	   oldbound = var->glbdom.lb;
6884 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6885 	   var->glbdom.lb = newbound;
6886 	   assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6887 	   assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6888 	
6889 	   if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6890 	   {
6891 	      /* merges overlapping holes into single holes, moves bounds respectively */
6892 	      domMerge(&var->glbdom, blkmem, set, &newbound, NULL);
6893 	   }
6894 	
6895 	   /* update the root bound changes counters */
6896 	   varIncRootboundchgs(var, set, stat);
6897 	
6898 	   /* update the lbchginfos array by replacing worse local bounds with the new global bound and changing the
6899 	    * redundant bound changes to be branching decisions
6900 	    */
6901 	   for( i = 0; i < var->nlbchginfos; ++i )
6902 	   {
6903 	      assert(var->lbchginfos[i].var == var);
6904 	
6905 	      if( var->lbchginfos[i].oldbound < var->glbdom.lb )
6906 	      {
6907 	         SCIPsetDebugMsg(set, " -> adjust lower bound change <%s>: %g -> %g due to new global lower bound %g\n",
6908 	            SCIPvarGetName(var), var->lbchginfos[i].oldbound, var->lbchginfos[i].newbound, var->glbdom.lb);
6909 	         var->lbchginfos[i].oldbound = var->glbdom.lb;
6910 	         if( SCIPsetIsLE(set, var->lbchginfos[i].newbound, var->glbdom.lb) )
6911 	         {
6912 	            /* this bound change is redundant due to the new global bound */
6913 	            var->lbchginfos[i].newbound = var->glbdom.lb;
6914 	            var->lbchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6915 	            var->lbchginfos[i].redundant = TRUE;
6916 	         }
6917 	         else
6918 	            break; /* from now on, the remaining local bound changes are not redundant */
6919 	      }
6920 	      else
6921 	         break; /* from now on, the remaining local bound changes are not redundant */
6922 	   }
6923 	
6924 	   /* remove redundant implications and variable bounds */
6925 	   if( (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE)
6926 	      && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
6927 	   {
6928 	      SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6929 	   }
6930 	
6931 	   /* issue bound change event */
6932 	   assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6933 	   if( var->eventfilter != NULL )
6934 	   {
6935 	      SCIP_CALL( varEventGlbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6936 	   }
6937 	
6938 	   /* process parent variables */
6939 	   for( i = 0; i < var->nparentvars; ++i )
6940 	   {
6941 	      parentvar = var->parentvars[i];
6942 	      assert(parentvar != NULL);
6943 	
6944 	      switch( SCIPvarGetStatus(parentvar) )
6945 	      {
6946 	      case SCIP_VARSTATUS_ORIGINAL:
6947 	         SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6948 	         break;
6949 	
6950 	      case SCIP_VARSTATUS_COLUMN:
6951 	      case SCIP_VARSTATUS_LOOSE:
6952 	      case SCIP_VARSTATUS_FIXED:
6953 	      case SCIP_VARSTATUS_MULTAGGR:
6954 	         SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6955 	         return SCIP_INVALIDDATA;
6956 	
6957 	      case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
6958 	         assert(parentvar->data.aggregate.var == var);
6959 	         if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6960 	         {
6961 	            SCIP_Real parentnewbound;
6962 	
6963 	            /* a > 0 -> change lower bound of y */
6964 	            assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, -oldbound)
6965 	               || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6966 	               || (SCIPsetIsZero(set, parentvar->glbdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6967 	
6968 	            if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6969 	               parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6970 	            else
6971 	               parentnewbound = newbound;
6972 	            SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6973 	         }
6974 	         else
6975 	         {
6976 	            SCIP_Real parentnewbound;
6977 	
6978 	            /* a < 0 -> change upper bound of y */
6979 	            assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6980 	            assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, -oldbound)
6981 	               || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6982 	               || (SCIPsetIsZero(set, parentvar->glbdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6983 	
6984 	            if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6985 	               parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6986 	            else
6987 	               parentnewbound = -newbound;
6988 	            SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6989 	         }
6990 	         break;
6991 	
6992 	      case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
6993 	         assert(parentvar->negatedvar != NULL);
6994 	         assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6995 	         assert(parentvar->negatedvar->negatedvar == parentvar);
6996 	         SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6997 	               parentvar->data.negate.constant - newbound) );
6998 	         break;
6999 	
7000 	      default:
7001 	         SCIPerrorMessage("unknown variable status\n");
7002 	         return SCIP_INVALIDDATA;
7003 	      }
7004 	   }
7005 	
7006 	   return SCIP_OKAY;
7007 	}
7008 	
7009 	/** performs the current change in upper bound, changes all parents accordingly */
7010 	static
7011 	SCIP_RETCODE varProcessChgUbGlobal(
7012 	   SCIP_VAR*             var,                /**< problem variable to change */
7013 	   BMS_BLKMEM*           blkmem,             /**< block memory */
7014 	   SCIP_SET*             set,                /**< global SCIP settings */
7015 	   SCIP_STAT*            stat,               /**< problem statistics */
7016 	   SCIP_LP*              lp,                 /**< current LP data, may be NULL for original variables */
7017 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage, may be NULL for original variables */
7018 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
7019 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
7020 	   SCIP_Real             newbound            /**< new bound for variable */
7021 	   )
7022 	{
7023 	   SCIP_VAR* parentvar;
7024 	   SCIP_Real oldbound;
7025 	   int i;
7026 	
7027 	   assert(var != NULL);
7028 	   /* local domains can violate global bounds but not more than feasibility epsilon */
7029 	   assert(SCIPsetIsFeasLE(set, var->glbdom.lb , var->locdom.lb));
7030 	   assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
7031 	   assert(blkmem != NULL);
7032 	   assert(set != NULL);
7033 	   assert(var->scip == set->scip);
7034 	   assert(stat != NULL);
7035 	
7036 	   /* adjust bound to integral value if variable is of integral type */
7037 	   newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7038 	
7039 	   /* check that the bound is feasible */
7040 	   if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound < var->glbdom.lb )
7041 	   {
7042 	      /* due to numerics we only want to be feasible in feasibility tolerance */
7043 	      assert(SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
7044 	      newbound = var->glbdom.lb;
7045 	   }
7046 	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7047 	
7048 	   assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0));  /*lint !e641*/
7049 	
7050 	   SCIPsetDebugMsg(set, "process changing global upper bound of <%s> from %f to %f\n", var->name, var->glbdom.ub, newbound);
7051 	
7052 	   if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) )  /*lint !e777*/
7053 	      return SCIP_OKAY;
7054 	
7055 	   /* check bound on debugging solution */
7056 	   SCIP_CALL( SCIPdebugCheckUbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
7057 	
7058 	   /* change the bound */
7059 	   oldbound = var->glbdom.ub;
7060 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
7061 	   var->glbdom.ub = newbound;
7062 	   assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
7063 	   assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
7064 	
7065 	   if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7066 	   {
7067 	      /* merges overlapping holes into single holes, moves bounds respectively */
7068 	      domMerge(&var->glbdom, blkmem, set, NULL, &newbound);
7069 	   }
7070 	
7071 	   /* update the root bound changes counters */
7072 	   varIncRootboundchgs(var, set, stat);
7073 	
7074 	   /* update the ubchginfos array by replacing worse local bounds with the new global bound and changing the
7075 	    * redundant bound changes to be branching decisions
7076 	    */
7077 	   for( i = 0; i < var->nubchginfos; ++i )
7078 	   {
7079 	      assert(var->ubchginfos[i].var == var);
7080 	      if( var->ubchginfos[i].oldbound > var->glbdom.ub )
7081 	      {
7082 	         SCIPsetDebugMsg(set, " -> adjust upper bound change <%s>: %g -> %g due to new global upper bound %g\n",
7083 	            SCIPvarGetName(var), var->ubchginfos[i].oldbound, var->ubchginfos[i].newbound, var->glbdom.ub);
7084 	         var->ubchginfos[i].oldbound = var->glbdom.ub;
7085 	         if( SCIPsetIsGE(set, var->ubchginfos[i].newbound, var->glbdom.ub) )
7086 	         {
7087 	            /* this bound change is redundant due to the new global bound */
7088 	            var->ubchginfos[i].newbound = var->glbdom.ub;
7089 	            var->ubchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
7090 	            var->ubchginfos[i].redundant = TRUE;
7091 	         }
7092 	         else
7093 	            break; /* from now on, the remaining local bound changes are not redundant */
7094 	      }
7095 	      else
7096 	         break; /* from now on, the remaining local bound changes are not redundant */
7097 	   }
7098 	
7099 	   /* remove redundant implications and variable bounds */
7100 	   if( (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE)
7101 	      && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
7102 	   {
7103 	      SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
7104 	   }
7105 	
7106 	   /* issue bound change event */
7107 	   assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7108 	   if( var->eventfilter != NULL )
7109 	   {
7110 	      SCIP_CALL( varEventGubChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7111 	   }
7112 	
7113 	   /* process parent variables */
7114 	   for( i = 0; i < var->nparentvars; ++i )
7115 	   {
7116 	      parentvar = var->parentvars[i];
7117 	      assert(parentvar != NULL);
7118 	
7119 	      switch( SCIPvarGetStatus(parentvar) )
7120 	      {
7121 	      case SCIP_VARSTATUS_ORIGINAL:
7122 	         SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7123 	         break;
7124 	
7125 	      case SCIP_VARSTATUS_COLUMN:
7126 	      case SCIP_VARSTATUS_LOOSE:
7127 	      case SCIP_VARSTATUS_FIXED:
7128 	      case SCIP_VARSTATUS_MULTAGGR:
7129 	         SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7130 	         return SCIP_INVALIDDATA;
7131 	
7132 	      case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
7133 	         assert(parentvar->data.aggregate.var == var);
7134 	         if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7135 	         {
7136 	            SCIP_Real parentnewbound;
7137 	
7138 	            /* a > 0 -> change upper bound of y */
7139 	            assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, oldbound)
7140 	               || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub,
7141 	                  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7142 	            if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7143 	               parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7144 	            else
7145 	               parentnewbound = newbound;
7146 	            SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
7147 	         }
7148 	         else
7149 	         {
7150 	            SCIP_Real parentnewbound;
7151 	
7152 	            /* a < 0 -> change lower bound of y */
7153 	            assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7154 	            assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, oldbound)
7155 	               || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb,
7156 	                  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7157 	            if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7158 	               parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7159 	            else
7160 	               parentnewbound = -newbound;
7161 	            SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
7162 	         }
7163 	         break;
7164 	
7165 	      case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
7166 	         assert(parentvar->negatedvar != NULL);
7167 	         assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7168 	         assert(parentvar->negatedvar->negatedvar == parentvar);
7169 	         SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7170 	               parentvar->data.negate.constant - newbound) );
7171 	         break;
7172 	
7173 	      default:
7174 	         SCIPerrorMessage("unknown variable status\n");
7175 	         return SCIP_INVALIDDATA;
7176 	      }
7177 	   }
7178 	
7179 	   return SCIP_OKAY;
7180 	}
7181 	
7182 	/** changes global lower bound of variable; if possible, adjusts bound to integral value;
7183 	 *  updates local lower bound if the global bound is tighter
7184 	 */
7185 	SCIP_RETCODE SCIPvarChgLbGlobal(
7186 	   SCIP_VAR*             var,                /**< problem variable to change */
7187 	   BMS_BLKMEM*           blkmem,             /**< block memory */
7188 	   SCIP_SET*             set,                /**< global SCIP settings */
7189 	   SCIP_STAT*            stat,               /**< problem statistics */
7190 	   SCIP_LP*              lp,                 /**< current LP data, may be NULL for original variables */
7191 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage, may be NULL for original variables */
7192 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
7193 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
7194 	   SCIP_Real             newbound            /**< new bound for variable */
7195 	   )
7196 	{
7197 	   assert(var != NULL);
7198 	   assert(blkmem != NULL);
7199 	   assert(set != NULL);
7200 	   assert(var->scip == set->scip);
7201 	
7202 	   /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7203 	    * of the domain within feastol
7204 	    */
7205 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
7206 	
7207 	   /* adjust bound to integral value if variable is of integral type */
7208 	   newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7209 	
7210 	   /* check that the adjusted bound is feasible
7211 	    * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
7212 	    *       here because we reset bounds to their original value!
7213 	    */
7214 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
7215 	
7216 	   if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7217 	   {
7218 	      /* we do not want to exceed the upperbound, which could have happened due to numerics */
7219 	      newbound = MIN(newbound, var->glbdom.ub);
7220 	   }
7221 	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7222 	
7223 	   /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
7224 	    * SCIPvarFix() allows fixings that are outside of the domain within feastol
7225 	    */
7226 	   assert(lp == NULL || SCIPsetIsFeasLE(set, var->glbdom.lb, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
7227 	
7228 	   SCIPsetDebugMsg(set, "changing global lower bound of <%s> from %g to %g\n", var->name, var->glbdom.lb, newbound);
7229 	
7230 	   if( SCIPsetIsEQ(set, var->glbdom.lb, newbound) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) )  /*lint !e777*/
7231 	      return SCIP_OKAY;
7232 	
7233 	   /* change bounds of attached variables */
7234 	   switch( SCIPvarGetStatus(var) )
7235 	   {
7236 	   case SCIP_VARSTATUS_ORIGINAL:
7237 	      if( var->data.original.transvar != NULL )
7238 	      {
7239 	         SCIP_CALL( SCIPvarChgLbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
7240 	               cliquetable, newbound) );
7241 	      }
7242 	      else
7243 	      {
7244 	         assert(set->stage == SCIP_STAGE_PROBLEM);
7245 	         if( newbound > SCIPvarGetLbLocal(var) )
7246 	         {
7247 	            SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7248 	         }
7249 	         SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7250 	      }
7251 	      break;
7252 	
7253 	   case SCIP_VARSTATUS_COLUMN:
7254 	   case SCIP_VARSTATUS_LOOSE:
7255 	      if( newbound > SCIPvarGetLbLocal(var) )
7256 	      {
7257 	         SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7258 	      }
7259 	      SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7260 	      break;
7261 	
7262 	   case SCIP_VARSTATUS_FIXED:
7263 	      SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7264 	      return SCIP_INVALIDDATA;
7265 	
7266 	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
7267 	      assert(var->data.aggregate.var != NULL);
7268 	      if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7269 	      {
7270 	         SCIP_Real childnewbound;
7271 	
7272 	         /* a > 0 -> change lower bound of y */
7273 	         assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
7274 	            || SCIPsetIsFeasEQ(set, var->glbdom.lb,
7275 	               var->data.aggregate.var->glbdom.lb * var->data.aggregate.scalar + var->data.aggregate.constant));
7276 	         if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7277 	            childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7278 	         else
7279 	            childnewbound = newbound;
7280 	         SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7281 	               childnewbound) );
7282 	      }
7283 	      else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7284 	      {
7285 	         SCIP_Real childnewbound;
7286 	
7287 	         /* a < 0 -> change upper bound of y */
7288 	         assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
7289 	            || SCIPsetIsFeasEQ(set, var->glbdom.lb,
7290 	               var->data.aggregate.var->glbdom.ub * var->data.aggregate.scalar + var->data.aggregate.constant));
7291 	         if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7292 	            childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7293 	         else
7294 	            childnewbound = -newbound;
7295 	         SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7296 	               childnewbound) );
7297 	      }
7298 	      else
7299 	      {
7300 	         SCIPerrorMessage("scalar is zero in aggregation\n");
7301 	         return SCIP_INVALIDDATA;
7302 	      }
7303 	      break;
7304 	
7305 	   case SCIP_VARSTATUS_MULTAGGR:
7306 	      SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7307 	      return SCIP_INVALIDDATA;
7308 	
7309 	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
7310 	      assert(var->negatedvar != NULL);
7311 	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
7312 	      assert(var->negatedvar->negatedvar == var);
7313 	      SCIP_CALL( SCIPvarChgUbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7314 	            var->data.negate.constant - newbound) );
7315 	      break;
7316 	
7317 	   default:
7318 	      SCIPerrorMessage("unknown variable status\n");
7319 	      return SCIP_INVALIDDATA;
7320 	   }
7321 	
7322 	   return SCIP_OKAY;
7323 	}
7324 	
7325 	/** changes global upper bound of variable; if possible, adjusts bound to integral value;
7326 	 *  updates local upper bound if the global bound is tighter
7327 	 */
7328 	SCIP_RETCODE SCIPvarChgUbGlobal(
7329 	   SCIP_VAR*             var,                /**< problem variable to change */
7330 	   BMS_BLKMEM*           blkmem,             /**< block memory */
7331 	   SCIP_SET*             set,                /**< global SCIP settings */
7332 	   SCIP_STAT*            stat,               /**< problem statistics */
7333 	   SCIP_LP*              lp,                 /**< current LP data, may be NULL for original variables */
7334 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage, may be NULL for original variables */
7335 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
7336 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
7337 	   SCIP_Real             newbound            /**< new bound for variable */
7338 	   )
7339 	{
7340 	   assert(var != NULL);
7341 	   assert(blkmem != NULL);
7342 	   assert(set != NULL);
7343 	   assert(var->scip == set->scip);
7344 	
7345 	   /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7346 	    * of the domain within feastol
7347 	    */
7348 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
7349 	
7350 	   /* adjust bound to integral value if variable is of integral type */
7351 	   newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7352 	
7353 	   /* check that the adjusted bound is feasible
7354 	    * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
7355 	    *       here because we reset bounds to their original value!
7356 	    */
7357 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
7358 	
7359 	   if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7360 	   {
7361 	      /* we do not want to undercut the lowerbound, which could have happened due to numerics */
7362 	      newbound = MAX(newbound, var->glbdom.lb);
7363 	   }
7364 	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7365 	
7366 	   /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
7367 	    * SCIPvarFix() allows fixings that are outside of the domain within feastol
7368 	    */
7369 	   assert(lp == NULL || SCIPsetIsFeasGE(set, var->glbdom.ub, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
7370 	
7371 	   SCIPsetDebugMsg(set, "changing global upper bound of <%s> from %g to %g\n", var->name, var->glbdom.ub, newbound);
7372 	
7373 	   if( SCIPsetIsEQ(set, var->glbdom.ub, newbound) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) )  /*lint !e777*/
7374 	      return SCIP_OKAY;
7375 	
7376 	   /* change bounds of attached variables */
7377 	   switch( SCIPvarGetStatus(var) )
7378 	   {
7379 	   case SCIP_VARSTATUS_ORIGINAL:
7380 	      if( var->data.original.transvar != NULL )
7381 	      {
7382 	         SCIP_CALL( SCIPvarChgUbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7383 	               newbound) );
7384 	      }
7385 	      else
7386 	      {
7387 	         assert(set->stage == SCIP_STAGE_PROBLEM);
7388 	         if( newbound < SCIPvarGetUbLocal(var) )
7389 	         {
7390 	            SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7391 	         }
7392 	         SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7393 	      }
7394 	      break;
7395 	
7396 	   case SCIP_VARSTATUS_COLUMN:
7397 	   case SCIP_VARSTATUS_LOOSE:
7398 	      if( newbound < SCIPvarGetUbLocal(var) )
7399 	      {
7400 	         SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7401 	      }
7402 	      SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7403 	      break;
7404 	
7405 	   case SCIP_VARSTATUS_FIXED:
7406 	      SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7407 	      return SCIP_INVALIDDATA;
7408 	
7409 	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
7410 	      assert(var->data.aggregate.var != NULL);
7411 	      if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7412 	      {
7413 	         SCIP_Real childnewbound;
7414 	
7415 	         /* a > 0 -> change lower bound of y */
7416 	         assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
7417 	            || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7418 	               var->data.aggregate.var->glbdom.ub * var->data.aggregate.scalar + var->data.aggregate.constant));
7419 	         if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7420 	            childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7421 	         else
7422 	            childnewbound = newbound;
7423 	         SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7424 	               childnewbound) );
7425 	      }
7426 	      else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7427 	      {
7428 	         SCIP_Real childnewbound;
7429 	
7430 	         /* a < 0 -> change upper bound of y */
7431 	         assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
7432 	            || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7433 	               var->data.aggregate.var->glbdom.lb * var->data.aggregate.scalar + var->data.aggregate.constant));
7434 	         if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7435 	            childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7436 	         else
7437 	            childnewbound = -newbound;
7438 	         SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7439 	               childnewbound) );
7440 	      }
7441 	      else
7442 	      {
7443 	         SCIPerrorMessage("scalar is zero in aggregation\n");
7444 	         return SCIP_INVALIDDATA;
7445 	      }
7446 	      break;
7447 	
7448 	   case SCIP_VARSTATUS_MULTAGGR:
7449 	      SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7450 	      return SCIP_INVALIDDATA;
7451 	
7452 	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
7453 	      assert(var->negatedvar != NULL);
7454 	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
7455 	      assert(var->negatedvar->negatedvar == var);
7456 	      SCIP_CALL( SCIPvarChgLbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7457 	            var->data.negate.constant - newbound) );
7458 	      break;
7459 	
7460 	   default:
7461 	      SCIPerrorMessage("unknown variable status\n");
7462 	      return SCIP_INVALIDDATA;
7463 	   }
7464 	
7465 	   return SCIP_OKAY;
7466 	}
7467 	
7468 	/** changes lazy lower bound of the variable, this is only possible if the variable is not in the LP yet */
7469 	SCIP_RETCODE SCIPvarChgLbLazy(
7470 	   SCIP_VAR*             var,                /**< problem variable */
7471 	   SCIP_SET*             set,                /**< global SCIP settings */
7472 	   SCIP_Real             lazylb              /**< the lazy lower bound to be set */
7473 	   )
7474 	{
7475 	   assert(var != NULL);
7476 	   assert(var->probindex != -1);
7477 	   assert(SCIPsetIsFeasGE(set, var->glbdom.ub, lazylb));
7478 	   assert(SCIPsetIsFeasGE(set, var->lazyub, lazylb));
7479 	   assert(set != NULL);
7480 	   assert(var->scip == set->scip);
7481 	
7482 	   /* variable should not be in the LP */
7483 	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN )
7484 	      return SCIP_INVALIDCALL;
7485 	
7486 	   var->lazylb = lazylb;
7487 	
7488 	   return SCIP_OKAY;
7489 	}
7490 	
7491 	/** changes lazy upper bound of the variable, this is only possible if the variable is not in the LP yet */
7492 	SCIP_RETCODE SCIPvarChgUbLazy(
7493 	   SCIP_VAR*             var,                /**< problem variable */
7494 	   SCIP_SET*             set,                /**< global SCIP settings */
7495 	   SCIP_Real             lazyub              /**< the lazy lower bound to be set */
7496 	   )
7497 	{
7498 	   assert(var != NULL);
7499 	   assert(var->probindex != -1);
7500 	   assert(SCIPsetIsFeasGE(set, lazyub, var->glbdom.lb));
7501 	   assert(SCIPsetIsFeasGE(set, lazyub, var->lazylb));
7502 	   assert(set != NULL);
7503 	   assert(var->scip == set->scip);
7504 	
7505 	   /* variable should not be in the LP */
7506 	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN )
7507 	      return SCIP_INVALIDCALL;
7508 	
7509 	   var->lazyub = lazyub;
7510 	
7511 	   return SCIP_OKAY;
7512 	}
7513 	
7514 	
7515 	/** changes global bound of variable; if possible, adjusts bound to integral value;
7516 	 *  updates local bound if the global bound is tighter
7517 	 */
7518 	SCIP_RETCODE SCIPvarChgBdGlobal(
7519 	   SCIP_VAR*             var,                /**< problem variable to change */
7520 	   BMS_BLKMEM*           blkmem,             /**< block memory */
7521 	   SCIP_SET*             set,                /**< global SCIP settings */
7522 	   SCIP_STAT*            stat,               /**< problem statistics */
7523 	   SCIP_LP*              lp,                 /**< current LP data, may be NULL for original variables */
7524 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage, may be NULL for original variables */
7525 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
7526 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
7527 	   SCIP_Real             newbound,           /**< new bound for variable */
7528 	   SCIP_BOUNDTYPE        boundtype           /**< type of bound: lower or upper bound */
7529 	   )
7530 	{
7531 	   /* apply bound change to the LP data */
7532 	   switch( boundtype )
7533 	   {
7534 	   case SCIP_BOUNDTYPE_LOWER:
7535 	      return SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7536 	   case SCIP_BOUNDTYPE_UPPER:
7537 	      return SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7538 	   default:
7539 	      SCIPerrorMessage("unknown bound type\n");
7540 	      return SCIP_INVALIDDATA;
7541 	   }
7542 	}
7543 	
7544 	/** appends LBTIGHTENED or LBRELAXED event to the event queue */
7545 	static
7546 	SCIP_RETCODE varEventLbChanged(
7547 	   SCIP_VAR*             var,                /**< problem variable to change */
7548 	   BMS_BLKMEM*           blkmem,             /**< block memory */
7549 	   SCIP_SET*             set,                /**< global SCIP settings */
7550 	   SCIP_LP*              lp,                 /**< current LP data */
7551 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
7552 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
7553 	   SCIP_Real             oldbound,           /**< old lower bound for variable */
7554 	   SCIP_Real             newbound            /**< new lower bound for variable */
7555 	   )
7556 	{
7557 	   assert(var != NULL);
7558 	   assert(var->eventfilter != NULL);
7559 	   assert(SCIPvarIsTransformed(var));
7560 	   assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.lb || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
7561 	   assert(set != NULL);
7562 	   assert(var->scip == set->scip);
7563 	
7564 	   /* check, if the variable is being tracked for bound changes
7565 	    * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7566 	    */
7567 	   if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_LBCHANGED) != 0)
7568 	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
7569 	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE )
7570 	   {
7571 	      SCIP_EVENT* event;
7572 	
7573 	      SCIPsetDebugMsg(set, "issue LBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7574 	
7575 	      SCIP_CALL( SCIPeventCreateLbChanged(&event, blkmem, var, oldbound, newbound) );
7576 	      SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7577 	   }
7578 	
7579 	   return SCIP_OKAY;
7580 	}
7581 	
7582 	/** appends UBTIGHTENED or UBRELAXED event to the event queue */
7583 	static
7584 	SCIP_RETCODE varEventUbChanged(
7585 	   SCIP_VAR*             var,                /**< problem variable to change */
7586 	   BMS_BLKMEM*           blkmem,             /**< block memory */
7587 	   SCIP_SET*             set,                /**< global SCIP settings */
7588 	   SCIP_LP*              lp,                 /**< current LP data */
7589 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
7590 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
7591 	   SCIP_Real             oldbound,           /**< old upper bound for variable */
7592 	   SCIP_Real             newbound            /**< new upper bound for variable */
7593 	   )
7594 	{
7595 	   assert(var != NULL);
7596 	   assert(var->eventfilter != NULL);
7597 	   assert(SCIPvarIsTransformed(var));
7598 	   assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.ub || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
7599 	   assert(set != NULL);
7600 	   assert(var->scip == set->scip);
7601 	
7602 	   /* check, if the variable is being tracked for bound changes
7603 	    * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7604 	    */
7605 	   if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_UBCHANGED) != 0)
7606 	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
7607 	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE )
7608 	   {
7609 	      SCIP_EVENT* event;
7610 	
7611 	      SCIPsetDebugMsg(set, "issue UBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7612 	
7613 	      SCIP_CALL( SCIPeventCreateUbChanged(&event, blkmem, var, oldbound, newbound) );
7614 	      SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7615 	   }
7616 	
7617 	   return SCIP_OKAY;
7618 	}
7619 	
7620 	/* forward declaration, because both methods call each other recursively */
7621 	
7622 	/* performs the current change in upper bound, changes all parents accordingly */
7623 	static
7624 	SCIP_RETCODE varProcessChgUbLocal(
7625 	   SCIP_VAR*             var,                /**< problem variable to change */
7626 	   BMS_BLKMEM*           blkmem,             /**< block memory */
7627 	   SCIP_SET*             set,                /**< global SCIP settings */
7628 	   SCIP_STAT*            stat,               /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7629 	   SCIP_LP*              lp,                 /**< current LP data, may be NULL for original variables */
7630 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage, may be NULL for original variables */
7631 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
7632 	   SCIP_Real             newbound            /**< new bound for variable */
7633 	   );
7634 	
7635 	/** performs the current change in lower bound, changes all parents accordingly */
7636 	static
7637 	SCIP_RETCODE varProcessChgLbLocal(
7638 	   SCIP_VAR*             var,                /**< problem variable to change */
7639 	   BMS_BLKMEM*           blkmem,             /**< block memory */
7640 	   SCIP_SET*             set,                /**< global SCIP settings */
7641 	   SCIP_STAT*            stat,               /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7642 	   SCIP_LP*              lp,                 /**< current LP data, may be NULL for original variables */
7643 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage, may be NULL for original variables */
7644 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
7645 	   SCIP_Real             newbound            /**< new bound for variable */
7646 	   )
7647 	{
7648 	   SCIP_VAR* parentvar;
7649 	   SCIP_Real oldbound;
7650 	   int i;
7651 	
7652 	   assert(var != NULL);
7653 	   assert(set != NULL);
7654 	   assert(var->scip == set->scip);
7655 	   assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7656 	            || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7657 	      || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && (SCIPsetIsIntegral(set, newbound)
7658 	            || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7659 	      || SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
7660 	
7661 	   /* check that the bound is feasible */
7662 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, var->glbdom.ub));
7663 	   /* adjust bound to integral value if variable is of integral type */
7664 	   newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7665 	
7666 	   if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7667 	   {
7668 	      /* we do not want to exceed the upper bound, which could have happened due to numerics */
7669 	      newbound = MIN(newbound, var->locdom.ub);
7670 	
7671 	      /* we do not want to undercut the global lower bound, which could have happened due to numerics */
7672 	      newbound = MAX(newbound, var->glbdom.lb);
7673 	   }
7674 	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7675 	
7676 	   SCIPsetDebugMsg(set, "process changing lower bound of <%s> from %g to %g\n", var->name, var->locdom.lb, newbound);
7677 	
7678 	   if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && var->glbdom.lb != var->locdom.lb ) /*lint !e777*/
7679 	      newbound = var->glbdom.lb;
7680 	   else if( SCIPsetIsEQ(set, newbound, var->locdom.lb) && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) )  /*lint !e777*/
7681 	      return SCIP_OKAY;
7682 	
7683 	   /* change the bound */
7684 	   oldbound = var->locdom.lb;
7685 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->locdom.ub));
7686 	   var->locdom.lb = newbound;
7687 	
7688 	   /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7689 	    * once update the statistic
7690 	    */
7691 	   if( stat != NULL )
7692 	      SCIPstatIncrement(stat, set, domchgcount);
7693 	
7694 	   if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7695 	   {
7696 	      /* merges overlapping holes into single holes, moves bounds respectively */
7697 	      domMerge(&var->locdom, blkmem, set, &newbound, NULL);
7698 	   }
7699 	
7700 	   /* issue bound change event */
7701 	   assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7702 	   if( var->eventfilter != NULL )
7703 	   {
7704 	      SCIP_CALL( varEventLbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7705 	   }
7706 	
7707 	   /* process parent variables */
7708 	   for( i = 0; i < var->nparentvars; ++i )
7709 	   {
7710 	      parentvar = var->parentvars[i];
7711 	      assert(parentvar != NULL);
7712 	
7713 	      switch( SCIPvarGetStatus(parentvar) )
7714 	      {
7715 	      case SCIP_VARSTATUS_ORIGINAL:
7716 	         SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7717 	         break;
7718 	
7719 	      case SCIP_VARSTATUS_COLUMN:
7720 	      case SCIP_VARSTATUS_LOOSE:
7721 	      case SCIP_VARSTATUS_FIXED:
7722 	      case SCIP_VARSTATUS_MULTAGGR:
7723 	         SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7724 	         return SCIP_INVALIDDATA;
7725 	
7726 	      case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
7727 	         assert(parentvar->data.aggregate.var == var);
7728 	         if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7729 	         {
7730 	            SCIP_Real parentnewbound;
7731 	
7732 	            /* a > 0 -> change lower bound of y */
7733 	            assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, -oldbound)
7734 	               || SCIPsetIsFeasEQ(set, parentvar->locdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7735 	               || (SCIPsetIsZero(set, parentvar->locdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7736 	
7737 	            if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7738 	            {
7739 	               parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7740 	               /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7741 	                * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7742 	                * as a result, the parent's lower bound is set to it's upper bound, and not above
7743 	                */
7744 	               if( parentnewbound > parentvar->glbdom.ub )
7745 	               {
7746 	                  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7747 	                  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7748 	                  parentnewbound = parentvar->glbdom.ub;
7749 	               }
7750 	            }
7751 	            else
7752 	               parentnewbound = newbound;
7753 	            SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7754 	         }
7755 	         else
7756 	         {
7757 	            SCIP_Real parentnewbound;
7758 	
7759 	            /* a < 0 -> change upper bound of y */
7760 	            assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7761 	            assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, -oldbound)
7762 	               || SCIPsetIsFeasEQ(set, parentvar->locdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7763 	               || (SCIPsetIsZero(set, parentvar->locdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7764 	
7765 	            if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7766 	            {
7767 	               parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7768 	               /* 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
7769 	                * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7770 	                * as a result, the parent's upper bound is set to it's lower bound, and not below
7771 	                */
7772 	               if( parentnewbound < parentvar->glbdom.lb )
7773 	               {
7774 	                  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7775 	                  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7776 	                  parentnewbound = parentvar->glbdom.lb;
7777 	               }
7778 	            }
7779 	            else
7780 	               parentnewbound = -newbound;
7781 	            SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7782 	         }
7783 	         break;
7784 	
7785 	      case SCIP_VARSTATUS_NEGATED: /* x = offset - x'  ->  x' = offset - x */
7786 	         assert(parentvar->negatedvar != NULL);
7787 	         assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7788 	         assert(parentvar->negatedvar->negatedvar == parentvar);
7789 	         SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7790 	               parentvar->data.negate.constant - newbound) );
7791 	         break;
7792 	
7793 	      default:
7794 	         SCIPerrorMessage("unknown variable status\n");
7795 	         return SCIP_INVALIDDATA;
7796 	      }
7797 	   }
7798 	
7799 	   return SCIP_OKAY;
7800 	}
7801 	
7802 	/** performs the current change in upper bound, changes all parents accordingly */
7803 	static
7804 	SCIP_RETCODE varProcessChgUbLocal(
7805 	   SCIP_VAR*             var,                /**< problem variable to change */
7806 	   BMS_BLKMEM*           blkmem,             /**< block memory */
7807 	   SCIP_SET*             set,                /**< global SCIP settings */
7808 	   SCIP_STAT*            stat,               /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7809 	   SCIP_LP*              lp,                 /**< current LP data, may be NULL for original variables */
7810 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage, may be NULL for original variables */
7811 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
7812 	   SCIP_Real             newbound            /**< new bound for variable */
7813 	   )
7814 	{
7815 	   SCIP_VAR* parentvar;
7816 	   SCIP_Real oldbound;
7817 	   int i;
7818 	
7819 	   assert(var != NULL);
7820 	   assert(set != NULL);
7821 	   assert(var->scip == set->scip);
7822 	   assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7823 	            || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7824 	      || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && (SCIPsetIsIntegral(set, newbound)
7825 	            || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7826 	      || SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
7827 	
7828 	   /* check that the bound is feasible */
7829 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, var->glbdom.lb));
7830 	   /* adjust bound to integral value if variable is of integral type */
7831 	   newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7832 	
7833 	   if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7834 	   {
7835 	      /* we do not want to undercut the lower bound, which could have happened due to numerics */
7836 	      newbound = MAX(newbound, var->locdom.lb);
7837 	
7838 	      /* we do not want to exceed the global upper bound, which could have happened due to numerics */
7839 	      newbound = MIN(newbound, var->glbdom.ub);
7840 	   }
7841 	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7842 	
7843 	   SCIPsetDebugMsg(set, "process changing upper bound of <%s> from %g to %g\n", var->name, var->locdom.ub, newbound);
7844 	
7845 	   if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && var->glbdom.ub != var->locdom.ub  ) /*lint !e777*/
7846 	      newbound = var->glbdom.ub;
7847 	   else if( SCIPsetIsEQ(set, newbound, var->locdom.ub) && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) )  /*lint !e777*/
7848 	      return SCIP_OKAY;
7849 	
7850 	   /* change the bound */
7851 	   oldbound = var->locdom.ub;
7852 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->locdom.lb));
7853 	   var->locdom.ub = newbound;
7854 	
7855 	   /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7856 	    * once update the statistic
7857 	    */
7858 	   if( stat != NULL )
7859 	      SCIPstatIncrement(stat, set, domchgcount);
7860 	
7861 	   if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7862 	   {
7863 	      /* merges overlapping holes into single holes, moves bounds respectively */
7864 	      domMerge(&var->locdom, blkmem, set, NULL, &newbound);
7865 	   }
7866 	
7867 	   /* issue bound change event */
7868 	   assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7869 	   if( var->eventfilter != NULL )
7870 	   {
7871 	      SCIP_CALL( varEventUbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7872 	   }
7873 	
7874 	   /* process parent variables */
7875 	   for( i = 0; i < var->nparentvars; ++i )
7876 	   {
7877 	      parentvar = var->parentvars[i];
7878 	      assert(parentvar != NULL);
7879 	
7880 	      switch( SCIPvarGetStatus(parentvar) )
7881 	      {
7882 	      case SCIP_VARSTATUS_ORIGINAL:
7883 	         SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7884 	         break;
7885 	
7886 	      case SCIP_VARSTATUS_COLUMN:
7887 	      case SCIP_VARSTATUS_LOOSE:
7888 	      case SCIP_VARSTATUS_FIXED:
7889 	      case SCIP_VARSTATUS_MULTAGGR:
7890 	         SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7891 	         return SCIP_INVALIDDATA;
7892 	
7893 	      case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
7894 	         assert(parentvar->data.aggregate.var == var);
7895 	         if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7896 	         {
7897 	            SCIP_Real parentnewbound;
7898 	
7899 	            /* a > 0 -> change upper bound of x */
7900 	            assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, oldbound)
7901 	               || SCIPsetIsFeasEQ(set, parentvar->locdom.ub,
7902 	                  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7903 	            if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7904 	            {
7905 	               parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7906 	               /* 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
7907 	                * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7908 	                * as a result, the parent's upper bound is set to it's lower bound, and not below
7909 	                */
7910 	               if( parentnewbound < parentvar->glbdom.lb )
7911 	               {
7912 	                  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7913 	                  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7914 	                  parentnewbound = parentvar->glbdom.lb;
7915 	               }
7916 	            }
7917 	            else
7918 	               parentnewbound = newbound;
7919 	            SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7920 	         }
7921 	         else
7922 	         {
7923 	            SCIP_Real parentnewbound;
7924 	
7925 	            /* a < 0 -> change lower bound of x */
7926 	            assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7927 	            assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, oldbound)
7928 	               || SCIPsetIsFeasEQ(set, parentvar->locdom.lb,
7929 	                  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7930 	            if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7931 	            {
7932 	               parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7933 	               /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7934 	                * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7935 	                * as a result, the parent's lower bound is set to it's upper bound, and not above
7936 	                */
7937 	               if( parentnewbound > parentvar->glbdom.ub )
7938 	               {
7939 	                  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7940 	                  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7941 	                  parentnewbound = parentvar->glbdom.ub;
7942 	               }
7943 	            }
7944 	            else
7945 	               parentnewbound = -newbound;
7946 	            SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7947 	         }
7948 	         break;
7949 	
7950 	      case SCIP_VARSTATUS_NEGATED: /* x = offset - x'  ->  x' = offset - x */
7951 	         assert(parentvar->negatedvar != NULL);
7952 	         assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7953 	         assert(parentvar->negatedvar->negatedvar == parentvar);
7954 	         SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7955 	               parentvar->data.negate.constant - newbound) );
7956 	         break;
7957 	
7958 	      default:
7959 	         SCIPerrorMessage("unknown variable status\n");
7960 	         return SCIP_INVALIDDATA;
7961 	      }
7962 	   }
7963 	
7964 	   return SCIP_OKAY;
7965 	}
7966 	
7967 	/** changes current local lower bound of variable; if possible, adjusts bound to integral value; stores inference
7968 	 *  information in variable
7969 	 */
7970 	SCIP_RETCODE SCIPvarChgLbLocal(
7971 	   SCIP_VAR*             var,                /**< problem variable to change */
7972 	   BMS_BLKMEM*           blkmem,             /**< block memory */
7973 	   SCIP_SET*             set,                /**< global SCIP settings */
7974 	   SCIP_STAT*            stat,               /**< problem statistics */
7975 	   SCIP_LP*              lp,                 /**< current LP data, may be NULL for original variables */
7976 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage, may be NULL for original variables */
7977 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
7978 	   SCIP_Real             newbound            /**< new bound for variable */
7979 	   )
7980 	{
7981 	   assert(var != NULL);
7982 	   assert(blkmem != NULL);
7983 	   assert(set != NULL);
7984 	   assert(var->scip == set->scip);
7985 	
7986 	   /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7987 	    * of the domain within feastol
7988 	    */
7989 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7990 	
7991 	   /* adjust bound to integral value if variable is of integral type */
7992 	   newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7993 	
7994 	   /* check that the adjusted bound is feasible */
7995 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7996 	
7997 	   if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7998 	   {
7999 	      /* we do not want to exceed the upperbound, which could have happened due to numerics */
8000 	      newbound = MIN(newbound, var->locdom.ub);
8001 	   }
8002 	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
8003 	
8004 	   SCIPsetDebugMsg(set, "changing lower bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
8005 	
8006 	   if( SCIPsetIsEQ(set, var->locdom.lb, newbound) && (!SCIPsetIsEQ(set, var->glbdom.lb, newbound) || var->locdom.lb == newbound) /*lint !e777*/
8007 	         && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) ) /*lint !e777*/
8008 	      return SCIP_OKAY;
8009 	
8010 	   /* change bounds of attached variables */
8011 	   switch( SCIPvarGetStatus(var) )
8012 	   {
8013 	   case SCIP_VARSTATUS_ORIGINAL:
8014 	      if( var->data.original.transvar != NULL )
8015 	      {
8016 	         SCIP_CALL( SCIPvarChgLbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
8017 	               newbound) );
8018 	      }
8019 	      else
8020 	      {
8021 	         assert(set->stage == SCIP_STAGE_PROBLEM);
8022 	         SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8023 	      }
8024 	      break;
8025 	
8026 	   case SCIP_VARSTATUS_COLUMN:
8027 	   case SCIP_VARSTATUS_LOOSE:
8028 	      SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8029 	      break;
8030 	
8031 	   case SCIP_VARSTATUS_FIXED:
8032 	      SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8033 	      return SCIP_INVALIDDATA;
8034 	
8035 	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
8036 	      assert(var->data.aggregate.var != NULL);
8037 	      if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8038 	      {
8039 	         SCIP_Real childnewbound;
8040 	
8041 	         /* a > 0 -> change lower bound of y */
8042 	         assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
8043 	            || SCIPsetIsFeasEQ(set, var->locdom.lb,
8044 	               var->data.aggregate.var->locdom.lb * var->data.aggregate.scalar + var->data.aggregate.constant));
8045 	         if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8046 	            childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8047 	         else
8048 	            childnewbound = newbound;
8049 	         SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8050 	               childnewbound) );
8051 	      }
8052 	      else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8053 	      {
8054 	         SCIP_Real childnewbound;
8055 	
8056 	         /* a < 0 -> change upper bound of y */
8057 	         assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
8058 	            || SCIPsetIsFeasEQ(set, var->locdom.lb,
8059 	               var->data.aggregate.var->locdom.ub * var->data.aggregate.scalar + var->data.aggregate.constant));
8060 	         if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8061 	            childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8062 	         else
8063 	            childnewbound = -newbound;
8064 	         SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8065 	               childnewbound) );
8066 	      }
8067 	      else
8068 	      {
8069 	         SCIPerrorMessage("scalar is zero in aggregation\n");
8070 	         return SCIP_INVALIDDATA;
8071 	      }
8072 	      break;
8073 	
8074 	   case SCIP_VARSTATUS_MULTAGGR:
8075 	      SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8076 	      return SCIP_INVALIDDATA;
8077 	
8078 	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
8079 	      assert(var->negatedvar != NULL);
8080 	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
8081 	      assert(var->negatedvar->negatedvar == var);
8082 	      SCIP_CALL( SCIPvarChgUbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
8083 	            var->data.negate.constant - newbound) );
8084 	      break;
8085 	
8086 	   default:
8087 	      SCIPerrorMessage("unknown variable status\n");
8088 	      return SCIP_INVALIDDATA;
8089 	   }
8090 	
8091 	   return SCIP_OKAY;
8092 	}
8093 	
8094 	/** changes current local upper bound of variable; if possible, adjusts bound to integral value; stores inference
8095 	 *  information in variable
8096 	 */
8097 	SCIP_RETCODE SCIPvarChgUbLocal(
8098 	   SCIP_VAR*             var,                /**< problem variable to change */
8099 	   BMS_BLKMEM*           blkmem,             /**< block memory */
8100 	   SCIP_SET*             set,                /**< global SCIP settings */
8101 	   SCIP_STAT*            stat,               /**< problem statistics */
8102 	   SCIP_LP*              lp,                 /**< current LP data, may be NULL for original variables */
8103 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage, may be NULL for original variables */
8104 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
8105 	   SCIP_Real             newbound            /**< new bound for variable */
8106 	   )
8107 	{
8108 	   assert(var != NULL);
8109 	   assert(blkmem != NULL);
8110 	   assert(set != NULL);
8111 	   assert(var->scip == set->scip);
8112 	
8113 	   /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
8114 	    * of the domain within feastol
8115 	    */
8116 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
8117 	
8118 	   /* adjust bound to integral value if variable is of integral type */
8119 	   newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
8120 	
8121 	   /* check that the adjusted bound is feasible */
8122 	   assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
8123 	
8124 	   if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
8125 	   {
8126 	      /* we do not want to undercut the lowerbound, which could have happened due to numerics */
8127 	      newbound = MAX(newbound, var->locdom.lb);
8128 	   }
8129 	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
8130 	
8131 	   SCIPsetDebugMsg(set, "changing upper bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
8132 	
8133 	   if( SCIPsetIsEQ(set, var->locdom.ub, newbound) && (!SCIPsetIsEQ(set, var->glbdom.ub, newbound) || var->locdom.ub == newbound) /*lint !e777*/
8134 	      && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) ) /*lint !e777*/
8135 	      return SCIP_OKAY;
8136 	
8137 	   /* change bounds of attached variables */
8138 	   switch( SCIPvarGetStatus(var) )
8139 	   {
8140 	   case SCIP_VARSTATUS_ORIGINAL:
8141 	      if( var->data.original.transvar != NULL )
8142 	      {
8143 	         SCIP_CALL( SCIPvarChgUbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8144 	      }
8145 	      else
8146 	      {
8147 	         assert(set->stage == SCIP_STAGE_PROBLEM);
8148 	         SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8149 	      }
8150 	      break;
8151 	
8152 	   case SCIP_VARSTATUS_COLUMN:
8153 	   case SCIP_VARSTATUS_LOOSE:
8154 	      SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8155 	      break;
8156 	
8157 	   case SCIP_VARSTATUS_FIXED:
8158 	      SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8159 	      return SCIP_INVALIDDATA;
8160 	
8161 	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
8162 	      assert(var->data.aggregate.var != NULL);
8163 	      if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8164 	      {
8165 	         SCIP_Real childnewbound;
8166 	
8167 	         /* a > 0 -> change upper bound of y */
8168 	         assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
8169 	            || SCIPsetIsFeasEQ(set, var->locdom.ub,
8170 	               var->data.aggregate.var->locdom.ub * var->data.aggregate.scalar + var->data.aggregate.constant));
8171 	         if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8172 	            childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8173 	         else
8174 	            childnewbound = newbound;
8175 	         SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8176 	               childnewbound) );
8177 	      }
8178 	      else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8179 	      {
8180 	         SCIP_Real childnewbound;
8181 	
8182 	         /* a < 0 -> change lower bound of y */
8183 	         assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
8184 	            || SCIPsetIsFeasEQ(set, var->locdom.ub,
8185 	               var->data.aggregate.var->locdom.lb * var->data.aggregate.scalar + var->data.aggregate.constant));
8186 	         if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8187 	            childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8188 	         else
8189 	            childnewbound = -newbound;
8190 	         SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8191 	               childnewbound) );
8192 	      }
8193 	      else
8194 	      {
8195 	         SCIPerrorMessage("scalar is zero in aggregation\n");
8196 	         return SCIP_INVALIDDATA;
8197 	      }
8198 	      break;
8199 	
8200 	   case SCIP_VARSTATUS_MULTAGGR:
8201 	      SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8202 	      return SCIP_INVALIDDATA;
8203 	
8204 	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
8205 	      assert(var->negatedvar != NULL);
8206 	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
8207 	      assert(var->negatedvar->negatedvar == var);
8208 	      SCIP_CALL( SCIPvarChgLbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
8209 	            var->data.negate.constant - newbound) );
8210 	      break;
8211 	
8212 	   default:
8213 	      SCIPerrorMessage("unknown variable status\n");
8214 	      return SCIP_INVALIDDATA;
8215 	   }
8216 	
8217 	   return SCIP_OKAY;
8218 	}
8219 	
8220 	/** changes current local bound of variable; if possible, adjusts bound to integral value; stores inference
8221 	 *  information in variable
8222 	 */
8223 	SCIP_RETCODE SCIPvarChgBdLocal(
8224 	   SCIP_VAR*             var,                /**< problem variable to change */
8225 	   BMS_BLKMEM*           blkmem,             /**< block memory */
8226 	   SCIP_SET*             set,                /**< global SCIP settings */
8227 	   SCIP_STAT*            stat,               /**< problem statistics */
8228 	   SCIP_LP*              lp,                 /**< current LP data, may be NULL for original variables */
8229 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage, may be NULL for original variables */
8230 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
8231 	   SCIP_Real             newbound,           /**< new bound for variable */
8232 	   SCIP_BOUNDTYPE        boundtype           /**< type of bound: lower or upper bound */
8233 	   )
8234 	{
8235 	   /* apply bound change to the LP data */
8236 	   switch( boundtype )
8237 	   {
8238 	   case SCIP_BOUNDTYPE_LOWER:
8239 	      return SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
8240 	   case SCIP_BOUNDTYPE_UPPER:
8241 	      return SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
8242 	   default:
8243 	      SCIPerrorMessage("unknown bound type\n");
8244 	      return SCIP_INVALIDDATA;
8245 	   }
8246 	}
8247 	
8248 	/** changes lower bound of variable in current dive; if possible, adjusts bound to integral value */
8249 	SCIP_RETCODE SCIPvarChgLbDive(
8250 	   SCIP_VAR*             var,                /**< problem variable to change */
8251 	   SCIP_SET*             set,                /**< global SCIP settings */
8252 	   SCIP_LP*              lp,                 /**< current LP data */
8253 	   SCIP_Real             newbound            /**< new bound for variable */
8254 	   )
8255 	{
8256 	   assert(var != NULL);
8257 	   assert(set != NULL);
8258 	   assert(var->scip == set->scip);
8259 	   assert(lp != NULL);
8260 	   assert(SCIPlpDiving(lp));
8261 	
8262 	   /* adjust bound for integral variables */
8263 	   SCIPvarAdjustLb(var, set, &newbound);
8264 	
8265 	   SCIPsetDebugMsg(set, "changing lower bound of <%s> to %g in current dive\n", var->name, newbound);
8266 	
8267 	   /* change bounds of attached variables */
8268 	   switch( SCIPvarGetStatus(var) )
8269 	   {
8270 	   case SCIP_VARSTATUS_ORIGINAL:
8271 	      assert(var->data.original.transvar != NULL);
8272 	      SCIP_CALL( SCIPvarChgLbDive(var->data.original.transvar, set, lp, newbound) );
8273 	      break;
8274 	
8275 	   case SCIP_VARSTATUS_COLUMN:
8276 	      assert(var->data.col != NULL);
8277 	      SCIP_CALL( SCIPcolChgLb(var->data.col, set, lp, newbound) );
8278 	      break;
8279 	
8280 	   case SCIP_VARSTATUS_LOOSE:
8281 	      SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
8282 	      return SCIP_INVALIDDATA;
8283 	
8284 	   case SCIP_VARSTATUS_FIXED:
8285 	      SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8286 	      return SCIP_INVALIDDATA;
8287 	
8288 	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
8289 	      assert(var->data.aggregate.var != NULL);
8290 	      if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8291 	      {
8292 	         SCIP_Real childnewbound;
8293 	
8294 	         /* a > 0 -> change lower bound of y */
8295 	         if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8296 	            childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8297 	         else
8298 	            childnewbound = newbound;
8299 	         SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8300 	      }
8301 	      else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8302 	      {
8303 	         SCIP_Real childnewbound;
8304 	
8305 	         /* a < 0 -> change upper bound of y */
8306 	         if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8307 	            childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8308 	         else
8309 	            childnewbound = -newbound;
8310 	         SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8311 	      }
8312 	      else
8313 	      {
8314 	         SCIPerrorMessage("scalar is zero in aggregation\n");
8315 	         return SCIP_INVALIDDATA;
8316 	      }
8317 	      break;
8318 	
8319 	   case SCIP_VARSTATUS_MULTAGGR:
8320 	      SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8321 	      return SCIP_INVALIDDATA;
8322 	
8323 	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
8324 	      assert(var->negatedvar != NULL);
8325 	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
8326 	      assert(var->negatedvar->negatedvar == var);
8327 	      SCIP_CALL( SCIPvarChgUbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8328 	      break;
8329 	
8330 	   default:
8331 	      SCIPerrorMessage("unknown variable status\n");
8332 	      return SCIP_INVALIDDATA;
8333 	   }
8334 	
8335 	   return SCIP_OKAY;
8336 	}
8337 	
8338 	/** changes upper bound of variable in current dive; if possible, adjusts bound to integral value */
8339 	SCIP_RETCODE SCIPvarChgUbDive(
8340 	   SCIP_VAR*             var,                /**< problem variable to change */
8341 	   SCIP_SET*             set,                /**< global SCIP settings */
8342 	   SCIP_LP*              lp,                 /**< current LP data */
8343 	   SCIP_Real             newbound            /**< new bound for variable */
8344 	   )
8345 	{
8346 	   assert(var != NULL);
8347 	   assert(set != NULL);
8348 	   assert(var->scip == set->scip);
8349 	   assert(lp != NULL);
8350 	   assert(SCIPlpDiving(lp));
8351 	
8352 	   /* adjust bound for integral variables */
8353 	   SCIPvarAdjustUb(var, set, &newbound);
8354 	
8355 	   SCIPsetDebugMsg(set, "changing upper bound of <%s> to %g in current dive\n", var->name, newbound);
8356 	
8357 	   /* change bounds of attached variables */
8358 	   switch( SCIPvarGetStatus(var) )
8359 	   {
8360 	   case SCIP_VARSTATUS_ORIGINAL:
8361 	      assert(var->data.original.transvar != NULL);
8362 	      SCIP_CALL( SCIPvarChgUbDive(var->data.original.transvar, set, lp, newbound) );
8363 	      break;
8364 	
8365 	   case SCIP_VARSTATUS_COLUMN:
8366 	      assert(var->data.col != NULL);
8367 	      SCIP_CALL( SCIPcolChgUb(var->data.col, set, lp, newbound) );
8368 	      break;
8369 	
8370 	   case SCIP_VARSTATUS_LOOSE:
8371 	      SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
8372 	      return SCIP_INVALIDDATA;
8373 	
8374 	   case SCIP_VARSTATUS_FIXED:
8375 	      SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8376 	      return SCIP_INVALIDDATA;
8377 	
8378 	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
8379 	      assert(var->data.aggregate.var != NULL);
8380 	      if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8381 	      {
8382 	         SCIP_Real childnewbound;
8383 	
8384 	         /* a > 0 -> change upper bound of y */
8385 	         if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8386 	            childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8387 	         else
8388 	            childnewbound = newbound;
8389 	         SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8390 	      }
8391 	      else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8392 	      {
8393 	         SCIP_Real childnewbound;
8394 	
8395 	         /* a < 0 -> change lower bound of y */
8396 	         if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8397 	            childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8398 	         else
8399 	            childnewbound = -newbound;
8400 	         SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8401 	      }
8402 	      else
8403 	      {
8404 	         SCIPerrorMessage("scalar is zero in aggregation\n");
8405 	         return SCIP_INVALIDDATA;
8406 	      }
8407 	      break;
8408 	
8409 	   case SCIP_VARSTATUS_MULTAGGR:
8410 	      SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8411 	      return SCIP_INVALIDDATA;
8412 	
8413 	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
8414 	      assert(var->negatedvar != NULL);
8415 	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
8416 	      assert(var->negatedvar->negatedvar == var);
8417 	      SCIP_CALL( SCIPvarChgLbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8418 	      break;
8419 	
8420 	   default:
8421 	      SCIPerrorMessage("unknown variable status\n");
8422 	      return SCIP_INVALIDDATA;
8423 	   }
8424 	
8425 	   return SCIP_OKAY;
8426 	}
8427 	
8428 	/** for a multi-aggregated variable, gives the local lower bound computed by adding the local bounds from all
8429 	 *  aggregation variables, this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is
8430 	 *  not updated if bounds of aggregation variables are changing
8431 	 *
8432 	 *  calling this function for a non-multi-aggregated variable is not allowed
8433 	 */
8434 	SCIP_Real SCIPvarGetMultaggrLbLocal(
8435 	   SCIP_VAR*             var,                /**< problem variable */
8436 	   SCIP_SET*             set                 /**< global SCIP settings */
8437 	   )
8438 	{
8439 	   int i;
8440 	   SCIP_Real lb;
8441 	   SCIP_Real bnd;
8442 	   SCIP_VAR* aggrvar;
8443 	   SCIP_Bool posinf;
8444 	   SCIP_Bool neginf;
8445 	
8446 	   assert(var != NULL);
8447 	   assert(set != NULL);
8448 	   assert(var->scip == set->scip);
8449 	   assert((SCIP_VARSTATUS) var->varstatus == SCIP_VARSTATUS_MULTAGGR);
8450 	
8451 	   posinf = FALSE;
8452 	   neginf = FALSE;
8453 	   lb = var->data.multaggr.constant;
8454 	   for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8455 	   {
8456 	      aggrvar = var->data.multaggr.vars[i];
8457 	      if( var->data.multaggr.scalars[i] > 0.0 )
8458 	      {
8459 	         bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8460 	
8461 	         if( SCIPsetIsInfinity(set, bnd) )
8462 	            posinf = TRUE;
8463 	         else if( SCIPsetIsInfinity(set, -bnd) )
8464 	            neginf = TRUE;
8465 	         else
8466 	            lb += var->data.multaggr.scalars[i] * bnd;
8467 	      }
8468 	      else
8469 	      {
8470 	         bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8471 	
8472 	         if( SCIPsetIsInfinity(set, -bnd) )
8473 	            posinf = TRUE;
8474 	         else if( SCIPsetIsInfinity(set, bnd) )
8475 	            neginf = TRUE;
8476 	         else
8477 	            lb += var->data.multaggr.scalars[i] * bnd;
8478 	      }
8479 	
8480 	      /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
8481 	       * variable
8482 	       */
8483 	      if( neginf )
8484 	         return SCIPvarGetLbLocal(var);
8485 	   }
8486 	
8487 	   /* if positive infinity flag was set to true return infinity */
8488 	   if( posinf )
8489 	      return SCIPsetInfinity(set);
8490 	
8491 	   return (MAX(lb, SCIPvarGetLbLocal(var))); /*lint !e666*/
8492 	}
8493 	
8494 	/** for a multi-aggregated variable, gives the local upper bound computed by adding the local bounds from all
8495 	 *  aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is
8496 	 *  not updated if bounds of aggregation variables are changing
8497 	 *
8498 	 *  calling this function for a non-multi-aggregated variable is not allowed
8499 	 */
8500 	SCIP_Real SCIPvarGetMultaggrUbLocal(
8501 	   SCIP_VAR*             var,                /**< problem variable */
8502 	   SCIP_SET*             set                 /**< global SCIP settings */
8503 	   )
8504 	{
8505 	   int i;
8506 	   SCIP_Real ub;
8507 	   SCIP_Real bnd;
8508 	   SCIP_VAR* aggrvar;
8509 	   SCIP_Bool posinf;
8510 	   SCIP_Bool neginf;
8511 	
8512 	   assert(var != NULL);
8513 	   assert(set != NULL);
8514 	   assert(var->scip == set->scip);
8515 	   assert((SCIP_VARSTATUS) var->varstatus == SCIP_VARSTATUS_MULTAGGR);
8516 	
8517 	   posinf = FALSE;
8518 	   neginf = FALSE;
8519 	   ub = var->data.multaggr.constant;
8520 	   for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8521 	   {
8522 	      aggrvar = var->data.multaggr.vars[i];
8523 	      if( var->data.multaggr.scalars[i] > 0.0 )
8524 	      {
8525 	         bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8526 	
8527 	         if( SCIPsetIsInfinity(set, bnd) )
8528 	            posinf = TRUE;
8529 	         else if( SCIPsetIsInfinity(set, -bnd) )
8530 	            neginf = TRUE;
8531 	         else
8532 	            ub += var->data.multaggr.scalars[i] * bnd;
8533 	      }
8534 	      else
8535 	      {
8536 	         bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8537 	
8538 	         if( SCIPsetIsInfinity(set, -bnd) )
8539 	            posinf = TRUE;
8540 	         else if( SCIPsetIsInfinity(set, bnd) )
8541 	            neginf = TRUE;
8542 	         else
8543 	            ub += var->data.multaggr.scalars[i] * bnd;
8544 	      }
8545 	
8546 	      /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8547 	       * variable
8548 	       */
8549 	      if( posinf )
8550 	         return SCIPvarGetUbLocal(var);
8551 	   }
8552 	
8553 	   /* if negative infinity flag was set to true return -infinity */
8554 	   if( neginf )
8555 	      return -SCIPsetInfinity(set);
8556 	
8557 	   return (MIN(ub, SCIPvarGetUbLocal(var))); /*lint !e666*/
8558 	}
8559 	
8560 	/** for a multi-aggregated variable, gives the global lower bound computed by adding the global bounds from all
8561 	 *  aggregation variables, this global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is
8562 	 *  not updated if bounds of aggregation variables are changing
8563 	 *
8564 	 *  calling this function for a non-multi-aggregated variable is not allowed
8565 	 */
8566 	SCIP_Real SCIPvarGetMultaggrLbGlobal(
8567 	   SCIP_VAR*             var,                /**< problem variable */
8568 	   SCIP_SET*             set                 /**< global SCIP settings */
8569 	   )
8570 	{
8571 	   int i;
8572 	   SCIP_Real lb;
8573 	   SCIP_Real bnd;
8574 	   SCIP_VAR* aggrvar;
8575 	   SCIP_Bool posinf;
8576 	   SCIP_Bool neginf;
8577 	
8578 	   assert(var != NULL);
8579 	   assert(set != NULL);
8580 	   assert(var->scip == set->scip);
8581 	   assert((SCIP_VARSTATUS) var->varstatus == SCIP_VARSTATUS_MULTAGGR);
8582 	
8583 	   posinf = FALSE;
8584 	   neginf = FALSE;
8585 	   lb = var->data.multaggr.constant;
8586 	   for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8587 	   {
8588 	      aggrvar = var->data.multaggr.vars[i];
8589 	      if( var->data.multaggr.scalars[i] > 0.0 )
8590 	      {
8591 	         bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8592 	
8593 	         if( SCIPsetIsInfinity(set, bnd) )
8594 	            posinf = TRUE;
8595 	         else if( SCIPsetIsInfinity(set, -bnd) )
8596 	            neginf = TRUE;
8597 	         else
8598 	            lb += var->data.multaggr.scalars[i] * bnd;
8599 	      }
8600 	      else
8601 	      {
8602 	         bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8603 	
8604 	         if( SCIPsetIsInfinity(set, -bnd) )
8605 	            posinf = TRUE;
8606 	         else if( SCIPsetIsInfinity(set, bnd) )
8607 	            neginf = TRUE;
8608 	         else
8609 	            lb += var->data.multaggr.scalars[i] * bnd;
8610 	      }
8611 	
8612 	      /* stop if two diffrent infinities (or a -infinity) were found and return global lower bound of multi aggregated
8613 	       * variable
8614 	       */
8615 	      if( neginf )
8616 	         return SCIPvarGetLbGlobal(var);
8617 	   }
8618 	
8619 	   /* if positive infinity flag was set to true return infinity */
8620 	   if( posinf )
8621 	      return SCIPsetInfinity(set);
8622 	
8623 	   return (MAX(lb, SCIPvarGetLbGlobal(var))); /*lint !e666*/
8624 	}
8625 	
8626 	/** for a multi-aggregated variable, gives the global upper bound computed by adding the global bounds from all
8627 	 *  aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is
8628 	 *  not updated if bounds of aggregation variables are changing
8629 	 *
8630 	 *  calling this function for a non-multi-aggregated variable is not allowed
8631 	 */
8632 	SCIP_Real SCIPvarGetMultaggrUbGlobal(
8633 	   SCIP_VAR*             var,                /**< problem variable */
8634 	   SCIP_SET*             set                 /**< global SCIP settings */
8635 	   )
8636 	{
8637 	   int i;
8638 	   SCIP_Real ub;
8639 	   SCIP_Real bnd;
8640 	   SCIP_VAR* aggrvar;
8641 	   SCIP_Bool posinf;
8642 	   SCIP_Bool neginf;
8643 	
8644 	   assert(var != NULL);
8645 	   assert(set != NULL);
8646 	   assert(var->scip == set->scip);
8647 	   assert((SCIP_VARSTATUS) var->varstatus == SCIP_VARSTATUS_MULTAGGR);
8648 	
8649 	   posinf = FALSE;
8650 	   neginf = FALSE;
8651 	   ub = var->data.multaggr.constant;
8652 	   for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8653 	   {
8654 	      aggrvar = var->data.multaggr.vars[i];
8655 	      if( var->data.multaggr.scalars[i] > 0.0 )
8656 	      {
8657 	         bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8658 	
8659 	         if( SCIPsetIsInfinity(set, bnd) )
8660 	            posinf = TRUE;
8661 	         else if( SCIPsetIsInfinity(set, -bnd) )
8662 	            neginf = TRUE;
8663 	         else
8664 	            ub += var->data.multaggr.scalars[i] * bnd;
8665 	      }
8666 	      else
8667 	      {
8668 	         bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8669 	
8670 	         if( SCIPsetIsInfinity(set, -bnd) )
8671 	            posinf = TRUE;
8672 	         else if( SCIPsetIsInfinity(set, bnd) )
8673 	            neginf = TRUE;
8674 	         else
8675 	            ub += var->data.multaggr.scalars[i] * bnd;
8676 	      }
8677 	
8678 	      /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8679 	       * variable
8680 	       */
8681 	      if( posinf )
8682 	         return SCIPvarGetUbGlobal(var);
8683 	   }
8684 	
8685 	   /* if negative infinity flag was set to true return -infinity */
8686 	   if( neginf )
8687 	      return -SCIPsetInfinity(set);
8688 	
8689 	   return (MIN(ub, SCIPvarGetUbGlobal(var))); /*lint !e666*/
8690 	}
8691 	
8692 	/** adds a hole to the original domain of the variable */
8693 	SCIP_RETCODE SCIPvarAddHoleOriginal(
8694 	   SCIP_VAR*             var,                /**< problem variable */
8695 	   BMS_BLKMEM*           blkmem,             /**< block memory */
8696 	   SCIP_SET*             set,                /**< global SCIP settings */
8697 	   SCIP_Real             left,               /**< left bound of open interval in new hole */
8698 	   SCIP_Real             right               /**< right bound of open interval in new hole */
8699 	   )
8700 	{
8701 	   SCIP_Bool added;
8702 	
8703 	   assert(var != NULL);
8704 	   assert(!SCIPvarIsTransformed(var));
8705 	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL || SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
8706 	   assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8707 	   assert(set != NULL);
8708 	   assert(var->scip == set->scip);
8709 	   assert(set->stage == SCIP_STAGE_PROBLEM);
8710 	
8711 	   SCIPsetDebugMsg(set, "adding original hole (%g,%g) to <%s>\n", left, right, var->name);
8712 	
8713 	   if( SCIPsetIsEQ(set, left, right) )
8714 	      return SCIP_OKAY;
8715 	
8716 	   /* the interval should not be empty */
8717 	   assert(SCIPsetIsLT(set, left, right));
8718 	
8719 	   /* the the interval bound should already be adjusted */
8720 	   assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8721 	   assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8722 	
8723 	   /* the the interval should lay between the lower and upper bound */
8724 	   assert(SCIPsetIsGE(set, left, SCIPvarGetLbOriginal(var)));
8725 	   assert(SCIPsetIsLE(set, right, SCIPvarGetUbOriginal(var)));
8726 	
8727 	   /* add domain hole */
8728 	   SCIP_CALL( domAddHole(&var->data.original.origdom, blkmem, set, left, right, &added) );
8729 	
8730 	   /* merges overlapping holes into single holes, moves bounds respectively if hole was added */
8731 	   if( added )
8732 	   {
8733 	      domMerge(&var->data.original.origdom, blkmem, set, NULL, NULL);
8734 	   }
8735 	
8736 	   /**@todo add hole in parent and child variables (just like with bound changes);
8737 	    *       warning! original vars' holes are in original blkmem, transformed vars' holes in transformed blkmem
8738 	    */
8739 	
8740 	   return SCIP_OKAY;
8741 	}
8742 	
8743 	/** performs the current add of domain, changes all parents accordingly */
8744 	static
8745 	SCIP_RETCODE varProcessAddHoleGlobal(
8746 	   SCIP_VAR*             var,                /**< problem variable */
8747 	   BMS_BLKMEM*           blkmem,             /**< block memory */
8748 	   SCIP_SET*             set,                /**< global SCIP settings */
8749 	   SCIP_STAT*            stat,               /**< problem statistics */
8750 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
8751 	   SCIP_Real             left,               /**< left bound of open interval in new hole */
8752 	   SCIP_Real             right,              /**< right bound of open interval in new hole */
8753 	   SCIP_Bool*            added               /**< pointer to store whether the hole was added */
8754 	   )
8755 	{
8756 	   SCIP_VAR* parentvar;
8757 	   SCIP_Real newlb;
8758 	   SCIP_Real newub;
8759 	   int i;
8760 	
8761 	   assert(var != NULL);
8762 	   assert(added != NULL);
8763 	   assert(blkmem != NULL);
8764 	
8765 	   /* the interval should not be empty */
8766 	   assert(SCIPsetIsLT(set, left, right));
8767 	
8768 	   /* the interval bound should already be adjusted */
8769 	   assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8770 	   assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8771 	
8772 	   /* the interval should lay between the lower and upper bound */
8773 	   assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8774 	   assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8775 	
8776 	   /* @todo add debugging mechanism for holes when using a debugging solution */
8777 	
8778 	   /* add hole to hole list */
8779 	   SCIP_CALL( domAddHole(&var->glbdom, blkmem, set, left, right, added) );
8780 	
8781 	   /* check if the hole is redundant */
8782 	   if( !(*added) )
8783 	      return SCIP_OKAY;
8784 	
8785 	   /* current bounds */
8786 	   newlb = var->glbdom.lb;
8787 	   newub = var->glbdom.ub;
8788 	
8789 	   /* merge domain holes */
8790 	   domMerge(&var->glbdom, blkmem, set, &newlb, &newub);
8791 	
8792 	   /* the bound should not be changed */
8793 	   assert(SCIPsetIsEQ(set, newlb, var->glbdom.lb));
8794 	   assert(SCIPsetIsEQ(set, newub, var->glbdom.ub));
8795 	
8796 	   /* issue bound change event */
8797 	   assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8798 	   if( var->eventfilter != NULL )
8799 	   {
8800 	      SCIP_CALL( varEventGholeAdded(var, blkmem, set, eventqueue, left, right) );
8801 	   }
8802 	
8803 	   /* process parent variables */
8804 	   for( i = 0; i < var->nparentvars; ++i )
8805 	   {
8806 	      SCIP_Real parentnewleft;
8807 	      SCIP_Real parentnewright;
8808 	      SCIP_Bool localadded;
8809 	
8810 	      parentvar = var->parentvars[i];
8811 	      assert(parentvar != NULL);
8812 	
8813 	      switch( SCIPvarGetStatus(parentvar) )
8814 	      {
8815 	      case SCIP_VARSTATUS_ORIGINAL:
8816 	         parentnewleft = left;
8817 	         parentnewright = right;
8818 	         break;
8819 	
8820 	      case SCIP_VARSTATUS_COLUMN:
8821 	      case SCIP_VARSTATUS_LOOSE:
8822 	      case SCIP_VARSTATUS_FIXED:
8823 	      case SCIP_VARSTATUS_MULTAGGR:
8824 	         SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8825 	         return SCIP_INVALIDDATA;
8826 	
8827 	      case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
8828 	         assert(parentvar->data.aggregate.var == var);
8829 	
8830 	         if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8831 	         {
8832 	            /* a > 0 -> change upper bound of x */
8833 	            parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8834 	            parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8835 	         }
8836 	         else
8837 	         {
8838 	            /* a < 0 -> change lower bound of x */
8839 	            assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8840 	
8841 	            parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8842 	            parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8843 	         }
8844 	         break;
8845 	
8846 	      case SCIP_VARSTATUS_NEGATED: /* x = offset - x'  ->  x' = offset - x */
8847 	         assert(parentvar->negatedvar != NULL);
8848 	         assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8849 	         assert(parentvar->negatedvar->negatedvar == parentvar);
8850 	
8851 	         parentnewright = -left + parentvar->data.negate.constant;
8852 	         parentnewleft = -right + parentvar->data.negate.constant;
8853 	         break;
8854 	
8855 	      default:
8856 	         SCIPerrorMessage("unknown variable status\n");
8857 	         return SCIP_INVALIDDATA;
8858 	      }
8859 	
8860 	      SCIPsetDebugMsg(set, "add global hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8861 	
8862 	      /* perform hole added for parent variable */
8863 	      assert(blkmem != NULL);
8864 	      assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8865 	      SCIP_CALL( varProcessAddHoleGlobal(parentvar, blkmem, set, stat, eventqueue, 
8866 	            parentnewleft, parentnewright, &localadded) );
8867 	      assert(localadded);
8868 	   }
8869 	
8870 	   return SCIP_OKAY;
8871 	}
8872 	
8873 	/** adds a hole to the variable's global and local domain */
8874 	SCIP_RETCODE SCIPvarAddHoleGlobal(
8875 	   SCIP_VAR*             var,                /**< problem variable */
8876 	   BMS_BLKMEM*           blkmem,             /**< block memory */
8877 	   SCIP_SET*             set,                /**< global SCIP settings */
8878 	   SCIP_STAT*            stat,               /**< problem statistics */
8879 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
8880 	   SCIP_Real             left,               /**< left bound of open interval in new hole */
8881 	   SCIP_Real             right,              /**< right bound of open interval in new hole */
8882 	   SCIP_Bool*            added               /**< pointer to store whether the hole was added */
8883 	   )
8884 	{
8885 	   SCIP_Real childnewleft;
8886 	   SCIP_Real childnewright;
8887 	
8888 	   assert(var != NULL);
8889 	   assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8890 	   assert(blkmem != NULL);
8891 	   assert(added != NULL);
8892 	
8893 	   SCIPsetDebugMsg(set, "adding global hole (%g,%g) to <%s>\n", left, right, var->name);
8894 	
8895 	   /* the interval should not be empty */
8896 	   assert(SCIPsetIsLT(set, left, right));
8897 	
8898 	   /* the the interval bound should already be adjusted */
8899 	   assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8900 	   assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8901 	
8902 	   /* the the interval should lay between the lower and upper bound */
8903 	   assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8904 	   assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8905 	
8906 	   /* change bounds of attached variables */
8907 	   switch( SCIPvarGetStatus(var) )
8908 	   {
8909 	   case SCIP_VARSTATUS_ORIGINAL:
8910 	      if( var->data.original.transvar != NULL )
8911 	      {
8912 	         SCIP_CALL( SCIPvarAddHoleGlobal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8913 	               left, right, added) );
8914 	      }
8915 	      else
8916 	      {
8917 	         assert(set->stage == SCIP_STAGE_PROBLEM);
8918 	
8919 	         SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8920 	         if( *added )
8921 	         {
8922 	            SCIP_Bool localadded;
8923 	
8924 	            SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8925 	         }
8926 	      }
8927 	      break;
8928 	
8929 	   case SCIP_VARSTATUS_COLUMN:
8930 	   case SCIP_VARSTATUS_LOOSE:
8931 	      SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8932 	      if( *added )
8933 	      {
8934 	         SCIP_Bool localadded;
8935 	
8936 	         SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8937 	      }
8938 	      break;
8939 	
8940 	   case SCIP_VARSTATUS_FIXED:
8941 	      SCIPerrorMessage("cannot add hole of a fixed variable\n");
8942 	      return SCIP_INVALIDDATA;
8943 	
8944 	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
8945 	      assert(var->data.aggregate.var != NULL);
8946 	
8947 	      if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8948 	      {
8949 	         /* a > 0 -> change lower bound of y */
8950 	         childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8951 	         childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8952 	      }
8953 	      else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8954 	      {
8955 	         childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8956 	         childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8957 	      }
8958 	      else
8959 	      { 
8960 	         SCIPerrorMessage("scalar is zero in aggregation\n");
8961 	         return SCIP_INVALIDDATA;
8962 	      }
8963 	      SCIP_CALL( SCIPvarAddHoleGlobal(var->data.aggregate.var, blkmem, set, stat, eventqueue, 
8964 	            childnewleft, childnewright, added) );
8965 	      break;
8966 	
8967 	   case SCIP_VARSTATUS_MULTAGGR:
8968 	      SCIPerrorMessage("cannot add a hole of a multi-aggregated variable.\n");
8969 	      return SCIP_INVALIDDATA;
8970 	
8971 	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
8972 	      assert(var->negatedvar != NULL);
8973 	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
8974 	      assert(var->negatedvar->negatedvar == var);
8975 	
8976 	      childnewright = -left + var->data.negate.constant;
8977 	      childnewleft = -right + var->data.negate.constant;
8978 	
8979 	      SCIP_CALL( SCIPvarAddHoleGlobal(var->negatedvar, blkmem, set, stat, eventqueue, 
8980 	            childnewleft, childnewright, added) );
8981 	      break;
8982 	
8983 	   default:
8984 	      SCIPerrorMessage("unknown variable status\n");
8985 	      return SCIP_INVALIDDATA;
8986 	   }
8987 	
8988 	   return SCIP_OKAY;
8989 	}
8990 	
8991 	/** performs the current add of domain, changes all parents accordingly */
8992 	static
8993 	SCIP_RETCODE varProcessAddHoleLocal(
8994 	   SCIP_VAR*             var,                /**< problem variable */
8995 	   BMS_BLKMEM*           blkmem,             /**< block memory */
8996 	   SCIP_SET*             set,                /**< global SCIP settings */
8997 	   SCIP_STAT*            stat,               /**< problem statistics */
8998 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
8999 	   SCIP_Real             left,               /**< left bound of open interval in new hole */
9000 	   SCIP_Real             right,              /**< right bound of open interval in new hole */
9001 	   SCIP_Bool*            added               /**< pointer to store whether the hole was added, or NULL */
9002 	   )
9003 	{
9004 	   SCIP_VAR* parentvar;
9005 	   SCIP_Real newlb;
9006 	   SCIP_Real newub;
9007 	   int i;
9008 	
9009 	   assert(var != NULL);
9010 	   assert(added != NULL);
9011 	   assert(blkmem != NULL);
9012 	
9013 	   /* the interval should not be empty */
9014 	   assert(SCIPsetIsLT(set, left, right));
9015 	
9016 	   /* the the interval bound should already be adjusted */
9017 	   assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
9018 	   assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
9019 	
9020 	   /* the the interval should lay between the lower and upper bound */
9021 	   assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
9022 	   assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
9023 	
9024 	   /* add hole to hole list */
9025 	   SCIP_CALL( domAddHole(&var->locdom, blkmem, set, left, right, added) );
9026 	
9027 	   /* check if the hole is redundant */
9028 	   if( !(*added) )
9029 	      return SCIP_OKAY;
9030 	
9031 	   /* current bounds */
9032 	   newlb = var->locdom.lb;
9033 	   newub = var->locdom.ub;
9034 	
9035 	   /* merge domain holes */
9036 	   domMerge(&var->locdom, blkmem, set, &newlb, &newub);
9037 	
9038 	   /* the bound should not be changed */
9039 	   assert(SCIPsetIsEQ(set, newlb, var->locdom.lb));
9040 	   assert(SCIPsetIsEQ(set, newub, var->locdom.ub));
9041 	
9042 	#if 0
9043 	   /* issue bound change event */
9044 	   assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
9045 	   if( var->eventfilter != NULL )
9046 	   {
9047 	      SCIP_CALL( varEventLholeAdded(var, blkmem, set, lp, branchcand, eventqueue, left, right) );
9048 	   }
9049 	#endif
9050 	
9051 	   /* process parent variables */
9052 	   for( i = 0; i < var->nparentvars; ++i )
9053 	   {
9054 	      SCIP_Real parentnewleft;
9055 	      SCIP_Real parentnewright;
9056 	      SCIP_Bool localadded;
9057 	
9058 	      parentvar = var->parentvars[i];
9059 	      assert(parentvar != NULL);
9060 	
9061 	      switch( SCIPvarGetStatus(parentvar) )
9062 	      {
9063 	      case SCIP_VARSTATUS_ORIGINAL:
9064 	         parentnewleft = left;
9065 	         parentnewright = right;
9066 	         break;
9067 	
9068 	      case SCIP_VARSTATUS_COLUMN:
9069 	      case SCIP_VARSTATUS_LOOSE:
9070 	      case SCIP_VARSTATUS_FIXED:
9071 	      case SCIP_VARSTATUS_MULTAGGR:
9072 	         SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
9073 	         return SCIP_INVALIDDATA;
9074 	
9075 	      case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
9076 	         assert(parentvar->data.aggregate.var == var);
9077 	
9078 	         if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
9079 	         {
9080 	            /* a > 0 -> change upper bound of x */
9081 	            parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
9082 	            parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
9083 	         }
9084 	         else
9085 	         {
9086 	            /* a < 0 -> change lower bound of x */
9087 	            assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
9088 	
9089 	            parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
9090 	            parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
9091 	         }
9092 	         break;
9093 	
9094 	      case SCIP_VARSTATUS_NEGATED: /* x = offset - x'  ->  x' = offset - x */
9095 	         assert(parentvar->negatedvar != NULL);
9096 	         assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
9097 	         assert(parentvar->negatedvar->negatedvar == parentvar);
9098 	
9099 	         parentnewright = -left + parentvar->data.negate.constant;
9100 	         parentnewleft = -right + parentvar->data.negate.constant;
9101 	         break;
9102 	
9103 	      default:
9104 	         SCIPerrorMessage("unknown variable status\n");
9105 	         return SCIP_INVALIDDATA;
9106 	      }
9107 	
9108 	      SCIPsetDebugMsg(set, "add local hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
9109 	
9110 	      /* perform hole added for parent variable */
9111 	      assert(blkmem != NULL);
9112 	      assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
9113 	      SCIP_CALL( varProcessAddHoleLocal(parentvar, blkmem, set, stat, eventqueue, 
9114 	            parentnewleft, parentnewright, &localadded) );
9115 	      assert(localadded);
9116 	   }
9117 	
9118 	   return SCIP_OKAY;
9119 	}
9120 	
9121 	/** adds a hole to the variable's current local domain */
9122 	SCIP_RETCODE SCIPvarAddHoleLocal(
9123 	   SCIP_VAR*             var,                /**< problem variable */
9124 	   BMS_BLKMEM*           blkmem,             /**< block memory */
9125 	   SCIP_SET*             set,                /**< global SCIP settings */
9126 	   SCIP_STAT*            stat,               /**< problem statistics */
9127 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue, may be NULL for original variables */
9128 	   SCIP_Real             left,               /**< left bound of open interval in new hole */
9129 	   SCIP_Real             right,              /**< right bound of open interval in new hole */
9130 	   SCIP_Bool*            added               /**< pointer to store whether the hole was added */
9131 	   )
9132 	{
9133 	   SCIP_Real childnewleft;
9134 	   SCIP_Real childnewright;
9135 	
9136 	   assert(var != NULL);
9137 	
9138 	   SCIPsetDebugMsg(set, "adding local hole (%g,%g) to <%s>\n", left, right, var->name);
9139 	
9140 	   assert(set != NULL);
9141 	   assert(var->scip == set->scip);
9142 	   assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
9143 	   assert(blkmem != NULL);
9144 	   assert(added != NULL);
9145 	
9146 	   /* the interval should not be empty */
9147 	   assert(SCIPsetIsLT(set, left, right));
9148 	
9149 	   /* the the interval bound should already be adjusted */
9150 	   assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
9151 	   assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
9152 	
9153 	   /* the the interval should lay between the lower and upper bound */
9154 	   assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
9155 	   assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
9156 	
9157 	   /* change bounds of attached variables */
9158 	   switch( SCIPvarGetStatus(var) )
9159 	   {
9160 	   case SCIP_VARSTATUS_ORIGINAL:
9161 	      if( var->data.original.transvar != NULL )
9162 	      {
9163 	         SCIP_CALL( SCIPvarAddHoleLocal(var->data.original.transvar, blkmem, set, stat, eventqueue, 
9164 	               left, right, added) );
9165 	      }
9166 	      else
9167 	      {
9168 	         assert(set->stage == SCIP_STAGE_PROBLEM);
9169 	         SCIPstatIncrement(stat, set, domchgcount);
9170 	         SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
9171 	      }
9172 	      break;
9173 	
9174 	   case SCIP_VARSTATUS_COLUMN:
9175 	   case SCIP_VARSTATUS_LOOSE:
9176 	      SCIPstatIncrement(stat, set, domchgcount);
9177 	      SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
9178 	      break;
9179 	
9180 	   case SCIP_VARSTATUS_FIXED:
9181 	      SCIPerrorMessage("cannot add domain hole to a fixed variable\n");
9182 	      return SCIP_INVALIDDATA;
9183 	
9184 	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
9185 	      assert(var->data.aggregate.var != NULL);
9186 	
9187 	      if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
9188 	      {
9189 	         /* a > 0 -> change lower bound of y */
9190 	         childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
9191 	         childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
9192 	      }
9193 	      else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
9194 	      {
9195 	         childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
9196 	         childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
9197 	      }
9198 	      else
9199 	      {         
9200 	         SCIPerrorMessage("scalar is zero in aggregation\n");
9201 	         return SCIP_INVALIDDATA;
9202 	      }
9203 	      SCIP_CALL( SCIPvarAddHoleLocal(var->data.aggregate.var, blkmem, set, stat, eventqueue, 
9204 	            childnewleft, childnewright, added) );
9205 	      break;
9206 	
9207 	   case SCIP_VARSTATUS_MULTAGGR:
9208 	      SCIPerrorMessage("cannot add domain hole to a multi-aggregated variable.\n");
9209 	      return SCIP_INVALIDDATA;
9210 	
9211 	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
9212 	      assert(var->negatedvar != NULL);
9213 	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
9214 	      assert(var->negatedvar->negatedvar == var);
9215 	
9216 	      childnewright = -left + var->data.negate.constant;
9217 	      childnewleft = -right + var->data.negate.constant;
9218 	
9219 	      SCIP_CALL( SCIPvarAddHoleLocal(var->negatedvar, blkmem, set, stat, eventqueue, childnewleft, childnewright, added) );
9220 	      break;
9221 	
9222 	   default:
9223 	      SCIPerrorMessage("unknown variable status\n");
9224 	      return SCIP_INVALIDDATA;
9225 	   }
9226 	
9227 	   return SCIP_OKAY;
9228 	}
9229 	
9230 	/** resets the global and local bounds of original variable to their original values */
9231 	SCIP_RETCODE SCIPvarResetBounds(
9232 	   SCIP_VAR*             var,                /**< problem variable */
9233 	   BMS_BLKMEM*           blkmem,             /**< block memory */
9234 	   SCIP_SET*             set,                /**< global SCIP settings */
9235 	   SCIP_STAT*            stat                /**< problem statistics */
9236 	   )
9237 	{
9238 	   assert(var != NULL);
9239 	   assert(set != NULL);
9240 	   assert(var->scip == set->scip);
9241 	   assert(SCIPvarIsOriginal(var));
9242 	   /* resetting of bounds on original variables which have a transformed counterpart easily fails if, e.g.,
9243 	    * the transformed variable has been fixed */ 
9244 	   assert(SCIPvarGetTransVar(var) == NULL);
9245 	
9246 	   /* copy the original bounds back to the global and local bounds */
9247 	   SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.lb) );
9248 	   SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.ub) );
9249 	   SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.lb) );
9250 	   SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.ub) );
9251 	
9252 	   /* free the global and local holelists and duplicate the original ones */
9253 	   /**@todo this has also to be called recursively with methods similar to SCIPvarChgLbGlobal() */
9254 	   holelistFree(&var->glbdom.holelist, blkmem);
9255 	   holelistFree(&var->locdom.holelist, blkmem);
9256 	   SCIP_CALL( holelistDuplicate(&var->glbdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
9257 	   SCIP_CALL( holelistDuplicate(&var->locdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
9258 	
9259 	   return SCIP_OKAY;
9260 	}
9261 	
9262 	/** issues a IMPLADDED event on the given variable */
9263 	static
9264 	SCIP_RETCODE varEventImplAdded(
9265 	   SCIP_VAR*             var,                /**< problem variable to change */
9266 	   BMS_BLKMEM*           blkmem,             /**< block memory */
9267 	   SCIP_SET*             set,                /**< global SCIP settings */
9268 	   SCIP_EVENTQUEUE*      eventqueue          /**< event queue */
9269 	   )
9270 	{
9271 	   SCIP_EVENT* event;
9272 	
9273 	   assert(var != NULL);
9274 	
9275 	   /* issue IMPLADDED event on variable */
9276 	   SCIP_CALL( SCIPeventCreateImplAdded(&event, blkmem, var) );
9277 	   SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
9278 	
9279 	   return SCIP_OKAY;
9280 	}
9281 	
9282 	/** actually performs the addition of a variable bound to the variable's vbound arrays */
9283 	static
9284 	SCIP_RETCODE varAddVbound(
9285 	   SCIP_VAR*             var,                /**< problem variable x in x <= b*z + d  or  x >= b*z + d */
9286 	   BMS_BLKMEM*           blkmem,             /**< block memory */
9287 	   SCIP_SET*             set,                /**< global SCIP settings */
9288 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
9289 	   SCIP_BOUNDTYPE        vbtype,             /**< type of variable bound (LOWER or UPPER) */
9290 	   SCIP_VAR*             vbvar,              /**< variable z    in x <= b*z + d  or  x >= b*z + d */
9291 	   SCIP_Real             vbcoef,             /**< coefficient b in x <= b*z + d  or  x >= b*z + d */
9292 	   SCIP_Real             vbconstant          /**< constant d    in x <= b*z + d  or  x >= b*z + d */
9293 	   )
9294 	{
9295 	   SCIP_Bool added;
9296 	
9297 	   /* It can happen that the variable "var" and the variable "vbvar" are the same variable. For example if a variable
9298 	    * gets aggregated, the variable bounds (vbound) of that variable are copied to the other variable. A variable bound
9299 	    * variable of the aggregated variable might be the same as the one its gets aggregated too.
9300 	    * 
9301 	    * If the variable "var" and the variable "vbvar" are the same, the variable bound which should be added here has to
9302 	    * be redundant. This is the case since an infeasibility should have be detected in the previous methods. As well as
9303 	    * the bounds of the variable which should be also already be tightened in the previous methods. Therefore, the
9304 	    * variable bound can be ignored.
9305 	    *
9306 	    * From the way the the variable bound system is implemented (detecting infeasibility, tighten bounds), the
9307 	    * equivalence of the variables should be checked here.
9308 	    */
9309 	   if( var == vbvar )
9310 	   {
9311 	      /* in this case the variable bound has to be redundant, this means for possible assignments to this variable; this
9312 	       * can be checked via the global bounds of the variable */
9313 	#ifndef NDEBUG
9314 	      SCIP_Real lb;
9315 	      SCIP_Real ub;
9316 	
9317 	      lb = SCIPvarGetLbGlobal(var);
9318 	      ub = SCIPvarGetUbGlobal(var);
9319 	
9320 	      if(vbtype == SCIP_BOUNDTYPE_LOWER)
9321 	      {
9322 	         if( vbcoef > 0.0 )
9323 	         {
9324 	            assert(SCIPsetIsGE(set, lb,  lb * vbcoef + vbconstant) );
9325 	            assert(SCIPsetIsGE(set, ub,  ub * vbcoef + vbconstant) );
9326 	         }
9327 	         else
9328 	         {
9329 	            assert(SCIPsetIsGE(set, lb,  ub * vbcoef + vbconstant) );
9330 	            assert(SCIPsetIsGE(set, ub,  lb * vbcoef + vbconstant) );
9331 	         }
9332 	      }
9333 	      else
9334 	      {
9335 	         assert(vbtype == SCIP_BOUNDTYPE_UPPER);
9336 	         if( vbcoef > 0.0 )
9337 	         {
9338 	            assert(SCIPsetIsLE(set, lb,  lb * vbcoef + vbconstant) );
9339 	            assert(SCIPsetIsLE(set, ub,  ub * vbcoef + vbconstant) );
9340 	         }
9341 	         else
9342 	         {
9343 	            assert(SCIPsetIsLE(set, lb,  ub * vbcoef + vbconstant) );
9344 	            assert(SCIPsetIsLE(set, ub,  lb * vbcoef + vbconstant) );
9345 	         }
9346 	      }
9347 	#endif
9348 	      SCIPsetDebugMsg(set, "redundant variable bound: <%s> %s %g<%s> %+g\n",
9349 	         SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
9350 	
9351 	      return SCIP_OKAY;
9352 	   }
9353 	
9354 	   SCIPsetDebugMsg(set, "adding variable bound: <%s> %s %g<%s> %+g\n",
9355 	      SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
9356 	
9357 	   /* check variable bound on debugging solution */
9358 	   SCIP_CALL( SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant) ); /*lint !e506 !e774*/
9359 	
9360 	   /* perform the addition */
9361 	   if( vbtype == SCIP_BOUNDTYPE_LOWER )
9362 	   {
9363 	      SCIP_CALL( SCIPvboundsAdd(&var->vlbs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9364 	   }
9365 	   else
9366 	   {
9367 	      SCIP_CALL( SCIPvboundsAdd(&var->vubs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9368 	   }
9369 	   var->closestvblpcount = -1;
9370 	
9371 	   if( added )
9372 	   {
9373 	      /* issue IMPLADDED event */
9374 	      SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9375 	   }
9376 	
9377 	   return SCIP_OKAY;
9378 	}
9379 	
9380 	/** checks whether the given implication is redundant or infeasible w.r.t. the implied variables global bounds */
9381 	static
9382 	void checkImplic(
9383 	   SCIP_SET*             set,                /**< global SCIP settings */
9384 	   SCIP_VAR*             implvar,            /**< variable y in implication y <= b or y >= b */
9385 	   SCIP_BOUNDTYPE        impltype,           /**< type       of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9386 	   SCIP_Real             implbound,          /**< bound b    in implication y <= b or y >= b */
9387 	   SCIP_Bool*            redundant,          /**< pointer to store whether the implication is redundant */
9388 	   SCIP_Bool*            infeasible          /**< pointer to store whether the implication is infeasible */
9389 	   )
9390 	{
9391 	   SCIP_Real impllb;
9392 	   SCIP_Real implub;
9393 	
9394 	   assert(redundant != NULL);
9395 	   assert(infeasible != NULL);
9396 	
9397 	   impllb = SCIPvarGetLbGlobal(implvar);
9398 	   implub = SCIPvarGetUbGlobal(implvar);
9399 	   if( impltype == SCIP_BOUNDTYPE_LOWER )
9400 	   {
9401 	      *infeasible = SCIPsetIsFeasGT(set, implbound, implub);
9402 	      *redundant = SCIPsetIsFeasLE(set, implbound, impllb);
9403 	   }
9404 	   else
9405 	   {
9406 	      *infeasible = SCIPsetIsFeasLT(set, implbound, impllb);
9407 	      *redundant = SCIPsetIsFeasGE(set, implbound, implub);
9408 	   }
9409 	}
9410 	
9411 	/** applies the given implication, if it is not redundant */
9412 	static
9413 	SCIP_RETCODE applyImplic(
9414 	   BMS_BLKMEM*           blkmem,             /**< block memory */
9415 	   SCIP_SET*             set,                /**< global SCIP settings */
9416 	   SCIP_STAT*            stat,               /**< problem statistics */
9417 	   SCIP_PROB*            transprob,          /**< transformed problem */
9418 	   SCIP_PROB*            origprob,           /**< original problem */
9419 	   SCIP_TREE*            tree,               /**< branch and bound tree if in solving stage */
9420 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
9421 	   SCIP_LP*              lp,                 /**< current LP data */
9422 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
9423 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
9424 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
9425 	   SCIP_VAR*             implvar,            /**< variable y in implication y <= b or y >= b */
9426 	   SCIP_BOUNDTYPE        impltype,           /**< type       of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9427 	   SCIP_Real             implbound,          /**< bound b    in implication y <= b or y >= b */
9428 	   SCIP_Bool*            infeasible,         /**< pointer to store whether an infeasibility was detected */
9429 	   int*                  nbdchgs             /**< pointer to count the number of performed bound changes, or NULL */
9430 	   )
9431 	{
9432 	   SCIP_Real implub;
9433 	   SCIP_Real impllb;
9434 	
9435 	   assert(infeasible != NULL);
9436 	
9437 	   *infeasible = FALSE;
9438 	
9439 	   implub = SCIPvarGetUbGlobal(implvar);
9440 	   impllb = SCIPvarGetLbGlobal(implvar);
9441 	   if( impltype == SCIP_BOUNDTYPE_LOWER )
9442 	   {
9443 	      if( SCIPsetIsFeasGT(set, implbound, implub) )
9444 	      {
9445 	         /* the implication produces a conflict: the problem is infeasible */
9446 	         *infeasible = TRUE;
9447 	      }
9448 	      else if( SCIPsetIsFeasGT(set, implbound, impllb) )
9449 	      {
9450 	         /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9451 	          * with the local bound, in this case we need to store the bound change as pending bound change
9452 	          */
9453 	         if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9454 	         {
9455 	            assert(tree != NULL);
9456 	            assert(transprob != NULL);
9457 	            assert(SCIPprobIsTransformed(transprob));
9458 	
9459 	            SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9460 	                  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
9461 	         }
9462 	         else
9463 	         {
9464 	            SCIP_CALL( SCIPvarChgLbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9465 	         }
9466 	
9467 	         if( nbdchgs != NULL )
9468 	            (*nbdchgs)++;
9469 	      }
9470 	   }
9471 	   else
9472 	   {
9473 	      if( SCIPsetIsFeasLT(set, implbound, impllb) )
9474 	      {
9475 	         /* the implication produces a conflict: the problem is infeasible */
9476 	         *infeasible = TRUE;
9477 	      }
9478 	      else if( SCIPsetIsFeasLT(set, implbound, implub) )
9479 	      {
9480 	         /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9481 	          * with the local bound, in this case we need to store the bound change as pending bound change
9482 	          */
9483 	         if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9484 	         {
9485 	            assert(tree != NULL);
9486 	            assert(transprob != NULL);
9487 	            assert(SCIPprobIsTransformed(transprob));
9488 	
9489 	            SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9490 	                  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
9491 	         }
9492 	         else
9493 	         {
9494 	            SCIP_CALL( SCIPvarChgUbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9495 	         }
9496 	
9497 	         if( nbdchgs != NULL )
9498 	            (*nbdchgs)++;
9499 	      }
9500 	   }
9501 	
9502 	   return SCIP_OKAY;
9503 	}
9504 	
9505 	/** actually performs the addition of an implication to the variable's implication arrays,
9506 	 *  and adds the corresponding implication or variable bound to the implied variable;
9507 	 *  if the implication is conflicting, the variable is fixed to the opposite value;
9508 	 *  if the variable is already fixed to the given value, the implication is performed immediately;
9509 	 *  if the implication is redundant with respect to the variables' global bounds, it is ignored
9510 	 */
9511 	static
9512 	SCIP_RETCODE varAddImplic(
9513 	   SCIP_VAR*             var,                /**< problem variable */
9514 	   BMS_BLKMEM*           blkmem,             /**< block memory */
9515 	   SCIP_SET*             set,                /**< global SCIP settings */
9516 	   SCIP_STAT*            stat,               /**< problem statistics */
9517 	   SCIP_PROB*            transprob,          /**< transformed problem */
9518 	   SCIP_PROB*            origprob,           /**< original problem */
9519 	   SCIP_TREE*            tree,               /**< branch and bound tree if in solving stage */
9520 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
9521 	   SCIP_LP*              lp,                 /**< current LP data */
9522 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
9523 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
9524 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
9525 	   SCIP_Bool             varfixing,          /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9526 	   SCIP_VAR*             implvar,            /**< variable y in implication y <= b or y >= b */
9527 	   SCIP_BOUNDTYPE        impltype,           /**< type       of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9528 	   SCIP_Real             implbound,          /**< bound b    in implication y <= b or y >= b */
9529 	   SCIP_Bool             isshortcut,         /**< is the implication a shortcut, i.e., added as part of the transitive closure of another implication? */
9530 	   SCIP_Bool*            infeasible,         /**< pointer to store whether an infeasibility was detected */
9531 	   int*                  nbdchgs,            /**< pointer to count the number of performed bound changes, or NULL */
9532 	   SCIP_Bool*            added               /**< pointer to store whether an implication was added */
9533 	   )
9534 	{
9535 	   SCIP_Bool redundant;
9536 	   SCIP_Bool conflict;
9537 	
9538 	   assert(var != NULL);
9539 	   assert(SCIPvarIsActive(var));
9540 	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
9541 	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9542 	   assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9543 	   assert(infeasible != NULL);
9544 	   assert(added != NULL);
9545 	
9546 	   /* check implication on debugging solution */
9547 	   SCIP_CALL( SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound) ); /*lint !e506 !e774*/
9548 	
9549 	   *infeasible = FALSE;
9550 	   *added = FALSE;
9551 	
9552 	   /* check, if the implication is redundant or infeasible */
9553 	   checkImplic(set, implvar, impltype, implbound, &redundant, &conflict);
9554 	   assert(!redundant || !conflict);
9555 	   if( redundant )
9556 	      return SCIP_OKAY;
9557 	
9558 	   if( var == implvar )
9559 	   {
9560 	      /* special cases appear were a bound to a variable implies itself to be outside the bounds:
9561 	       * x == varfixing  =>  x < 0 or x > 1
9562 	       */
9563 	      if( SCIPsetIsLT(set, implbound, 0.0) || SCIPsetIsGT(set, implbound, 1.0) )
9564 	         conflict = TRUE;
9565 	      else
9566 	      {
9567 	         /* variable implies itself: x == varfixing  =>  x == (impltype == SCIP_BOUNDTYPE_LOWER) */
9568 	         assert(SCIPsetIsZero(set, implbound) || SCIPsetIsEQ(set, implbound, 1.0));
9569 	         assert(SCIPsetIsZero(set, implbound) == (impltype == SCIP_BOUNDTYPE_UPPER));
9570 	         assert(SCIPsetIsEQ(set, implbound, 1.0) == (impltype == SCIP_BOUNDTYPE_LOWER));
9571 	         conflict = conflict || ((varfixing == TRUE) == (impltype == SCIP_BOUNDTYPE_UPPER));
9572 	         if( !conflict )
9573 	            return SCIP_OKAY;
9574 	      }
9575 	   }
9576 	
9577 	   /* check, if the variable is already fixed */
9578 	   if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
9579 	   {
9580 	      /* if the variable is fixed to the given value, perform the implication; otherwise, ignore the implication */
9581 	      if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
9582 	      {
9583 	         SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
9584 	               cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
9585 	      }
9586 	      return SCIP_OKAY;
9587 	   }
9588 	
9589 	   assert((impltype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, implbound, SCIPvarGetLbGlobal(implvar)))
9590 	      || (impltype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, implbound, SCIPvarGetUbGlobal(implvar))));
9591 	
9592 	   if( !conflict )
9593 	   {
9594 	      assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9595 	
9596 	      if( SCIPvarIsBinary(implvar) )
9597 	      {
9598 	         SCIP_VAR* vars[2];
9599 	         SCIP_Bool vals[2];
9600 	
9601 	         assert(SCIPsetIsFeasEQ(set, implbound, 1.0) || SCIPsetIsFeasZero(set, implbound));
9602 	         assert((impltype == SCIP_BOUNDTYPE_UPPER) == SCIPsetIsFeasZero(set, implbound));
9603 	
9604 	         vars[0] = var;
9605 	         vars[1] = implvar;
9606 	         vals[0] = varfixing;
9607 	         vals[1] = (impltype == SCIP_BOUNDTYPE_UPPER);
9608 	
9609 	         /* add the clique to the clique table */
9610 	         SCIP_CALL( SCIPcliquetableAdd(cliquetable, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
9611 	               eventqueue, vars, vals, 2, FALSE, &conflict, nbdchgs) );
9612 	
9613 	         if( !conflict )
9614 	            return SCIP_OKAY;
9615 	      }
9616 	      else
9617 	      {
9618 	         /* add implication x == 0/1 -> y <= b / y >= b to the implications list of x */
9619 	         SCIPsetDebugMsg(set, "adding implication: <%s> == %u  ==>  <%s> %s %g\n",
9620 	            SCIPvarGetName(var), varfixing,
9621 	            SCIPvarGetName(implvar), impltype == SCIP_BOUNDTYPE_UPPER ? "<=" : ">=", implbound);
9622 	         SCIP_CALL( SCIPimplicsAdd(&var->implics, blkmem, set, stat, varfixing, implvar, impltype, implbound,
9623 	               isshortcut, &conflict, added) );
9624 	      }
9625 	   }
9626 	   assert(!conflict || !(*added));
9627 	
9628 	   /* on conflict, fix the variable to the opposite value */
9629 	   if( conflict )
9630 	   {
9631 	      SCIPsetDebugMsg(set, " -> implication yields a conflict: fix <%s> == %d\n", SCIPvarGetName(var), !varfixing);
9632 	
9633 	      /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9634 	       * with the local bound, in this case we need to store the bound change as pending bound change
9635 	       */
9636 	      if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9637 	      {
9638 	         assert(tree != NULL);
9639 	         assert(transprob != NULL);
9640 	         assert(SCIPprobIsTransformed(transprob));
9641 	
9642 	         if( varfixing )
9643 	         {
9644 	            SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9645 	                  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
9646 	         }
9647 	         else
9648 	         {
9649 	            SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9650 	                  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
9651 	         }
9652 	      }
9653 	      else
9654 	      {
9655 	         if( varfixing )
9656 	         {
9657 	            SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
9658 	         }
9659 	         else
9660 	         {
9661 	            SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
9662 	         }
9663 	      }
9664 	      if( nbdchgs != NULL )
9665 	         (*nbdchgs)++;
9666 	
9667 	      return SCIP_OKAY;
9668 	   }
9669 	   else if( *added )
9670 	   {
9671 	      /* issue IMPLADDED event */
9672 	      SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9673 	   }
9674 	   else
9675 	   {
9676 	      /* the implication was redundant: the inverse is also redundant */
9677 	      return SCIP_OKAY;
9678 	   }
9679 	
9680 	   assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9681 	
9682 	   /* check, whether implied variable is binary */
9683 	   if( !SCIPvarIsBinary(implvar) )
9684 	   {
9685 	      SCIP_Real lb;
9686 	      SCIP_Real ub;
9687 	
9688 	      /* add inverse variable bound to the variable bounds of y with global bounds y \in [lb,ub]:
9689 	       *   x == 0 -> y <= b  <->  y <= (ub - b)*x + b
9690 	       *   x == 1 -> y <= b  <->  y <= (b - ub)*x + ub
9691 	       *   x == 0 -> y >= b  <->  y >= (lb - b)*x + b
9692 	       *   x == 1 -> y >= b  <->  y >= (b - lb)*x + lb
9693 	       * for numerical reasons, ignore variable bounds with large absolute coefficient
9694 	       */
9695 	      lb = SCIPvarGetLbGlobal(implvar);
9696 	      ub = SCIPvarGetUbGlobal(implvar);
9697 	      if( impltype == SCIP_BOUNDTYPE_UPPER )
9698 	      {
9699 	         if( REALABS(implbound - ub) <= MAXABSVBCOEF ) 
9700 	         {
9701 	            SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, var,
9702 	                  varfixing ? implbound - ub : ub - implbound, varfixing ? ub : implbound) );
9703 	         }
9704 	      }
9705 	      else
9706 	      {
9707 	         if( REALABS(implbound - lb) <= MAXABSVBCOEF ) 
9708 	         {
9709 	            SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, var,
9710 	                  varfixing ? implbound - lb : lb - implbound, varfixing ? lb : implbound) );
9711 	         }
9712 	      }
9713 	   }
9714 	
9715 	   return SCIP_OKAY;
9716 	}
9717 	
9718 	/** adds transitive closure for binary implication x = a -> y = b */
9719 	static
9720 	SCIP_RETCODE varAddTransitiveBinaryClosureImplic(
9721 	   SCIP_VAR*             var,                /**< problem variable */
9722 	   BMS_BLKMEM*           blkmem,             /**< block memory */
9723 	   SCIP_SET*             set,                /**< global SCIP settings */
9724 	   SCIP_STAT*            stat,               /**< problem statistics */
9725 	   SCIP_PROB*            transprob,          /**< transformed problem */
9726 	   SCIP_PROB*            origprob,           /**< original problem */
9727 	   SCIP_TREE*            tree,               /**< branch and bound tree if in solving stage */
9728 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
9729 	   SCIP_LP*              lp,                 /**< current LP data */
9730 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
9731 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
9732 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
9733 	   SCIP_Bool             varfixing,          /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9734 	   SCIP_VAR*             implvar,            /**< variable y in implication y <= b or y >= b */
9735 	   SCIP_Bool             implvarfixing,      /**< fixing b in implication */
9736 	   SCIP_Bool*            infeasible,         /**< pointer to store whether an infeasibility was detected */
9737 	   int*                  nbdchgs             /**< pointer to count the number of performed bound changes, or NULL */
9738 	   )
9739 	{
9740 	   SCIP_VAR** implvars;
9741 	   SCIP_BOUNDTYPE* impltypes;
9742 	   SCIP_Real* implbounds;
9743 	   int nimpls;
9744 	   int i;
9745 	
9746 	   *infeasible = FALSE;
9747 	
9748 	   /* binary variable: implications of implvar */
9749 	   nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9750 	   implvars = SCIPimplicsGetVars(implvar->implics, implvarfixing);
9751 	   impltypes = SCIPimplicsGetTypes(implvar->implics, implvarfixing);
9752 	   implbounds = SCIPimplicsGetBounds(implvar->implics, implvarfixing);
9753 	
9754 	   /* if variable has too many implications, the implication graph may become too dense */
9755 	   i = MIN(nimpls, MAXIMPLSCLOSURE) - 1;
9756 	
9757 	   /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9758 	    * implvars[i] is fixed, s.t. the implication y == varfixing -> z <= b / z >= b is deleted; this affects the
9759 	    * array over which we currently iterate; the only thing that can happen, is that elements of the array are
9760 	    * deleted; in this case, the subsequent elements are moved to the front; if we iterate from back to front, the
9761 	    * only thing that can happen is that we add the same implication twice - this does no harm
9762 	    */
9763 	   while ( i >= 0 && !(*infeasible) )
9764 	   {
9765 	      SCIP_Bool added;
9766 	
9767 	      assert(implvars[i] != implvar);
9768 	
9769 	      /* we have x == varfixing -> y == implvarfixing -> z <= b / z >= b:
9770 	       * add implication x == varfixing -> z <= b / z >= b to the implications list of x 
9771 	       */
9772 	      if( SCIPvarIsActive(implvars[i]) )
9773 	      {
9774 	         SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9775 	               eventqueue, varfixing, implvars[i], impltypes[i], implbounds[i], TRUE, infeasible, nbdchgs, &added) );
9776 	         assert(SCIPimplicsGetNImpls(implvar->implics, implvarfixing) <= nimpls);
9777 	         nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9778 	         i = MIN(i, nimpls); /* some elements from the array could have been removed */
9779 	      }
9780 	      --i;
9781 	   }
9782 	
9783 	   return SCIP_OKAY;
9784 	}
9785 	
9786 	/** adds given implication to the variable's implication list, and adds all implications directly implied by this
9787 	 *  implication to the variable's implication list;
9788 	 *  if the implication is conflicting, the variable is fixed to the opposite value;
9789 	 *  if the variable is already fixed to the given value, the implication is performed immediately;
9790 	 *  if the implication is redundant with respect to the variables' global bounds, it is ignored
9791 	 */
9792 	static
9793 	SCIP_RETCODE varAddTransitiveImplic(
9794 	   SCIP_VAR*             var,                /**< problem variable */
9795 	   BMS_BLKMEM*           blkmem,             /**< block memory */
9796 	   SCIP_SET*             set,                /**< global SCIP settings */
9797 	   SCIP_STAT*            stat,               /**< problem statistics */
9798 	   SCIP_PROB*            transprob,          /**< transformed problem */
9799 	   SCIP_PROB*            origprob,           /**< original problem */
9800 	   SCIP_TREE*            tree,               /**< branch and bound tree if in solving stage */
9801 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
9802 	   SCIP_LP*              lp,                 /**< current LP data */
9803 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
9804 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
9805 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
9806 	   SCIP_Bool             varfixing,          /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9807 	   SCIP_VAR*             implvar,            /**< variable y in implication y <= b or y >= b */
9808 	   SCIP_BOUNDTYPE        impltype,           /**< type       of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9809 	   SCIP_Real             implbound,          /**< bound b    in implication y <= b or y >= b */
9810 	   SCIP_Bool             transitive,         /**< should transitive closure of implication also be added? */
9811 	   SCIP_Bool*            infeasible,         /**< pointer to store whether an infeasibility was detected */
9812 	   int*                  nbdchgs             /**< pointer to count the number of performed bound changes, or NULL */
9813 	   )
9814 	{
9815 	   SCIP_Bool added;
9816 	
9817 	   assert(var != NULL);
9818 	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9819 	   assert(SCIPvarIsActive(var));
9820 	   assert(implvar != NULL);
9821 	   assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9822 	   assert(infeasible != NULL);
9823 	
9824 	   /* add implication x == varfixing -> y <= b / y >= b to the implications list of x */
9825 	   SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9826 	         eventqueue, varfixing, implvar, impltype, implbound, FALSE, infeasible, nbdchgs, &added) );
9827 	
9828 	   if( *infeasible || var == implvar || !transitive || !added )
9829 	      return SCIP_OKAY;
9830 	
9831 	   assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9832 	
9833 	   /* add transitive closure */
9834 	   if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
9835 	   {
9836 	      SCIP_Bool implvarfixing;
9837 	
9838 	      implvarfixing = (impltype == SCIP_BOUNDTYPE_LOWER);
9839 	
9840 	      /* binary variable: implications of implvar */
9841 	      SCIP_CALL( varAddTransitiveBinaryClosureImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9842 	            cliquetable, branchcand, eventqueue, varfixing, implvar, implvarfixing, infeasible, nbdchgs) );
9843 	
9844 	      /* inverse implication */
9845 	      if( !(*infeasible) )
9846 	      {
9847 	         SCIP_CALL( varAddTransitiveBinaryClosureImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9848 	               cliquetable, branchcand, eventqueue, !implvarfixing, var, !varfixing, infeasible, nbdchgs) );
9849 	      }
9850 	   }
9851 	   else
9852 	   {
9853 	      /* non-binary variable: variable lower bounds of implvar */
9854 	      if( impltype == SCIP_BOUNDTYPE_UPPER && implvar->vlbs != NULL )
9855 	      {
9856 	         SCIP_VAR** vlbvars;
9857 	         SCIP_Real* vlbcoefs;
9858 	         SCIP_Real* vlbconstants;
9859 	         int nvlbvars;
9860 	         int i;
9861 	
9862 	         nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9863 	         vlbvars = SCIPvboundsGetVars(implvar->vlbs);
9864 	         vlbcoefs = SCIPvboundsGetCoefs(implvar->vlbs);
9865 	         vlbconstants = SCIPvboundsGetConstants(implvar->vlbs);
9866 	
9867 	         /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9868 	          * vlbvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9869 	          * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9870 	          * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9871 	          * is that we add the same implication twice - this does no harm
9872 	          */
9873 	         i = nvlbvars-1;
9874 	         while ( i >= 0 && !(*infeasible) )
9875 	         {
9876 	            assert(vlbvars[i] != implvar);
9877 	            assert(!SCIPsetIsZero(set, vlbcoefs[i]));
9878 	
9879 	            /* we have x == varfixing -> y <= b and y >= c*z + d:
9880 	             *   c > 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9881 	             *   c < 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9882 	             *
9883 	             * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9884 	             *       SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9885 	             *       aggregation variable (the one which will stay active); 
9886 	             *
9887 	             *       W.l.o.g. we consider the variable upper bounds for now. Let "vubvar" be a variable upper bound of
9888 	             *       the aggregated variable "aggvar"; During that copying of that variable upper bound variable
9889 	             *       "vubvar" the variable lower and upper bounds of this variable "vubvar" are also considered; note
9890 	             *       that the "aggvar" can be a variable lower bound variable of the variable "vubvar"; Due to that
9891 	             *       situation it can happen that we reach that code place where "vlbvars[i] == aggvar". In particular
9892 	             *       the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9893 	             *       but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9894 	             *       have to explicitly check that the active variable has not a variable status
9895 	             *       SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9896 	             */
9897 	            if( SCIPvarIsActive(vlbvars[i]) && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_NEGATED )
9898 	            {
9899 	               SCIP_Real vbimplbound;
9900 	
9901 	               vbimplbound = (implbound - vlbconstants[i])/vlbcoefs[i];
9902 	               if( vlbcoefs[i] >= 0.0 )
9903 	               {
9904 	                  vbimplbound = adjustedUb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9905 	                  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9906 	                        branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9907 	                        infeasible, nbdchgs, &added) );
9908 	               }
9909 	               else
9910 	               {
9911 	                  vbimplbound = adjustedLb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9912 	                  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9913 	                        branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9914 	                        infeasible, nbdchgs, &added) );
9915 	               }
9916 	               nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9917 	               i = MIN(i, nvlbvars); /* some elements from the array could have been removed */
9918 	            }
9919 	            --i;
9920 	         }
9921 	      }
9922 	
9923 	      /* non-binary variable: variable upper bounds of implvar */
9924 	      if( impltype == SCIP_BOUNDTYPE_LOWER && implvar->vubs != NULL )
9925 	      {
9926 	         SCIP_VAR** vubvars;
9927 	         SCIP_Real* vubcoefs;
9928 	         SCIP_Real* vubconstants;
9929 	         int nvubvars;
9930 	         int i;
9931 	
9932 	         nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9933 	         vubvars = SCIPvboundsGetVars(implvar->vubs);
9934 	         vubcoefs = SCIPvboundsGetCoefs(implvar->vubs);
9935 	         vubconstants = SCIPvboundsGetConstants(implvar->vubs);
9936 	
9937 	         /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9938 	          * vubvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9939 	          * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9940 	          * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9941 	          * is that we add the same implication twice - this does no harm
9942 	          */
9943 	         i = nvubvars-1;
9944 	         while ( i >= 0 && !(*infeasible) )
9945 	         {
9946 	            assert(vubvars[i] != implvar);
9947 	            assert(!SCIPsetIsZero(set, vubcoefs[i]));
9948 	
9949 	            /* we have x == varfixing -> y >= b and y <= c*z + d:
9950 	             *   c > 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9951 	             *   c < 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9952 	             *
9953 	             * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9954 	             *       SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9955 	             *       aggregation variable (the one which will stay active); 
9956 	             *
9957 	             *       W.l.o.g. we consider the variable lower bounds for now. Let "vlbvar" be a variable lower bound of
9958 	             *       the aggregated variable "aggvar"; During that copying of that variable lower bound variable
9959 	             *       "vlbvar" the variable lower and upper bounds of this variable "vlbvar" are also considered; note
9960 	             *       that the "aggvar" can be a variable upper bound variable of the variable "vlbvar"; Due to that
9961 	             *       situation it can happen that we reach that code place where "vubvars[i] == aggvar". In particular
9962 	             *       the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9963 	             *       but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9964 	             *       have to explicitly check that the active variable has not a variable status
9965 	             *       SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9966 	             */
9967 	            if( SCIPvarIsActive(vubvars[i]) && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_NEGATED )
9968 	            {
9969 	               SCIP_Real vbimplbound;
9970 	
9971 	               vbimplbound = (implbound - vubconstants[i])/vubcoefs[i];
9972 	               if( vubcoefs[i] >= 0.0 )
9973 	               {
9974 	                  vbimplbound = adjustedLb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9975 	                  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9976 	                        branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9977 	                        infeasible, nbdchgs, &added) );
9978 	               }
9979 	               else
9980 	               {
9981 	                  vbimplbound = adjustedUb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9982 	                  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9983 	                        branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9984 	                        infeasible, nbdchgs, &added) );
9985 	               }
9986 	               nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9987 	               i = MIN(i, nvubvars); /* some elements from the array could have been removed */
9988 	            }
9989 	            --i;
9990 	         }
9991 	      }
9992 	   }
9993 	
9994 	   return SCIP_OKAY;
9995 	}
9996 	
9997 	/** informs variable x about a globally valid variable lower bound x >= b*z + d with integer variable z;
9998 	 *  if z is binary, the corresponding valid implication for z is also added;
9999 	 *  improves the global bounds of the variable and the vlb variable if possible
10000	 */
10001	SCIP_RETCODE SCIPvarAddVlb(
10002	   SCIP_VAR*             var,                /**< problem variable */
10003	   BMS_BLKMEM*           blkmem,             /**< block memory */
10004	   SCIP_SET*             set,                /**< global SCIP settings */
10005	   SCIP_STAT*            stat,               /**< problem statistics */
10006	   SCIP_PROB*            transprob,          /**< transformed problem */
10007	   SCIP_PROB*            origprob,           /**< original problem */
10008	   SCIP_TREE*            tree,               /**< branch and bound tree if in solving stage */
10009	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
10010	   SCIP_LP*              lp,                 /**< current LP data */
10011	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
10012	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
10013	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
10014	   SCIP_VAR*             vlbvar,             /**< variable z    in x >= b*z + d */
10015	   SCIP_Real             vlbcoef,            /**< coefficient b in x >= b*z + d */
10016	   SCIP_Real             vlbconstant,        /**< constant d    in x >= b*z + d */
10017	   SCIP_Bool             transitive,         /**< should transitive closure of implication also be added? */
10018	   SCIP_Bool*            infeasible,         /**< pointer to store whether an infeasibility was detected */
10019	   int*                  nbdchgs             /**< pointer to store the number of performed bound changes, or NULL */
10020	   )
10021	{
10022	   assert(var != NULL);
10023	   assert(set != NULL);
10024	   assert(var->scip == set->scip);
10025	   assert(SCIPvarGetType(vlbvar) != SCIP_VARTYPE_CONTINUOUS);
10026	   assert(infeasible != NULL);
10027	
10028	   SCIPsetDebugMsg(set, "adding variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
10029	
10030	   *infeasible = FALSE;
10031	   if( nbdchgs != NULL )
10032	      *nbdchgs = 0;
10033	
10034	   switch( SCIPvarGetStatus(var) )
10035	   {
10036	   case SCIP_VARSTATUS_ORIGINAL:
10037	      assert(var->data.original.transvar != NULL);
10038	      SCIP_CALL( SCIPvarAddVlb(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10039	            cliquetable, branchcand, eventqueue, vlbvar, vlbcoef, vlbconstant, transitive, infeasible, nbdchgs) );
10040	      break;
10041	
10042	   case SCIP_VARSTATUS_COLUMN:
10043	   case SCIP_VARSTATUS_LOOSE:
10044	   case SCIP_VARSTATUS_FIXED:
10045	      /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
10046	      SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );
10047	      SCIPsetDebugMsg(set, " -> transformed to variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
10048	
10049	      /* if the vlb coefficient is zero, just update the lower bound of the variable */
10050	      if( SCIPsetIsZero(set, vlbcoef) )
10051	      {
10052	         if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetUbGlobal(var)) )
10053	            *infeasible = TRUE;
10054	         else if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetLbGlobal(var)) )
10055	         {
10056	            /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10057	             * with the local bound, in this case we need to store the bound change as pending bound change
10058	             */
10059	            if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10060	            {
10061	               assert(tree != NULL);
10062	               assert(transprob != NULL);
10063	               assert(SCIPprobIsTransformed(transprob));
10064	
10065	               SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10066	                     tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vlbconstant, SCIP_BOUNDTYPE_LOWER, FALSE) );
10067	            }
10068	            else
10069	            {
10070	               SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vlbconstant) );
10071	            }
10072	
10073	            if( nbdchgs != NULL )
10074	               (*nbdchgs)++;
10075	         }
10076	      }
10077	      else if( var == vlbvar )
10078	      {
10079	         /* the variables cancels out, the variable bound constraint is either redundant or proves global infeasibility */
10080	         if( SCIPsetIsEQ(set, vlbcoef, 1.0) )
10081	         {
10082	            if( SCIPsetIsPositive(set, vlbconstant) )
10083	               *infeasible = TRUE;
10084	            return SCIP_OKAY;
10085	         }
10086	         else
10087	         {
10088	            SCIP_Real lb = SCIPvarGetLbGlobal(var);
10089	            SCIP_Real ub = SCIPvarGetUbGlobal(var);
10090	
10091	            /* the variable bound constraint defines a new upper bound */
10092	            if( SCIPsetIsGT(set, vlbcoef, 1.0) )
10093	            {
10094	               SCIP_Real newub = vlbconstant / (1.0 - vlbcoef);
10095	
10096	               if( SCIPsetIsFeasLT(set, newub, lb) )
10097	               {
10098	                  *infeasible = TRUE;
10099	                  return SCIP_OKAY;
10100	               }
10101	               else if( SCIPsetIsFeasLT(set, newub, ub) )
10102	               {
10103	                  /* bound might be adjusted due to integrality condition */
10104	                  newub = adjustedUb(set, SCIPvarGetType(var), newub);
10105	
10106	                  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10107	                   * with the local bound, in this case we need to store the bound change as pending bound change
10108	                   */
10109	                  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10110	                  {
10111	                     assert(tree != NULL);
10112	                     assert(transprob != NULL);
10113	                     assert(SCIPprobIsTransformed(transprob));
10114	
10115	                     SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10116	                           tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10117	                  }
10118	                  else
10119	                  {
10120	                     SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
10121	                  }
10122	
10123	                  if( nbdchgs != NULL )
10124	                     (*nbdchgs)++;
10125	               }
10126	            }
10127	            /* the variable bound constraint defines a new lower bound */
10128	            else
10129	            {
10130	               SCIP_Real newlb;
10131	
10132	               assert(SCIPsetIsLT(set, vlbcoef, 1.0));
10133	
10134	               newlb = vlbconstant / (1.0 - vlbcoef);
10135	
10136	               if( SCIPsetIsFeasGT(set, newlb, ub) )
10137	               {
10138	                  *infeasible = TRUE;
10139	                  return SCIP_OKAY;
10140	               }
10141	               else if( SCIPsetIsFeasGT(set, newlb, lb) )
10142	               {
10143	                  /* bound might be adjusted due to integrality condition */
10144	                  newlb = adjustedLb(set, SCIPvarGetType(var), newlb);
10145	
10146	                  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10147	                   * with the local bound, in this case we need to store the bound change as pending bound change
10148	                   */
10149	                  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10150	                  {
10151	                     assert(tree != NULL);
10152	                     assert(transprob != NULL);
10153	                     assert(SCIPprobIsTransformed(transprob));
10154	
10155	                     SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10156	                           tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10157	                  }
10158	                  else
10159	                  {
10160	                     SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
10161	                  }
10162	
10163	                  if( nbdchgs != NULL )
10164	                     (*nbdchgs)++;
10165	               }
10166	            }
10167	         }
10168	      }
10169	      else if( SCIPvarIsActive(vlbvar) )
10170	      {
10171	         SCIP_Real xlb;
10172	         SCIP_Real xub;
10173	         SCIP_Real zlb;
10174	         SCIP_Real zub;
10175	         SCIP_Real minvlb;
10176	         SCIP_Real maxvlb;
10177	
10178	         assert(SCIPvarGetStatus(vlbvar) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(vlbvar) == SCIP_VARSTATUS_COLUMN);
10179	         assert(vlbcoef != 0.0);
10180	
10181	         minvlb = -SCIPsetInfinity(set);
10182	         maxvlb = SCIPsetInfinity(set);
10183	
10184	         xlb = SCIPvarGetLbGlobal(var);
10185	         xub = SCIPvarGetUbGlobal(var);
10186	         zlb = SCIPvarGetLbGlobal(vlbvar);
10187	         zub = SCIPvarGetUbGlobal(vlbvar);
10188	
10189	         /* improve global bounds of vlb variable, and calculate minimal and maximal value of variable bound */
10190	         if( vlbcoef >= 0.0 )
10191	         {
10192	            SCIP_Real newzub;
10193	
10194	            if( !SCIPsetIsInfinity(set, xub) )
10195	            {
10196	               /* x >= b*z + d  ->  z <= (x-d)/b */
10197	               newzub = (xub - vlbconstant)/vlbcoef;
10198	
10199	               /* return if the new bound is less than -infinity */
10200	               if( SCIPsetIsInfinity(set, REALABS(newzub)) )
10201	                  return SCIP_OKAY;
10202	
10203	               if( SCIPsetIsFeasLT(set, newzub, zlb) )
10204	               {
10205	                  *infeasible = TRUE;
10206	                  return SCIP_OKAY;
10207	               }
10208	               if( SCIPsetIsFeasLT(set, newzub, zub) )
10209	               {
10210	                  /* bound might be adjusted due to integrality condition */
10211	                  newzub = adjustedUb(set, SCIPvarGetType(vlbvar), newzub);
10212	
10213	                  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10214	                   * with the local bound, in this case we need to store the bound change as pending bound change
10215	                   */
10216	                  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10217	                  {
10218	                     assert(tree != NULL);
10219	                     assert(transprob != NULL);
10220	                     assert(SCIPprobIsTransformed(transprob));
10221	
10222	                     SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10223	                           tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10224	                  }
10225	                  else
10226	                  {
10227	                     SCIP_CALL( SCIPvarChgUbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10228	                  }
10229	                  zub = newzub;
10230	
10231	                  if( nbdchgs != NULL )
10232	                     (*nbdchgs)++;
10233	               }
10234	               maxvlb = vlbcoef * zub + vlbconstant;
10235	               if( !SCIPsetIsInfinity(set, -zlb) )
10236	                  minvlb = vlbcoef * zlb + vlbconstant;
10237	            }
10238	            else
10239	            {
10240	               if( !SCIPsetIsInfinity(set, zub) )
10241	                  maxvlb = vlbcoef * zub + vlbconstant;
10242	               if( !SCIPsetIsInfinity(set, -zlb) )
10243	                  minvlb = vlbcoef * zlb + vlbconstant;
10244	            }
10245	         }
10246	         else
10247	         {
10248	            SCIP_Real newzlb;
10249	
10250	            if( !SCIPsetIsInfinity(set, xub) )
10251	            {
10252	               /* x >= b*z + d  ->  z >= (x-d)/b */
10253	               newzlb = (xub - vlbconstant)/vlbcoef;
10254	
10255	               /* return if the new bound is larger than infinity */
10256	               if( SCIPsetIsInfinity(set, REALABS(newzlb)) )
10257	                  return SCIP_OKAY;
10258	
10259	               if( SCIPsetIsFeasGT(set, newzlb, zub) )
10260	               {
10261	                  *infeasible = TRUE;
10262	                  return SCIP_OKAY;
10263	               }
10264	               if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10265	               {
10266	                  /* bound might be adjusted due to integrality condition */
10267	                  newzlb = adjustedLb(set, SCIPvarGetType(vlbvar), newzlb);
10268	
10269	                  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10270	                   * with the local bound, in this case we need to store the bound change as pending bound change
10271	                   */
10272	                  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10273	                  {
10274	                     assert(tree != NULL);
10275	                     assert(transprob != NULL);
10276	                     assert(SCIPprobIsTransformed(transprob));
10277	
10278	                     SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10279	                           tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10280	                  }
10281	                  else
10282	                  {
10283	                     SCIP_CALL( SCIPvarChgLbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10284	                  }
10285	                  zlb = newzlb;
10286	
10287	                  if( nbdchgs != NULL )
10288	                     (*nbdchgs)++;
10289	               }
10290	               maxvlb = vlbcoef * zlb + vlbconstant;
10291	               if( !SCIPsetIsInfinity(set, zub) )
10292	                  minvlb = vlbcoef * zub + vlbconstant;
10293	            }
10294	            else
10295	            {
10296	               if( !SCIPsetIsInfinity(set, -zlb) )
10297	                  maxvlb = vlbcoef * zlb + vlbconstant;
10298	               if( !SCIPsetIsInfinity(set, zub) )
10299	                  minvlb = vlbcoef * zub + vlbconstant;
10300	            }
10301	         }
10302	         if( maxvlb < minvlb )
10303	            maxvlb = minvlb;
10304	
10305	         /* adjust bounds due to integrality of variable */
10306	         minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
10307	         maxvlb = adjustedLb(set, SCIPvarGetType(var), maxvlb);
10308	
10309	         /* check bounds for feasibility */
10310	         if( SCIPsetIsFeasGT(set, minvlb, xub) || (var == vlbvar && SCIPsetIsEQ(set, vlbcoef, 1.0) && SCIPsetIsFeasPositive(set, vlbconstant))  )
10311	         {
10312	            *infeasible = TRUE;
10313	            return SCIP_OKAY;
10314	         }
10315	         /* improve global lower bound of variable */
10316	         if( SCIPsetIsFeasGT(set, minvlb, xlb) )
10317	         {
10318	            /* bound might be adjusted due to integrality condition */
10319	            minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
10320	
10321	            /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10322	             * with the local bound, in this case we need to store the bound change as pending bound change
10323	             */
10324	            if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10325	            {
10326	               assert(tree != NULL);
10327	               assert(transprob != NULL);
10328	               assert(SCIPprobIsTransformed(transprob));
10329	
10330	               SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10331	                     tree, reopt, lp, branchcand, eventqueue, cliquetable, var, minvlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10332	            }
10333	            else
10334	            {
10335	               SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, minvlb) );
10336	            }
10337	            xlb = minvlb;
10338	
10339	            if( nbdchgs != NULL )
10340	               (*nbdchgs)++;
10341	         }
10342	         minvlb = xlb;
10343	
10344	         /* improve variable bound for binary z by moving the variable's global bound to the vlb constant */
10345	         if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
10346	         {
10347	            /* b > 0: x >= (maxvlb - minvlb) * z + minvlb
10348	             * b < 0: x >= (minvlb - maxvlb) * z + maxvlb
10349	             */
10350	
10351	            assert(!SCIPsetIsInfinity(set, maxvlb) && !SCIPsetIsInfinity(set, -minvlb));
10352	
10353	            if( vlbcoef >= 0.0 )
10354	            {
10355	               vlbcoef = maxvlb - minvlb;
10356	               vlbconstant = minvlb;
10357	            }
10358	            else
10359	            {
10360	               vlbcoef = minvlb - maxvlb;
10361	               vlbconstant = maxvlb;
10362	            }
10363	         }
10364	
10365	         /* add variable bound to the variable bounds list */
10366	         if( SCIPsetIsFeasGT(set, maxvlb, xlb) )
10367	         {
10368	            assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10369	            assert(!SCIPsetIsZero(set, vlbcoef));
10370	
10371	            /* if one of the variables is binary, add the corresponding implication to the variable's implication
10372	             * list, thereby also adding the variable bound (or implication) to the other variable
10373	             */
10374	            if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
10375	            {
10376	               /* add corresponding implication:
10377	                *   b > 0, x >= b*z + d  <->  z == 1 -> x >= b+d
10378	                *   b < 0, x >= b*z + d  <->  z == 0 -> x >= d
10379	                */
10380	               SCIP_CALL( varAddTransitiveImplic(vlbvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10381	                     cliquetable, branchcand, eventqueue, (vlbcoef >= 0.0), var, SCIP_BOUNDTYPE_LOWER, maxvlb, transitive,
10382	                     infeasible, nbdchgs) );
10383	            }
10384	            else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10385	            {
10386	               /* add corresponding implication:
10387	                *   b > 0, x >= b*z + d  <->  x == 0 -> z <= -d/b
10388	                *   b < 0, x >= b*z + d  <->  x == 0 -> z >= -d/b
10389	                */
10390	               SCIP_Real implbound;
10391	               implbound = -vlbconstant/vlbcoef;
10392	
10393	               /* tighten the implication bound if the variable is integer */
10394	               if( SCIPvarIsIntegral(vlbvar) )
10395	               {
10396	                  if( vlbcoef >= 0 )
10397	                     implbound = SCIPsetFloor(set, implbound);
10398	                  else
10399	                     implbound = SCIPsetCeil(set, implbound);
10400	               }
10401	               SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10402	                     cliquetable, branchcand, eventqueue, FALSE, vlbvar, (vlbcoef >= 0.0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER),
10403	                     implbound, transitive, infeasible, nbdchgs) );
10404	            }
10405	            else
10406	            {
10407	               SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, vlbvar, vlbcoef, vlbconstant) );
10408	            }
10409	         }
10410	      }
10411	      break;
10412	
10413	   case SCIP_VARSTATUS_AGGREGATED:
10414	      /* x = a*y + c:  x >= b*z + d  <=>  a*y + c >= b*z + d  <=>  y >= b/a * z + (d-c)/a, if a > 0
10415	       *                                                           y <= b/a * z + (d-c)/a, if a < 0
10416	       */
10417	      assert(var->data.aggregate.var != NULL);
10418	      if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10419	      {
10420	         /* a > 0 -> add variable lower bound */
10421	         SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10422	               cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10423	               (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10424	      }
10425	      else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10426	      {
10427	         /* a < 0 -> add variable upper bound */
10428	         SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10429	               cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10430	               (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10431	      }
10432	      else
10433	      {
10434	         SCIPerrorMessage("scalar is zero in aggregation\n");
10435	         return SCIP_INVALIDDATA;
10436	      }
10437	      break;
10438	
10439	   case SCIP_VARSTATUS_MULTAGGR:
10440	      /* nothing to do here */
10441	      break;
10442	
10443	   case SCIP_VARSTATUS_NEGATED:
10444	      /* x = offset - x':  x >= b*z + d  <=>  offset - x' >= b*z + d  <=>  x' <= -b*z + (offset-d) */
10445	      assert(var->negatedvar != NULL);
10446	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
10447	      assert(var->negatedvar->negatedvar == var);
10448	      SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10449	            branchcand, eventqueue, vlbvar, -vlbcoef, var->data.negate.constant - vlbconstant, transitive, infeasible,
10450	            nbdchgs) );
10451	      break;
10452	
10453	   default:
10454	      SCIPerrorMessage("unknown variable status\n");
10455	      return SCIP_INVALIDDATA;
10456	   }
10457	
10458	   return SCIP_OKAY;
10459	}
10460	
10461	/** informs variable x about a globally valid variable upper bound x <= b*z + d with integer variable z;
10462	 *  if z is binary, the corresponding valid implication for z is also added;
10463	 *  updates the global bounds of the variable and the vub variable correspondingly
10464	 */
10465	SCIP_RETCODE SCIPvarAddVub(
10466	   SCIP_VAR*             var,                /**< problem variable */
10467	   BMS_BLKMEM*           blkmem,             /**< block memory */
10468	   SCIP_SET*             set,                /**< global SCIP settings */
10469	   SCIP_STAT*            stat,               /**< problem statistics */
10470	   SCIP_PROB*            transprob,          /**< transformed problem */
10471	   SCIP_PROB*            origprob,           /**< original problem */
10472	   SCIP_TREE*            tree,               /**< branch and bound tree if in solving stage */
10473	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
10474	   SCIP_LP*              lp,                 /**< current LP data */
10475	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
10476	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
10477	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
10478	   SCIP_VAR*             vubvar,             /**< variable z    in x <= b*z + d */
10479	   SCIP_Real             vubcoef,            /**< coefficient b in x <= b*z + d */
10480	   SCIP_Real             vubconstant,        /**< constant d    in x <= b*z + d */
10481	   SCIP_Bool             transitive,         /**< should transitive closure of implication also be added? */
10482	   SCIP_Bool*            infeasible,         /**< pointer to store whether an infeasibility was detected */
10483	   int*                  nbdchgs             /**< pointer to store the number of performed bound changes, or NULL */
10484	   )
10485	{
10486	   assert(var != NULL);
10487	   assert(set != NULL);
10488	   assert(var->scip == set->scip);
10489	   assert(SCIPvarGetType(vubvar) != SCIP_VARTYPE_CONTINUOUS);
10490	   assert(infeasible != NULL);
10491	
10492	   SCIPsetDebugMsg(set, "adding variable upper bound <%s> <= %g<%s> + %g\n", SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10493	
10494	   *infeasible = FALSE;
10495	   if( nbdchgs != NULL )
10496	      *nbdchgs = 0;
10497	
10498	   switch( SCIPvarGetStatus(var) )
10499	   {
10500	   case SCIP_VARSTATUS_ORIGINAL:
10501	      assert(var->data.original.transvar != NULL);
10502	      SCIP_CALL( SCIPvarAddVub(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10503	            cliquetable, branchcand, eventqueue, vubvar, vubcoef, vubconstant, transitive, infeasible, nbdchgs) );
10504	      break;
10505	
10506	   case SCIP_VARSTATUS_COLUMN:
10507	   case SCIP_VARSTATUS_LOOSE:
10508	   case SCIP_VARSTATUS_FIXED:
10509	      /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
10510	      SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );
10511	      SCIPsetDebugMsg(set, " -> transformed to variable upper bound <%s> <= %g<%s> + %g\n",
10512	         SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10513	
10514	      /* if the vub coefficient is zero, just update the upper bound of the variable */
10515	      if( SCIPsetIsZero(set, vubcoef) )
10516	      {
10517	         if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetLbGlobal(var)) )
10518	            *infeasible = TRUE;
10519	         else if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetUbGlobal(var)) )
10520	         {
10521	            /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10522	             * with the local bound, in this case we need to store the bound change as pending bound change
10523	             */
10524	            if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10525	            {
10526	               assert(tree != NULL);
10527	               assert(transprob != NULL);
10528	               assert(SCIPprobIsTransformed(transprob));
10529	
10530	               SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10531	                     tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vubconstant, SCIP_BOUNDTYPE_UPPER, FALSE) );
10532	            }
10533	            else
10534	            {
10535	               SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vubconstant) );
10536	            }
10537	
10538	            if( nbdchgs != NULL )
10539	               (*nbdchgs)++;
10540	         }
10541	      }
10542	      else if( var == vubvar )
10543	      {
10544	         /* the variables cancels out, the variable bound constraint is either redundant or proves global infeasibility */
10545	         if( SCIPsetIsEQ(set, vubcoef, 1.0) )
10546	         {
10547	            if( SCIPsetIsNegative(set, vubconstant) )
10548	               *infeasible = TRUE;
10549	            return SCIP_OKAY;
10550	         }
10551	         else
10552	         {
10553	            SCIP_Real lb = SCIPvarGetLbGlobal(var);
10554	            SCIP_Real ub = SCIPvarGetUbGlobal(var);
10555	
10556	            /* the variable bound constraint defines a new lower bound */
10557	            if( SCIPsetIsGT(set, vubcoef, 1.0) )
10558	            {
10559	               SCIP_Real newlb = vubconstant / (1.0 - vubcoef);
10560	
10561	               if( SCIPsetIsFeasGT(set, newlb, ub) )
10562	               {
10563	                  *infeasible = TRUE;
10564	                  return SCIP_OKAY;
10565	               }
10566	               else if( SCIPsetIsFeasGT(set, newlb, lb) )
10567	               {
10568	                  /* bound might be adjusted due to integrality condition */
10569	                  newlb = adjustedLb(set, SCIPvarGetType(var), newlb);
10570	
10571	                  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10572	                   * with the local bound, in this case we need to store the bound change as pending bound change
10573	                   */
10574	                  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10575	                  {
10576	                     assert(tree != NULL);
10577	                     assert(transprob != NULL);
10578	                     assert(SCIPprobIsTransformed(transprob));
10579	
10580	                     SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10581	                           tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10582	                  }
10583	                  else
10584	                  {
10585	                     SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
10586	                  }
10587	
10588	                  if( nbdchgs != NULL )
10589	                     (*nbdchgs)++;
10590	               }
10591	            }
10592	            /* the variable bound constraint defines a new upper bound */
10593	            else
10594	            {
10595	               SCIP_Real newub;
10596	
10597	               assert(SCIPsetIsLT(set, vubcoef, 1.0));
10598	
10599	               newub = vubconstant / (1.0 - vubcoef);
10600	
10601	               if( SCIPsetIsFeasLT(set, newub, lb) )
10602	               {
10603	                  *infeasible = TRUE;
10604	                  return SCIP_OKAY;
10605	               }
10606	               else if( SCIPsetIsFeasLT(set, newub, ub) )
10607	               {
10608	                  /* bound might be adjusted due to integrality condition */
10609	                  newub = adjustedUb(set, SCIPvarGetType(var), newub);
10610	
10611	                  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10612	                   * with the local bound, in this case we need to store the bound change as pending bound change
10613	                   */
10614	                  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10615	                  {
10616	                     assert(tree != NULL);
10617	                     assert(transprob != NULL);
10618	                     assert(SCIPprobIsTransformed(transprob));
10619	
10620	                     SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10621	                           tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10622	                  }
10623	                  else
10624	                  {
10625	                     SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
10626	                  }
10627	
10628	                  if( nbdchgs != NULL )
10629	                     (*nbdchgs)++;
10630	               }
10631	            }
10632	         }
10633	      }
10634	      else if( SCIPvarIsActive(vubvar) )
10635	      {
10636	         SCIP_Real xlb;
10637	         SCIP_Real xub;
10638	         SCIP_Real zlb;
10639	         SCIP_Real zub;
10640	         SCIP_Real minvub;
10641	         SCIP_Real maxvub;
10642	
10643	         assert(SCIPvarGetStatus(vubvar) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(vubvar) == SCIP_VARSTATUS_COLUMN);
10644	         assert(vubcoef != 0.0);
10645	
10646	         minvub = -SCIPsetInfinity(set);
10647	         maxvub = SCIPsetInfinity(set);
10648	
10649	         xlb = SCIPvarGetLbGlobal(var);
10650	         xub = SCIPvarGetUbGlobal(var);
10651	         zlb = SCIPvarGetLbGlobal(vubvar);
10652	         zub = SCIPvarGetUbGlobal(vubvar);
10653	
10654	         /* improve global bounds of vub variable, and calculate minimal and maximal value of variable bound */
10655	         if( vubcoef >= 0.0 )
10656	         {
10657	            SCIP_Real newzlb;
10658	
10659	            if( !SCIPsetIsInfinity(set, -xlb) )
10660	            {
10661	               /* x <= b*z + d  ->  z >= (x-d)/b */
10662	               newzlb = (xlb - vubconstant)/vubcoef;
10663	               if( SCIPsetIsFeasGT(set, newzlb, zub) )
10664	               {
10665	                  *infeasible = TRUE;
10666	                  return SCIP_OKAY;
10667	               }
10668	               if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10669	               {
10670	                  /* bound might be adjusted due to integrality condition */
10671	                  newzlb = adjustedLb(set, SCIPvarGetType(vubvar), newzlb);
10672	
10673	                  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10674	                   * with the local bound, in this case we need to store the bound change as pending bound change
10675	                   */
10676	                  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10677	                  {
10678	                     assert(tree != NULL);
10679	                     assert(transprob != NULL);
10680	                     assert(SCIPprobIsTransformed(transprob));
10681	
10682	                     SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10683	                           tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10684	                  }
10685	                  else
10686	                  {
10687	                     SCIP_CALL( SCIPvarChgLbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10688	                  }
10689	                  zlb = newzlb;
10690	
10691	                  if( nbdchgs != NULL )
10692	                     (*nbdchgs)++;
10693	               }
10694	               minvub = vubcoef * zlb + vubconstant;
10695	               if( !SCIPsetIsInfinity(set, zub) )
10696	                  maxvub = vubcoef * zub + vubconstant;
10697	            }
10698	            else
10699	            {
10700	               if( !SCIPsetIsInfinity(set, zub) )
10701	                  maxvub = vubcoef * zub + vubconstant;
10702	               if( !SCIPsetIsInfinity(set, -zlb) )
10703	                  minvub = vubcoef * zlb + vubconstant;
10704	            }
10705	         }
10706	         else
10707	         {
10708	            SCIP_Real newzub;
10709	
10710	            if( !SCIPsetIsInfinity(set, -xlb) )
10711	            {
10712	               /* x <= b*z + d  ->  z <= (x-d)/b */
10713	               newzub = (xlb - vubconstant)/vubcoef;
10714	               if( SCIPsetIsFeasLT(set, newzub, zlb) )
10715	               {
10716	                  *infeasible = TRUE;
10717	                  return SCIP_OKAY;
10718	               }
10719	               if( SCIPsetIsFeasLT(set, newzub, zub) )
10720	               {
10721	                  /* bound might be adjusted due to integrality condition */
10722	                  newzub = adjustedUb(set, SCIPvarGetType(vubvar), newzub);
10723	
10724	                  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10725	                   * with the local bound, in this case we need to store the bound change as pending bound change
10726	                   */
10727	                  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10728	                  {
10729	                     assert(tree != NULL);
10730	                     assert(transprob != NULL);
10731	                     assert(SCIPprobIsTransformed(transprob));
10732	
10733	                     SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10734	                           tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10735	                  }
10736	                  else
10737	                  {
10738	                     SCIP_CALL( SCIPvarChgUbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10739	                  }
10740	                  zub = newzub;
10741	
10742	                  if( nbdchgs != NULL )
10743	                     (*nbdchgs)++;
10744	               }
10745	               minvub = vubcoef * zub + vubconstant;
10746	               if( !SCIPsetIsInfinity(set, -zlb) )
10747	                  maxvub = vubcoef * zlb + vubconstant;
10748	            }
10749	            else
10750	            {
10751	               if( !SCIPsetIsInfinity(set, zub) )
10752	                  minvub = vubcoef * zub + vubconstant;
10753	               if( !SCIPsetIsInfinity(set, -zlb) )
10754	                  maxvub = vubcoef * zlb + vubconstant;
10755	            }
10756	         }
10757	         if( minvub > maxvub )
10758	            minvub = maxvub;
10759	
10760	         /* adjust bounds due to integrality of vub variable */
10761	         minvub = adjustedUb(set, SCIPvarGetType(var), minvub);
10762	         maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10763	
10764	         /* check bounds for feasibility */
10765	         if( SCIPsetIsFeasLT(set, maxvub, xlb) || (var == vubvar && SCIPsetIsEQ(set, vubcoef, 1.0) && SCIPsetIsFeasNegative(set, vubconstant))  )
10766	         {
10767	            *infeasible = TRUE;
10768	            return SCIP_OKAY;
10769	         }
10770	
10771	         /* improve global upper bound of variable */
10772	         if( SCIPsetIsFeasLT(set, maxvub, xub) )
10773	         {
10774	            /* bound might be adjusted due to integrality condition */
10775	            maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10776	
10777	            /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10778	             * with the local bound, in this case we need to store the bound change as pending bound change
10779	             */
10780	            if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10781	            {
10782	               assert(tree != NULL);
10783	               assert(transprob != NULL);
10784	               assert(SCIPprobIsTransformed(transprob));
10785	
10786	               SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10787	                     tree, reopt, lp, branchcand, eventqueue, cliquetable, var, maxvub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10788	            }
10789	            else
10790	            {
10791	               SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, maxvub) );
10792	            }
10793	            xub = maxvub;
10794	
10795	            if( nbdchgs != NULL )
10796	               (*nbdchgs)++;
10797	         }
10798	         maxvub = xub;
10799	
10800	         /* improve variable bound for binary z by moving the variable's global bound to the vub constant */
10801	         if( SCIPvarIsBinary(vubvar) )
10802	         {
10803	            /* b > 0: x <= (maxvub - minvub) * z + minvub
10804	             * b < 0: x <= (minvub - maxvub) * z + maxvub
10805	             */
10806	
10807	            assert(!SCIPsetIsInfinity(set, maxvub) && !SCIPsetIsInfinity(set, -minvub));
10808	
10809	            if( vubcoef >= 0.0 )
10810	            {
10811	               vubcoef = maxvub - minvub;
10812	               vubconstant = minvub;
10813	            }
10814	            else
10815	            {
10816	               vubcoef = minvub - maxvub;
10817	               vubconstant = maxvub;
10818	            }
10819	         }
10820	
10821	         /* add variable bound to the variable bounds list */
10822	         if( SCIPsetIsFeasLT(set, minvub, xub) )
10823	         {
10824	            assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10825	            assert(!SCIPsetIsZero(set, vubcoef));
10826	
10827	            /* if one of the variables is binary, add the corresponding implication to the variable's implication
10828	             * list, thereby also adding the variable bound (or implication) to the other variable
10829	             */
10830	            if( SCIPvarGetType(vubvar) == SCIP_VARTYPE_BINARY )
10831	            {
10832	               /* add corresponding implication:
10833	                *   b > 0, x <= b*z + d  <->  z == 0 -> x <= d
10834	                *   b < 0, x <= b*z + d  <->  z == 1 -> x <= b+d
10835	                */
10836	               SCIP_CALL( varAddTransitiveImplic(vubvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10837	                     cliquetable, branchcand, eventqueue, (vubcoef < 0.0), var, SCIP_BOUNDTYPE_UPPER, minvub, transitive,
10838	                     infeasible, nbdchgs) );
10839	            }
10840	            else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10841	            {
10842	               /* add corresponding implication:
10843	                *   b > 0, x <= b*z + d  <->  x == 1 -> z >= (1-d)/b
10844	                *   b < 0, x <= b*z + d  <->  x == 1 -> z <= (1-d)/b
10845	                */
10846	               SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10847	                     cliquetable, branchcand, eventqueue, TRUE, vubvar, (vubcoef >= 0.0 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER),
10848	                     (1.0-vubconstant)/vubcoef, transitive, infeasible, nbdchgs) );
10849	            }
10850	            else
10851	            {
10852	               SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, vubvar, vubcoef, vubconstant) );
10853	            }
10854	         }
10855	      }
10856	      break;
10857	
10858	   case SCIP_VARSTATUS_AGGREGATED:
10859	      /* x = a*y + c:  x <= b*z + d  <=>  a*y + c <= b*z + d  <=>  y <= b/a * z + (d-c)/a, if a > 0
10860	       *                                                           y >= b/a * z + (d-c)/a, if a < 0
10861	       */
10862	      assert(var->data.aggregate.var != NULL);
10863	      if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10864	      {
10865	         /* a > 0 -> add variable upper bound */
10866	         SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10867	               cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10868	               (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10869	      }
10870	      else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10871	      {
10872	         /* a < 0 -> add variable lower bound */
10873	         SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10874	               cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10875	               (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10876	      }
10877	      else
10878	      {
10879	         SCIPerrorMessage("scalar is zero in aggregation\n");
10880	         return SCIP_INVALIDDATA;
10881	      }
10882	      break;
10883	
10884	   case SCIP_VARSTATUS_MULTAGGR:
10885	      /* nothing to do here */
10886	      break;
10887	
10888	   case SCIP_VARSTATUS_NEGATED:
10889	      /* x = offset - x':  x <= b*z + d  <=>  offset - x' <= b*z + d  <=>  x' >= -b*z + (offset-d) */
10890	      assert(var->negatedvar != NULL);
10891	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
10892	      assert(var->negatedvar->negatedvar == var);
10893	      SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10894	            branchcand, eventqueue, vubvar, -vubcoef, var->data.negate.constant - vubconstant, transitive, infeasible,
10895	            nbdchgs) );
10896	      break;
10897	
10898	   default:
10899	      SCIPerrorMessage("unknown variable status\n");
10900	      return SCIP_INVALIDDATA;
10901	   }
10902	
10903	   return SCIP_OKAY;
10904	}
10905	
10906	/** informs binary variable x about a globally valid implication:  x == 0 or x == 1  ==>  y <= b  or  y >= b;
10907	 *  also adds the corresponding implication or variable bound to the implied variable;
10908	 *  if the implication is conflicting, the variable is fixed to the opposite value;
10909	 *  if the variable is already fixed to the given value, the implication is performed immediately;
10910	 *  if the implication is redundant with respect to the variables' global bounds, it is ignored
10911	 */
10912	SCIP_RETCODE SCIPvarAddImplic(
10913	   SCIP_VAR*             var,                /**< problem variable  */
10914	   BMS_BLKMEM*           blkmem,             /**< block memory */
10915	   SCIP_SET*             set,                /**< global SCIP settings */
10916	   SCIP_STAT*            stat,               /**< problem statistics */
10917	   SCIP_PROB*            transprob,          /**< transformed problem */
10918	   SCIP_PROB*            origprob,           /**< original problem */
10919	   SCIP_TREE*            tree,               /**< branch and bound tree if in solving stage */
10920	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
10921	   SCIP_LP*              lp,                 /**< current LP data */
10922	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
10923	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
10924	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
10925	   SCIP_Bool             varfixing,          /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
10926	   SCIP_VAR*             implvar,            /**< variable y in implication y <= b or y >= b */
10927	   SCIP_BOUNDTYPE        impltype,           /**< type       of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
10928	   SCIP_Real             implbound,          /**< bound b    in implication y <= b or y >= b */
10929	   SCIP_Bool             transitive,         /**< should transitive closure of implication also be added? */
10930	   SCIP_Bool*            infeasible,         /**< pointer to store whether an infeasibility was detected */
10931	   int*                  nbdchgs             /**< pointer to store the number of performed bound changes, or NULL */
10932	   )
10933	{
10934	   assert(var != NULL);
10935	   assert(set != NULL);
10936	   assert(var->scip == set->scip);
10937	   assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
10938	   assert(infeasible != NULL);
10939	
10940	   *infeasible = FALSE;
10941	   if( nbdchgs != NULL )
10942	      *nbdchgs = 0;
10943	
10944	   switch( SCIPvarGetStatus(var) )
10945	   {
10946	   case SCIP_VARSTATUS_ORIGINAL:
10947	      assert(var->data.original.transvar != NULL);
10948	      SCIP_CALL( SCIPvarAddImplic(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10949	            cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10950	            nbdchgs) );
10951	      break;
10952	
10953	   case SCIP_VARSTATUS_COLUMN:
10954	   case SCIP_VARSTATUS_LOOSE:
10955	      /* if the variable is fixed (although it has no FIXED status), and varfixing corresponds to the fixed value of
10956	       * the variable, the implication can be applied directly;
10957	       * otherwise, add implication to the implications list (and add inverse of implication to the implied variable)
10958	       */
10959	      if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
10960	      {
10961	         if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10962	         {
10963	            SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10964	                  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10965	         }
10966	      }
10967	      else
10968	      {
10969	         SCIP_CALL( SCIPvarGetProbvarBound(&implvar, &implbound, &impltype) );
10970	         SCIPvarAdjustBd(implvar, set, impltype, &implbound);
10971	         if( SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED )
10972	         {
10973	            SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10974	                  branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10975	         }
10976	      }
10977	      break;
10978	
10979	   case SCIP_VARSTATUS_FIXED:
10980	      /* if varfixing corresponds to the fixed value of the variable, the implication can be applied directly */
10981	      if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10982	      {
10983	         SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10984	               cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10985	      }
10986	      break;
10987	
10988	   case SCIP_VARSTATUS_AGGREGATED:
10989	      /* implication added for x == 1:
10990	       *   x == 1 && x =  1*z + 0  ==>  y <= b or y >= b    <==>    z >= 1  ==>  y <= b or y >= b 
10991	       *   x == 1 && x = -1*z + 1  ==>  y <= b or y >= b    <==>    z <= 0  ==>  y <= b or y >= b
10992	       * implication added for x == 0:
10993	       *   x == 0 && x =  1*z + 0  ==>  y <= b or y >= b    <==>    z <= 0  ==>  y <= b or y >= b
10994	       *   x == 0 && x = -1*z + 1  ==>  y <= b or y >= b    <==>    z >= 1  ==>  y <= b or y >= b
10995	       *
10996	       * use only binary variables z 
10997	       */
10998	      assert(var->data.aggregate.var != NULL);
10999	      if( SCIPvarIsBinary(var->data.aggregate.var) )
11000	      {
11001	         assert( (SCIPsetIsEQ(set, var->data.aggregate.scalar, 1.0) && SCIPsetIsZero(set, var->data.aggregate.constant))
11002	            || (SCIPsetIsEQ(set, var->data.aggregate.scalar, -1.0) && SCIPsetIsEQ(set, var->data.aggregate.constant, 1.0)) );
11003	
11004	         if( var->data.aggregate.scalar > 0 )
11005	         {
11006	            SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11007	                  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
11008	                  nbdchgs) );
11009	         }
11010	         else
11011	         {
11012	            SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11013	                  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible,
11014	                  nbdchgs) );
11015	         }
11016	      }
11017	      break;
11018	
11019	   case SCIP_VARSTATUS_MULTAGGR:
11020	      /* nothing to do here */
11021	      break;
11022	
11023	   case SCIP_VARSTATUS_NEGATED:
11024	      /* implication added for x == 1:
11025	       *   x == 1 && x = -1*z + 1  ==>  y <= b or y >= b    <==>    z <= 0  ==>  y <= b or y >= b
11026	       * implication added for x == 0:
11027	       *   x == 0 && x = -1*z + 1  ==>  y <= b or y >= b    <==>    z >= 1  ==>  y <= b or y >= b
11028	       */
11029	      assert(var->negatedvar != NULL);
11030	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
11031	      assert(var->negatedvar->negatedvar == var);
11032	      assert(SCIPvarIsBinary(var->negatedvar));
11033	
11034	      if( SCIPvarGetType(var->negatedvar) == SCIP_VARTYPE_BINARY )
11035	      {
11036	         SCIP_CALL( SCIPvarAddImplic(var->negatedvar, blkmem, set, stat,  transprob, origprob, tree, reopt, lp,
11037	               cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
11038	      }
11039	      /* in case one both variables are not of binary type we have to add the implication as variable bounds */
11040	      else
11041	      {
11042	         /* if the implied variable is of binary type exchange the variables */
11043	         if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
11044	         {
11045	            SCIP_CALL( SCIPvarAddImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11046	                  branchcand, eventqueue, (impltype == SCIP_BOUNDTYPE_UPPER) ? TRUE : FALSE, var->negatedvar,
11047	                  varfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER, varfixing ? 1.0 : 0.0, transitive,
11048	                  infeasible, nbdchgs) );
11049	         }
11050	         else
11051	         {
11052	            /* both variables are not of binary type but are implicit binary; in that case we can only add this
11053	             * implication as variable bounds
11054	             */
11055	
11056	            /* add variable lower bound on the negation of var */
11057	            if( varfixing )
11058	            {
11059	               /* (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
11060	                * as variable lower bound
11061	                */
11062	               SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11063	                     cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : -1.0,
11064	                     (impltype == SCIP_BOUNDTYPE_UPPER) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
11065	            }
11066	            else
11067	            {
11068	               /* (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
11069	                * as variable upper bound
11070	                */
11071	               SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11072	                     cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? -1.0 : 1.0,
11073	                     (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : 0.0, transitive, infeasible, nbdchgs) );
11074	            }
11075	
11076	            /* add variable bound on implvar */
11077	            if( impltype == SCIP_BOUNDTYPE_UPPER )
11078	            {
11079	               /* (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
11080	                * as variable upper bound
11081	                */
11082	               SCIP_CALL( SCIPvarAddVub(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11083	                     branchcand, eventqueue, var->negatedvar, (varfixing) ? 1.0 : -1.0,
11084	                     (varfixing) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
11085	            }
11086	            else
11087	            {
11088	               /* (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
11089	                * as variable upper bound
11090	                */
11091	               SCIP_CALL( SCIPvarAddVlb(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11092	                     branchcand, eventqueue, var->negatedvar, (varfixing) ? -1.0 : 1.0, (varfixing) ? 1.0 : 0.0,
11093	                     transitive, infeasible, nbdchgs) );
11094	            }
11095	         }
11096	      }
11097	      break;
11098	
11099	   default:
11100	      SCIPerrorMessage("unknown variable status\n");
11101	      return SCIP_INVALIDDATA;
11102	   }
11103	
11104	   return SCIP_OKAY;
11105	}
11106	
11107	/** returns whether there is an implication x == varfixing -> y <= b or y >= b in the implication graph;
11108	 *  implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
11109	 *  both variables must be active, variable x must be binary
11110	 */
11111	SCIP_Bool SCIPvarHasImplic(
11112	   SCIP_VAR*             var,                /**< problem variable x */
11113	   SCIP_Bool             varfixing,          /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
11114	   SCIP_VAR*             implvar,            /**< variable y to search for */
11115	   SCIP_BOUNDTYPE        impltype            /**< type of implication y <=/>= b to search for */
11116	   )
11117	{
11118	   assert(var != NULL);
11119	   assert(implvar != NULL);
11120	   assert(SCIPvarIsActive(var));
11121	   assert(SCIPvarIsActive(implvar));
11122	   assert(SCIPvarIsBinary(var));
11123	
11124	   return var->implics != NULL && SCIPimplicsContainsImpl(var->implics, varfixing, implvar, impltype);
11125	}
11126	
11127	/** returns whether there is an implication x == varfixing -> y == implvarfixing in the implication graph;
11128	 *  implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
11129	 *  both variables must be active binary variables
11130	 */
11131	SCIP_Bool SCIPvarHasBinaryImplic(
11132	   SCIP_VAR*             var,                /**< problem variable x */
11133	   SCIP_Bool             varfixing,          /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
11134	   SCIP_VAR*             implvar,            /**< variable y to search for */
11135	   SCIP_Bool             implvarfixing       /**< value of the implied variable to search for */
11136	   )
11137	{
11138	   assert(SCIPvarIsBinary(implvar));
11139	
11140	   return SCIPvarHasImplic(var, varfixing, implvar, implvarfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER);
11141	}
11142	
11143	/** gets the values of b in implications x == varfixing -> y <= b or y >= b in the implication graph;
11144	 *  the values are set to SCIP_INVALID if there is no implied bound
11145	 */
11146	void SCIPvarGetImplicVarBounds(
11147	   SCIP_VAR*             var,                /**< problem variable x */
11148	   SCIP_Bool             varfixing,          /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
11149	   SCIP_VAR*             implvar,            /**< variable y to search for */
11150	   SCIP_Real*            lb,                 /**< buffer to store the value of the implied lower bound */
11151	   SCIP_Real*            ub                  /**< buffer to store the value of the implied upper bound */
11152	   )
11153	{
11154	   int lowerpos;
11155	   int upperpos;
11156	   SCIP_Real* bounds;
11157	
11158	   assert(lb != NULL);
11159	   assert(ub != NULL);
11160	
11161	   *lb = SCIP_INVALID;
11162	   *ub = SCIP_INVALID;
11163	
11164	   if( var->implics == NULL )
11165	      return;
11166	
11167	   SCIPimplicsGetVarImplicPoss(var->implics, varfixing, implvar, &lowerpos, &upperpos);
11168	   bounds = SCIPvarGetImplBounds(var, varfixing);
11169	
11170	   if( bounds == NULL )
11171	      return;
11172	
11173	   if( lowerpos >= 0 )
11174	      *lb = bounds[lowerpos];
11175	
11176	   if( upperpos >= 0 )
11177	      *ub = bounds[upperpos];
11178	}
11179	
11180	
11181	/** fixes the bounds of a binary variable to the given value, counting bound changes and detecting infeasibility */
11182	SCIP_RETCODE SCIPvarFixBinary(
11183	   SCIP_VAR*             var,                /**< problem variable */
11184	   BMS_BLKMEM*           blkmem,             /**< block memory */
11185	   SCIP_SET*             set,                /**< global SCIP settings */
11186	   SCIP_STAT*            stat,               /**< problem statistics */
11187	   SCIP_PROB*            transprob,          /**< transformed problem */
11188	   SCIP_PROB*            origprob,           /**< original problem */
11189	   SCIP_TREE*            tree,               /**< branch and bound tree if in solving stage */
11190	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
11191	   SCIP_LP*              lp,                 /**< current LP data */
11192	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
11193	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
11194	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
11195	   SCIP_Bool             value,              /**< value to fix variable to */
11196	   SCIP_Bool*            infeasible,         /**< pointer to store whether an infeasibility was detected */
11197	   int*                  nbdchgs             /**< pointer to count the number of performed bound changes, or NULL */
11198	   )
11199	{
11200	   assert(var != NULL);
11201	   assert(set != NULL);
11202	   assert(var->scip == set->scip);
11203	   assert(infeasible != NULL);
11204	
11205	   *infeasible = FALSE;
11206	
11207	   if( value == FALSE )
11208	   {
11209	      if( var->glbdom.lb > 0.5 )
11210	         *infeasible = TRUE;
11211	      else if( var->glbdom.ub > 0.5 )
11212	      {
11213	         /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
11214	          * with the local bound, in this case we need to store the bound change as pending bound change
11215	          */
11216	         if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
11217	         {
11218	            assert(tree != NULL);
11219	            assert(transprob != NULL);
11220	            assert(SCIPprobIsTransformed(transprob));
11221	
11222	            SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
11223	                  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
11224	         }
11225	         else
11226	         {
11227	            SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
11228	         }
11229	
11230	         if( nbdchgs != NULL )
11231	            (*nbdchgs)++;
11232	      }
11233	   }
11234	   else
11235	   {
11236	      if( var->glbdom.ub < 0.5 )
11237	         *infeasible = TRUE;
11238	      else if( var->glbdom.lb < 0.5 )
11239	      {
11240	         /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
11241	          * with the local bound, in this case we need to store the bound change as pending bound change
11242	          */
11243	         if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
11244	         {
11245	            assert(tree != NULL);
11246	            assert(transprob != NULL);
11247	            assert(SCIPprobIsTransformed(transprob));
11248	
11249	            SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
11250	                  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
11251	         }
11252	         else
11253	         {
11254	            SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
11255	         }
11256	
11257	         if( nbdchgs != NULL )
11258	            (*nbdchgs)++;
11259	      }
11260	   }
11261	
11262	   return SCIP_OKAY;
11263	}
11264	
11265	/** adds the variable to the given clique and updates the list of cliques the binary variable is member of;
11266	 *  if the variable now appears twice in the clique with the same value, it is fixed to the opposite value;
11267	 *  if the variable now appears twice in the clique with opposite values, all other variables are fixed to
11268	 *  the opposite of the value they take in the clique
11269	 */
11270	SCIP_RETCODE SCIPvarAddClique(
11271	   SCIP_VAR*             var,                /**< problem variable  */
11272	   BMS_BLKMEM*           blkmem,             /**< block memory */
11273	   SCIP_SET*             set,                /**< global SCIP settings */
11274	   SCIP_STAT*            stat,               /**< problem statistics */
11275	   SCIP_PROB*            transprob,          /**< transformed problem */
11276	   SCIP_PROB*            origprob,           /**< original problem */
11277	   SCIP_TREE*            tree,               /**< branch and bound tree if in solving stage */
11278	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
11279	   SCIP_LP*              lp,                 /**< current LP data */
11280	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
11281	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
11282	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
11283	   SCIP_Bool             value,              /**< value of the variable in the clique */
11284	   SCIP_CLIQUE*          clique,             /**< clique the variable should be added to */
11285	   SCIP_Bool*            infeasible,         /**< pointer to store whether an infeasibility was detected */
11286	   int*                  nbdchgs             /**< pointer to count the number of performed bound changes, or NULL */
11287	   )
11288	{
11289	   assert(var != NULL);
11290	   assert(set != NULL);
11291	   assert(var->scip == set->scip);
11292	   assert(SCIPvarIsBinary(var));
11293	   assert(infeasible != NULL);
11294	
11295	   *infeasible = FALSE;
11296	
11297	   /* get corresponding active problem variable */
11298	   SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
11299	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
11300	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
11301	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED
11302	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
11303	   assert(SCIPvarIsBinary(var));
11304	
11305	   /* only column and loose variables may be member of a clique */
11306	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE )
11307	   {
11308	      SCIP_Bool doubleentry;
11309	      SCIP_Bool oppositeentry;
11310	
11311	      /* add variable to clique */
11312	      SCIP_CALL( SCIPcliqueAddVar(clique, blkmem, set, var, value, &doubleentry, &oppositeentry) );
11313	
11314	      /* add clique to variable's clique list */
11315	      SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
11316	
11317	      /* check consistency of cliquelist */
11318	      SCIPcliquelistCheck(var->cliquelist, var);
11319	
11320	      /* if the variable now appears twice with the same value in the clique, it can be fixed to the opposite value */
11321	      if( doubleentry )
11322	      {
11323	         SCIP_CALL( SCIPvarFixBinary(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
11324	               eventqueue, cliquetable, !value, infeasible, nbdchgs) );
11325	      }
11326	
11327	      /* if the variable appears with both values in the clique, all other variables of the clique can be fixed
11328	       * to the opposite of the value they take in the clique
11329	       */
11330	      if( oppositeentry )
11331	      {
11332	         SCIP_VAR** vars;
11333	         SCIP_Bool* values;
11334	         int nvars;
11335	         int i;
11336	
11337	         nvars = SCIPcliqueGetNVars(clique);
11338	         vars = SCIPcliqueGetVars(clique);
11339	         values = SCIPcliqueGetValues(clique);
11340	         for( i = 0; i < nvars && !(*infeasible); ++i )
11341	         {
11342	            if( vars[i] == var )
11343	               continue;
11344	
11345	            SCIP_CALL( SCIPvarFixBinary(vars[i], blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
11346	                  eventqueue, cliquetable, !values[i], infeasible, nbdchgs) );
11347	         }
11348	      }
11349	   }
11350	
11351	   return SCIP_OKAY;
11352	}
11353	
11354	/** adds a filled clique to the cliquelists of all corresponding variables */
11355	SCIP_RETCODE SCIPvarsAddClique(
11356	   SCIP_VAR**            vars,               /**< problem variables */
11357	   SCIP_Bool*            values,             /**< values of the variables in the clique */
11358	   int                   nvars,              /**< number of problem variables */
11359	   BMS_BLKMEM*           blkmem,             /**< block memory */
11360	   SCIP_SET*             set,                /**< global SCIP settings */
11361	   SCIP_CLIQUE*          clique              /**< clique that contains all given variables and values */
11362	   )
11363	{
11364	   SCIP_VAR* var;
11365	   int v;
11366	
11367	   assert(vars != NULL);
11368	   assert(values != NULL);
11369	   assert(nvars > 0);
11370	   assert(set != NULL);
11371	   assert(blkmem != NULL);
11372	   assert(clique != NULL);
11373	
11374	   for( v = nvars - 1; v >= 0; --v )
11375	   {
11376	      var = vars[v];
11377	      assert(SCIPvarIsBinary(var));
11378	      assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
11379	
11380	      /* add clique to variable's clique list */
11381	      SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, values[v], clique) );
11382	
11383	      /* check consistency of cliquelist */
11384	      SCIPcliquelistCheck(var->cliquelist, var);
11385	   }
11386	
11387	   return SCIP_OKAY;
11388	}
11389	
11390	/** adds a clique to the list of cliques of the given binary variable, but does not change the clique
11391	 *  itself
11392	 */
11393	SCIP_RETCODE SCIPvarAddCliqueToList(
11394	   SCIP_VAR*             var,                /**< problem variable  */
11395	   BMS_BLKMEM*           blkmem,             /**< block memory */
11396	   SCIP_SET*             set,                /**< global SCIP settings */
11397	   SCIP_Bool             value,              /**< value of the variable in the clique */
11398	   SCIP_CLIQUE*          clique              /**< clique that should be removed from the variable's clique list */
11399	   )
11400	{
11401	   assert(var != NULL);
11402	   assert(SCIPvarIsBinary(var));
11403	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
11404	
11405	   /* add clique to variable's clique list */
11406	   SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
11407	
11408	   return SCIP_OKAY;
11409	}
11410	
11411	
11412	/** deletes a clique from the list of cliques the binary variable is member of, but does not change the clique
11413	 *  itself
11414	 */
11415	SCIP_RETCODE SCIPvarDelCliqueFromList(
11416	   SCIP_VAR*             var,                /**< problem variable  */
11417	   BMS_BLKMEM*           blkmem,             /**< block memory */
11418	   SCIP_Bool             value,              /**< value of the variable in the clique */
11419	   SCIP_CLIQUE*          clique              /**< clique that should be removed from the variable's clique list */
11420	   )
11421	{
11422	   assert(var != NULL);
11423	   assert(SCIPvarIsBinary(var));
11424	
11425	   /* delete clique from variable's clique list */
11426	   SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
11427	
11428	   return SCIP_OKAY;
11429	}
11430	
11431	/** deletes the variable from the given clique and updates the list of cliques the binary variable is member of */
11432	SCIP_RETCODE SCIPvarDelClique(
11433	   SCIP_VAR*             var,                /**< problem variable  */
11434	   BMS_BLKMEM*           blkmem,             /**< block memory */
11435	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
11436	   SCIP_Bool             value,              /**< value of the variable in the clique */
11437	   SCIP_CLIQUE*          clique              /**< clique the variable should be removed from */
11438	   )
11439	{
11440	   assert(var != NULL);
11441	   assert(SCIPvarIsBinary(var));
11442	
11443	   /* get corresponding active problem variable */
11444	   SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
11445	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
11446	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
11447	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED
11448	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
11449	   assert(SCIPvarIsBinary(var));
11450	
11451	   /* only column and loose variables may be member of a clique */
11452	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE )
11453	   {
11454	      /* delete clique from variable's clique list */
11455	      SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
11456	
11457	      /* delete variable from clique */
11458	      SCIPcliqueDelVar(clique, cliquetable, var, value);
11459	
11460	      /* check consistency of cliquelist */
11461	      SCIPcliquelistCheck(var->cliquelist, var);
11462	   }
11463	
11464	   return SCIP_OKAY;
11465	}
11466	
11467	/** returns whether there is a clique that contains both given variable/value pairs;
11468	 *  the variables must be active binary variables;
11469	 *  if regardimplics is FALSE, only the cliques in the clique table are looked at;
11470	 *  if regardimplics is TRUE, both the cliques and the implications of the implication graph are regarded
11471	 *
11472	 *  @note a variable with it's negated variable are NOT! in a clique
11473	 *  @note a variable with itself are in a clique
11474	 */
11475	SCIP_Bool SCIPvarsHaveCommonClique(
11476	   SCIP_VAR*             var1,               /**< first variable */
11477	   SCIP_Bool             value1,             /**< value of first variable */
11478	   SCIP_VAR*             var2,               /**< second variable */
11479	   SCIP_Bool             value2,             /**< value of second variable */
11480	   SCIP_Bool             regardimplics       /**< should the implication graph also be searched for a clique? */
11481	   )
11482	{
11483	   assert(var1 != NULL);
11484	   assert(var2 != NULL);
11485	   assert(SCIPvarIsActive(var1));
11486	   assert(SCIPvarIsActive(var2));
11487	   assert(SCIPvarIsBinary(var1));
11488	   assert(SCIPvarIsBinary(var2));
11489	
11490	   return (SCIPcliquelistsHaveCommonClique(var1->cliquelist, value1, var2->cliquelist, value2)
11491	      || (regardimplics && SCIPvarHasImplic(var1, value1, var2, value2 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER)));
11492	}
11493	
11494	/** actually changes the branch factor of the variable and of all parent variables */
11495	static
11496	SCIP_RETCODE varProcessChgBranchFactor(
11497	   SCIP_VAR*             var,                /**< problem variable */
11498	   SCIP_SET*             set,                /**< global SCIP settings */
11499	   SCIP_Real             branchfactor        /**< factor to weigh variable's branching score with */
11500	   )
11501	{
11502	   SCIP_VAR* parentvar;
11503	   SCIP_Real eps;
11504	   int i;
11505	
11506	   assert(var != NULL);
11507	   assert(set != NULL);
11508	   assert(var->scip == set->scip);
11509	
11510	   /* only use positive values */
11511	   eps = SCIPsetEpsilon(set);
11512	   branchfactor = MAX(branchfactor, eps);
11513	
11514	   SCIPsetDebugMsg(set, "process changing branch factor of <%s> from %f to %f\n", var->name, var->branchfactor, branchfactor);
11515	
11516	   if( SCIPsetIsEQ(set, branchfactor, var->branchfactor) )
11517	      return SCIP_OKAY;
11518	
11519	   /* change the branch factor */
11520	   var->branchfactor = branchfactor;
11521	
11522	   /* process parent variables */
11523	   for( i = 0; i < var->nparentvars; ++i )
11524	   {
11525	      parentvar = var->parentvars[i];
11526	      assert(parentvar != NULL);
11527	
11528	      switch( SCIPvarGetStatus(parentvar) )
11529	      {
11530	      case SCIP_VARSTATUS_ORIGINAL:
11531	         /* do not change priorities across the border between transformed and original problem */
11532	         break;
11533	
11534	      case SCIP_VARSTATUS_COLUMN:
11535	      case SCIP_VARSTATUS_LOOSE:
11536	      case SCIP_VARSTATUS_FIXED:
11537	      case SCIP_VARSTATUS_MULTAGGR:
11538	         SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11539	         SCIPABORT();
11540	         return SCIP_INVALIDDATA; /*lint !e527*/
11541	
11542	      case SCIP_VARSTATUS_AGGREGATED:
11543	      case SCIP_VARSTATUS_NEGATED:
11544	         SCIP_CALL( varProcessChgBranchFactor(parentvar, set, branchfactor) );
11545	         break;
11546	
11547	      default:
11548	         SCIPerrorMessage("unknown variable status\n");
11549	         SCIPABORT();
11550	         return SCIP_ERROR; /*lint !e527*/
11551	      }
11552	   }
11553	
11554	   return SCIP_OKAY;
11555	}
11556	
11557	/** sets the branch factor of the variable; this value can be used in the branching methods to scale the score
11558	 *  values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
11559	 */
11560	SCIP_RETCODE SCIPvarChgBranchFactor(
11561	   SCIP_VAR*             var,                /**< problem variable */
11562	   SCIP_SET*             set,                /**< global SCIP settings */
11563	   SCIP_Real             branchfactor        /**< factor to weigh variable's branching score with */
11564	   )
11565	{
11566	   int v;
11567	
11568	   assert(var != NULL);
11569	   assert(set != NULL);
11570	   assert(var->scip == set->scip);
11571	   assert(branchfactor >= 0.0);
11572	
11573	   SCIPdebugMessage("changing branch factor of <%s> from %g to %g\n", var->name, var->branchfactor, branchfactor);
11574	
11575	   if( SCIPsetIsEQ(set, var->branchfactor, branchfactor) )
11576	      return SCIP_OKAY;
11577	
11578	   /* change priorities of attached variables */
11579	   switch( SCIPvarGetStatus(var) )
11580	   {
11581	   case SCIP_VARSTATUS_ORIGINAL:
11582	      if( var->data.original.transvar != NULL )
11583	      {
11584	         SCIP_CALL( SCIPvarChgBranchFactor(var->data.original.transvar, set, branchfactor) );
11585	      }
11586	      else
11587	      {
11588	         assert(set->stage == SCIP_STAGE_PROBLEM);
11589	         var->branchfactor = branchfactor;
11590	      }
11591	      break;
11592	
11593	   case SCIP_VARSTATUS_COLUMN:
11594	   case SCIP_VARSTATUS_LOOSE:
11595	   case SCIP_VARSTATUS_FIXED:
11596	      SCIP_CALL( varProcessChgBranchFactor(var, set, branchfactor) );
11597	      break;
11598	
11599	   case SCIP_VARSTATUS_AGGREGATED:
11600	      assert(!var->donotaggr);
11601	      assert(var->data.aggregate.var != NULL);
11602	      SCIP_CALL( SCIPvarChgBranchFactor(var->data.aggregate.var, set, branchfactor) );
11603	      break;
11604	
11605	   case SCIP_VARSTATUS_MULTAGGR:
11606	      assert(!var->donotmultaggr);
11607	      for( v = 0; v < var->data.multaggr.nvars; ++v )
11608	      {
11609	         SCIP_CALL( SCIPvarChgBranchFactor(var->data.multaggr.vars[v], set, branchfactor) );
11610	      }
11611	      break;
11612	
11613	   case SCIP_VARSTATUS_NEGATED:
11614	      assert(var->negatedvar != NULL);
11615	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
11616	      assert(var->negatedvar->negatedvar == var);
11617	      SCIP_CALL( SCIPvarChgBranchFactor(var->negatedvar, set, branchfactor) );
11618	      break;
11619	
11620	   default:
11621	      SCIPerrorMessage("unknown variable status\n");
11622	      SCIPABORT();
11623	      return SCIP_ERROR; /*lint !e527*/
11624	   }
11625	
11626	   return SCIP_OKAY;
11627	}
11628	
11629	/** actually changes the branch priority of the variable and of all parent variables */
11630	static
11631	SCIP_RETCODE varProcessChgBranchPriority(
11632	   SCIP_VAR*             var,                /**< problem variable */
11633	   int                   branchpriority      /**< branching priority of the variable */
11634	   )
11635	{
11636	   SCIP_VAR* parentvar;
11637	   int i;
11638	
11639	   assert(var != NULL);
11640	
11641	   SCIPdebugMessage("process changing branch priority of <%s> from %d to %d\n", 
11642	      var->name, var->branchpriority, branchpriority);
11643	
11644	   if( branchpriority == var->branchpriority )
11645	      return SCIP_OKAY;
11646	
11647	   /* change the branch priority */
11648	   var->branchpriority = branchpriority;
11649	
11650	   /* process parent variables */
11651	   for( i = 0; i < var->nparentvars; ++i )
11652	   {
11653	      parentvar = var->parentvars[i];
11654	      assert(parentvar != NULL);
11655	
11656	      switch( SCIPvarGetStatus(parentvar) )
11657	      {
11658	      case SCIP_VARSTATUS_ORIGINAL:
11659	         /* do not change priorities across the border between transformed and original problem */
11660	         break;
11661	
11662	      case SCIP_VARSTATUS_COLUMN:
11663	      case SCIP_VARSTATUS_LOOSE:
11664	      case SCIP_VARSTATUS_FIXED:
11665	      case SCIP_VARSTATUS_MULTAGGR:
11666	         SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11667	         SCIPABORT();
11668	         return SCIP_INVALIDDATA; /*lint !e527*/
11669	
11670	      case SCIP_VARSTATUS_AGGREGATED:
11671	      case SCIP_VARSTATUS_NEGATED:
11672	         SCIP_CALL( varProcessChgBranchPriority(parentvar, branchpriority) );
11673	         break;
11674	
11675	      default:
11676	         SCIPerrorMessage("unknown variable status\n");
11677	         return SCIP_ERROR;
11678	      }
11679	   }
11680	
11681	   return SCIP_OKAY;
11682	}
11683	
11684	/** sets the branch priority of the variable; variables with higher branch priority are always preferred to variables
11685	 *  with lower priority in selection of branching variable
11686	 */
11687	SCIP_RETCODE SCIPvarChgBranchPriority(
11688	   SCIP_VAR*             var,                /**< problem variable */
11689	   int                   branchpriority      /**< branching priority of the variable */
11690	   )
11691	{
11692	   int v;
11693	
11694	   assert(var != NULL);
11695	
11696	   SCIPdebugMessage("changing branch priority of <%s> from %d to %d\n", var->name, var->branchpriority, branchpriority);
11697	
11698	   if( var->branchpriority == branchpriority )
11699	      return SCIP_OKAY;
11700	
11701	   /* change priorities of attached variables */
11702	   switch( SCIPvarGetStatus(var) )
11703	   {
11704	   case SCIP_VARSTATUS_ORIGINAL:
11705	      if( var->data.original.transvar != NULL )
11706	      {
11707	         SCIP_CALL( SCIPvarChgBranchPriority(var->data.original.transvar, branchpriority) );
11708	      }
11709	      else
11710	         var->branchpriority = branchpriority;
11711	      break;
11712	
11713	   case SCIP_VARSTATUS_COLUMN:
11714	   case SCIP_VARSTATUS_LOOSE:
11715	   case SCIP_VARSTATUS_FIXED:
11716	      SCIP_CALL( varProcessChgBranchPriority(var, branchpriority) );
11717	      break;
11718	
11719	   case SCIP_VARSTATUS_AGGREGATED:
11720	      assert(!var->donotaggr);
11721	      assert(var->data.aggregate.var != NULL);
11722	      SCIP_CALL( SCIPvarChgBranchPriority(var->data.aggregate.var, branchpriority) );
11723	      break;
11724	
11725	   case SCIP_VARSTATUS_MULTAGGR:
11726	      assert(!var->donotmultaggr);
11727	      for( v = 0; v < var->data.multaggr.nvars; ++v )
11728	      {
11729	         SCIP_CALL( SCIPvarChgBranchPriority(var->data.multaggr.vars[v], branchpriority) );
11730	      }
11731	      break;
11732	
11733	   case SCIP_VARSTATUS_NEGATED:
11734	      assert(var->negatedvar != NULL);
11735	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
11736	      assert(var->negatedvar->negatedvar == var);
11737	      SCIP_CALL( SCIPvarChgBranchPriority(var->negatedvar, branchpriority) );
11738	      break;
11739	
11740	   default:
11741	      SCIPerrorMessage("unknown variable status\n");
11742	      SCIPABORT();
11743	      return SCIP_ERROR; /*lint !e527*/
11744	   }
11745	
11746	   return SCIP_OKAY;
11747	}
11748	
11749	/** actually changes the branch direction of the variable and of all parent variables */
11750	static
11751	SCIP_RETCODE varProcessChgBranchDirection(
11752	   SCIP_VAR*             var,                /**< problem variable */
11753	   SCIP_BRANCHDIR        branchdirection     /**< preferred branch direction of the variable (downwards, upwards, auto) */
11754	   )
11755	{
11756	   SCIP_VAR* parentvar;
11757	   int i;
11758	
11759	   assert(var != NULL);
11760	
11761	   SCIPdebugMessage("process changing branch direction of <%s> from %u to %d\n", 
11762	      var->name, var->branchdirection, branchdirection);
11763	
11764	   if( branchdirection == (SCIP_BRANCHDIR)var->branchdirection )
11765	      return SCIP_OKAY;
11766	
11767	   /* change the branch direction */
11768	   var->branchdirection = branchdirection; /*lint !e641*/
11769	
11770	   /* process parent variables */
11771	   for( i = 0; i < var->nparentvars; ++i )
11772	   {
11773	      parentvar = var->parentvars[i];
11774	      assert(parentvar != NULL);
11775	
11776	      switch( SCIPvarGetStatus(parentvar) )
11777	      {
11778	      case SCIP_VARSTATUS_ORIGINAL:
11779	         /* do not change directions across the border between transformed and original problem */
11780	         break;
11781	
11782	      case SCIP_VARSTATUS_COLUMN:
11783	      case SCIP_VARSTATUS_LOOSE:
11784	      case SCIP_VARSTATUS_FIXED:
11785	      case SCIP_VARSTATUS_MULTAGGR:
11786	         SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11787	         SCIPABORT();
11788	         return SCIP_INVALIDDATA; /*lint !e527*/
11789	
11790	      case SCIP_VARSTATUS_AGGREGATED:
11791	         if( parentvar->data.aggregate.scalar > 0.0 )
11792	         {
11793	            SCIP_CALL( varProcessChgBranchDirection(parentvar, branchdirection) );
11794	         }
11795	         else
11796	         {
11797	            SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11798	         }
11799	         break;
11800	
11801	      case SCIP_VARSTATUS_NEGATED:
11802	         SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11803	         break;
11804	
11805	      default:
11806	         SCIPerrorMessage("unknown variable status\n");
11807	         SCIPABORT();
11808	         return SCIP_ERROR; /*lint !e527*/
11809	      }
11810	   }
11811	
11812	   return SCIP_OKAY;
11813	}
11814	
11815	/** sets the branch direction of the variable; variables with higher branch direction are always preferred to variables
11816	 *  with lower direction in selection of branching variable
11817	 */
11818	SCIP_RETCODE SCIPvarChgBranchDirection(
11819	   SCIP_VAR*             var,                /**< problem variable */
11820	   SCIP_BRANCHDIR        branchdirection     /**< preferred branch direction of the variable (downwards, upwards, auto) */
11821	   )
11822	{
11823	   int v;
11824	
11825	   assert(var != NULL);
11826	
11827	   SCIPdebugMessage("changing branch direction of <%s> from %u to %d\n", var->name, var->branchdirection, branchdirection);
11828	
11829	   if( (SCIP_BRANCHDIR)var->branchdirection == branchdirection )
11830	      return SCIP_OKAY;
11831	
11832	   /* change directions of attached variables */
11833	   switch( SCIPvarGetStatus(var) )
11834	   {
11835	   case SCIP_VARSTATUS_ORIGINAL:
11836	      if( var->data.original.transvar != NULL )
11837	      {
11838	         SCIP_CALL( SCIPvarChgBranchDirection(var->data.original.transvar, branchdirection) );
11839	      }
11840	      else
11841	         var->branchdirection = branchdirection; /*lint !e641*/
11842	      break;
11843	
11844	   case SCIP_VARSTATUS_COLUMN:
11845	   case SCIP_VARSTATUS_LOOSE:
11846	   case SCIP_VARSTATUS_FIXED:
11847	      SCIP_CALL( varProcessChgBranchDirection(var, branchdirection) );
11848	      break;
11849	
11850	   case SCIP_VARSTATUS_AGGREGATED:
11851	      assert(!var->donotaggr);
11852	      assert(var->data.aggregate.var != NULL);
11853	      if( var->data.aggregate.scalar > 0.0 )
11854	      {
11855	         SCIP_CALL( SCIPvarChgBranchDirection(var->data.aggregate.var, branchdirection) );
11856	      }
11857	      else
11858	      {
11859	         SCIP_CALL( SCIPvarChgBranchDirection(var->data.aggregate.var, SCIPbranchdirOpposite(branchdirection)) );
11860	      }
11861	      break;
11862	
11863	   case SCIP_VARSTATUS_MULTAGGR:
11864	      assert(!var->donotmultaggr);
11865	      for( v = 0; v < var->data.multaggr.nvars; ++v )
11866	      {
11867	         /* only update branching direction of aggregation variables, if they don't have a preferred direction yet */
11868	         assert(var->data.multaggr.vars[v] != NULL);
11869	         if( (SCIP_BRANCHDIR)var->data.multaggr.vars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
11870	         {
11871	            if( var->data.multaggr.scalars[v] > 0.0 )
11872	            {
11873	               SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], branchdirection) );
11874	            }
11875	            else
11876	            {
11877	               SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], SCIPbranchdirOpposite(branchdirection)) );
11878	            }
11879	         }
11880	      }
11881	      break;
11882	
11883	   case SCIP_VARSTATUS_NEGATED:
11884	      assert(var->negatedvar != NULL);
11885	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
11886	      assert(var->negatedvar->negatedvar == var);
11887	      SCIP_CALL( SCIPvarChgBranchDirection(var->negatedvar, SCIPbranchdirOpposite(branchdirection)) );
11888	      break;
11889	
11890	   default:
11891	      SCIPerrorMessage("unknown variable status\n");
11892	      SCIPABORT();
11893	      return SCIP_ERROR; /*lint !e527*/
11894	   }
11895	
11896	   return SCIP_OKAY;
11897	}
11898	
11899	/** compares the index of two variables, only active, fixed or negated variables are allowed, if a variable
11900	 *  is negated then the index of the corresponding active variable is taken, returns -1 if first is
11901	 *  smaller than, and +1 if first is greater than second variable index; returns 0 if both indices
11902	 *  are equal, which means both variables are equal
11903	 */
11904	int SCIPvarCompareActiveAndNegated(
11905	   SCIP_VAR*             var1,               /**< first problem variable */
11906	   SCIP_VAR*             var2                /**< second problem variable */
11907	   )
11908	{
11909	   assert(var1 != NULL);
11910	   assert(var2 != NULL);
11911	   assert(SCIPvarIsActive(var1) || SCIPvarGetStatus(var1) == SCIP_VARSTATUS_NEGATED || SCIPvarGetStatus(var1) == SCIP_VARSTATUS_FIXED);
11912	   assert(SCIPvarIsActive(var2) || SCIPvarGetStatus(var2) == SCIP_VARSTATUS_NEGATED || SCIPvarGetStatus(var2) == SCIP_VARSTATUS_FIXED);
11913	
11914	   if( SCIPvarGetStatus(var1) == SCIP_VARSTATUS_NEGATED )
11915	      var1 = SCIPvarGetNegatedVar(var1);
11916	   if( SCIPvarGetStatus(var2) == SCIP_VARSTATUS_NEGATED )
11917	      var2 = SCIPvarGetNegatedVar(var2);
11918	
11919	   assert(var1 != NULL);
11920	   assert(var2 != NULL);
11921	
11922	   if( SCIPvarGetIndex(var1) < SCIPvarGetIndex(var2) )
11923	      return -1;
11924	   else if( SCIPvarGetIndex(var1) > SCIPvarGetIndex(var2) )
11925	      return +1;
11926	
11927	   assert(var1 == var2);
11928	   return 0;
11929	}
11930	
11931	/** comparison method for sorting active and negated variables by non-decreasing index, active and negated 
11932	 *  variables are handled as the same variables
11933	 */
11934	SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
11935	{
11936	   return SCIPvarCompareActiveAndNegated((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11937	}
11938	
11939	/** compares the index of two variables, returns -1 if first is smaller than, and +1 if first is greater than second
11940	 *  variable index; returns 0 if both indices are equal, which means both variables are equal
11941	 */
11942	int SCIPvarCompare(
11943	   SCIP_VAR*             var1,               /**< first problem variable */
11944	   SCIP_VAR*             var2                /**< second problem variable */
11945	   )
11946	{
11947	   assert(var1 != NULL);
11948	   assert(var2 != NULL);
11949	
11950	   if( var1->index < var2->index )
11951	      return -1;
11952	   else if( var1->index > var2->index )
11953	      return +1;
11954	   else
11955	   {
11956	      assert(var1 == var2);
11957	      return 0;
11958	   }
11959	}
11960	
11961	/** comparison method for sorting variables by non-decreasing index */
11962	SCIP_DECL_SORTPTRCOMP(SCIPvarComp)
11963	{
11964	   return SCIPvarCompare((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11965	}
11966	
11967	/** comparison method for sorting variables by non-decreasing objective coefficient */
11968	SCIP_DECL_SORTPTRCOMP(SCIPvarCompObj)
11969	{
11970	   SCIP_Real obj1;
11971	   SCIP_Real obj2;
11972	
11973	   obj1 = SCIPvarGetObj((SCIP_VAR*)elem1);
11974	   obj2 = SCIPvarGetObj((SCIP_VAR*)elem2);
11975	
11976	   if( obj1 < obj2 )
11977	      return -1;
11978	   else if( obj1 > obj2 )
11979	      return +1;
11980	   else
11981	      return 0;
11982	}
11983	
11984	/** hash key retrieval function for variables */
11985	SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
11986	{  /*lint --e{715}*/
11987	   return elem;
11988	}
11989	
11990	/** returns TRUE iff the indices of both variables are equal */
11991	SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
11992	{  /*lint --e{715}*/
11993	   if( key1 == key2 )
11994	      return TRUE;
11995	   return FALSE;
11996	}
11997	
11998	/** returns the hash value of the key */
11999	SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
12000	{  /*lint --e{715}*/
12001	   assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
12002	   return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
12003	}
12004	
12005	/** return for given variables all their active counterparts; all active variables will be pairwise different */
12006	SCIP_RETCODE SCIPvarsGetActiveVars(
12007	   SCIP_SET*             set,                /**< global SCIP settings */
12008	   SCIP_VAR**            vars,               /**< variable array with given variables and as output all active
12009						      *   variables, if enough slots exist
12010						      */
12011	   int*                  nvars,              /**< number of given variables, and as output number of active variables,
12012						      *   if enough slots exist
12013						      */
12014	   int                   varssize,           /**< available slots in vars array */
12015	   int*                  requiredsize        /**< pointer to store the required array size for the active variables */
12016	   )
12017	{
12018	   SCIP_VAR** activevars;
12019	   int nactivevars;
12020	   int activevarssize;
12021	
12022	   SCIP_VAR* var;
12023	   int v;
12024	
12025	   SCIP_VAR** tmpvars;
12026	   SCIP_VAR** multvars;
12027	   int tmpvarssize;
12028	   int ntmpvars;
12029	   int noldtmpvars;
12030	   int nmultvars;
12031	
12032	   assert(set != NULL);
12033	   assert(nvars != NULL);
12034	   assert(vars != NULL || *nvars == 0);
12035	   assert(varssize >= *nvars);
12036	   assert(requiredsize != NULL);
12037	
12038	   *requiredsize = 0;
12039	
12040	   if( *nvars == 0 )
12041	      return SCIP_OKAY;
12042	
12043	   nactivevars = 0;
12044	   activevarssize = *nvars;
12045	   ntmpvars = *nvars;
12046	   tmpvarssize = *nvars;
12047	
12048	   /* temporary memory */
12049	   SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
12050	   /* coverity[copy_paste_error] */
12051	   SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
12052	
12053	   noldtmpvars = ntmpvars;
12054	
12055	   /* sort all variables to combine equal variables easily */
12056	   SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12057	   for( v = ntmpvars - 1; v > 0; --v )
12058	   {
12059	      /* combine same variables */
12060	      if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
12061	      {
12062	         --ntmpvars;
12063	         tmpvars[v] = tmpvars[ntmpvars];
12064	      }
12065	   }
12066	   /* sort all variables again to combine equal variables later on */
12067	   if( noldtmpvars > ntmpvars )
12068	      SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12069	
12070	   /* collect for each variable the representation in active variables */
12071	   while( ntmpvars >= 1 )
12072	   {
12073	      --ntmpvars;
12074	      var = tmpvars[ntmpvars];
12075	      assert( var != NULL );
12076	
12077	      switch( SCIPvarGetStatus(var) )
12078	      {
12079	      case SCIP_VARSTATUS_ORIGINAL:
12080		 if( var->data.original.transvar == NULL )
12081		 {
12082		    SCIPerrorMessage("original variable has no transformed variable attached\n");
12083		    SCIPABORT();
12084		    return SCIP_INVALIDDATA; /*lint !e527*/
12085		 }
12086		 tmpvars[ntmpvars] = var->data.original.transvar;
12087		 ++ntmpvars;
12088		 break;
12089	
12090	      case SCIP_VARSTATUS_AGGREGATED:
12091		 tmpvars[ntmpvars] = var->data.aggregate.var;
12092		 ++ntmpvars;
12093		 break;
12094	
12095	      case SCIP_VARSTATUS_NEGATED:
12096		 tmpvars[ntmpvars] = var->negatedvar;
12097		 ++ntmpvars;
12098		 break;
12099	
12100	      case SCIP_VARSTATUS_LOOSE:
12101	      case SCIP_VARSTATUS_COLUMN:
12102		 /* check for space in temporary memory */
12103	         if( nactivevars >= activevarssize )
12104	         {
12105	            activevarssize *= 2;
12106	            SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
12107	            assert(nactivevars < activevarssize);
12108	         }
12109	         activevars[nactivevars] = var;
12110	         nactivevars++;
12111	         break;
12112	
12113	      case SCIP_VARSTATUS_MULTAGGR:
12114	         /* x = a_1*y_1 + ... + a_n*y_n + c */
12115	         nmultvars = var->data.multaggr.nvars;
12116	         multvars = var->data.multaggr.vars;
12117	
12118		 /* check for space in temporary memory */
12119	         if( nmultvars + ntmpvars > tmpvarssize )
12120	         {
12121	            while( nmultvars + ntmpvars > tmpvarssize )
12122	               tmpvarssize *= 2;
12123	            SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
12124	            assert(nmultvars + ntmpvars <= tmpvarssize);
12125	         }
12126	
12127		 /* copy all multi-aggregation variables into our working array */
12128		 BMScopyMemoryArray(&tmpvars[ntmpvars], multvars, nmultvars); /*lint !e866*/
12129	
12130		 /* get active, fixed or multi-aggregated corresponding variables for all new ones */
12131		 SCIPvarsGetProbvar(&tmpvars[ntmpvars], nmultvars);
12132	
12133		 ntmpvars += nmultvars;
12134		 noldtmpvars = ntmpvars;
12135	
12136		 /* sort all variables to combine equal variables easily */
12137		 SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12138		 for( v = ntmpvars - 1; v > 0; --v )
12139		 {
12140		    /* combine same variables */
12141		    if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
12142		    {
12143		       --ntmpvars;
12144		       tmpvars[v] = tmpvars[ntmpvars];
12145		    }
12146		 }
12147		 /* sort all variables again to combine equal variables later on */
12148		 if( noldtmpvars > ntmpvars )
12149		    SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12150	
12151	         break;
12152	
12153	      case SCIP_VARSTATUS_FIXED:
12154		 /* no need for memorizing fixed variables */
12155	         break;
12156	
12157	      default:
12158		 SCIPerrorMessage("unknown variable status\n");
12159	         SCIPABORT();
12160		 return SCIP_INVALIDDATA; /*lint !e527*/
12161	      }
12162	   }
12163	
12164	   /* sort variable array by variable index */
12165	   SCIPsortPtr((void**)activevars, SCIPvarComp, nactivevars);
12166	
12167	   /* eliminate duplicates and count required size */
12168	   v = nactivevars - 1;
12169	   while( v > 0 )
12170	   {
12171	      /* combine both variable since they are the same */
12172	      if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
12173	      {
12174		 --nactivevars;
12175		 activevars[v] = activevars[nactivevars];
12176	      }
12177	      --v;
12178	   }
12179	   *requiredsize = nactivevars;
12180	
12181	   if( varssize >= *requiredsize )
12182	   {
12183	      assert(vars != NULL);
12184	
12185	      *nvars = *requiredsize;
12186	      BMScopyMemoryArray(vars, activevars, nactivevars);
12187	   }
12188	
12189	   SCIPsetFreeBufferArray(set, &tmpvars);
12190	   SCIPsetFreeBufferArray(set, &activevars);
12191	
12192	   return SCIP_OKAY;
12193	}
12194	
12195	/** gets corresponding active, fixed, or multi-aggregated problem variables of given variables,
12196	 *  @note the content of the given array will/might change
12197	 */
12198	void SCIPvarsGetProbvar(
12199	   SCIP_VAR**            vars,               /**< array of problem variables */
12200	   int                   nvars               /**< number of variables */
12201	   )
12202	{
12203	   int v;
12204	
12205	   assert(vars != NULL || nvars == 0);
12206	
12207	   for( v = nvars - 1; v >= 0; --v )
12208	   {
12209	      assert(vars != NULL);
12210	      assert(vars[v] != NULL);
12211	
12212	      vars[v] = SCIPvarGetProbvar(vars[v]);
12213	      assert(vars[v] != NULL);
12214	   }
12215	}
12216	
12217	/** gets corresponding active, fixed, or multi-aggregated problem variable of a variable */
12218	SCIP_VAR* SCIPvarGetProbvar(
12219	   SCIP_VAR*             var                 /**< problem variable */
12220	   )
12221	{
12222	   SCIP_VAR* retvar;
12223	
12224	   assert(var != NULL);
12225	
12226	   retvar = var;
12227	
12228	   SCIPdebugMessage("get problem variable of <%s>\n", var->name);
12229	
12230	   while( TRUE ) /*lint !e716 */
12231	   {
12232	      assert(retvar != NULL);
12233	
12234	      switch( SCIPvarGetStatus(retvar) )
12235	      {
12236	      case SCIP_VARSTATUS_ORIGINAL:
12237		 if( retvar->data.original.transvar == NULL )
12238		 {
12239		    SCIPerrorMessage("original variable has no transformed variable attached\n");
12240		    SCIPABORT();
12241		    return NULL; /*lint !e527 */
12242		 }
12243		 retvar = retvar->data.original.transvar;
12244		 break;
12245	
12246	      case SCIP_VARSTATUS_LOOSE:
12247	      case SCIP_VARSTATUS_COLUMN:
12248	      case SCIP_VARSTATUS_FIXED:
12249		 return retvar;
12250	
12251	      case SCIP_VARSTATUS_MULTAGGR:
12252		 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12253		 if ( retvar->data.multaggr.nvars == 1 )
12254		    retvar = retvar->data.multaggr.vars[0];
12255		 else
12256		    return retvar;
12257		 break;
12258	
12259	      case SCIP_VARSTATUS_AGGREGATED:
12260		 retvar = retvar->data.aggregate.var;
12261		 break;
12262	
12263	      case SCIP_VARSTATUS_NEGATED:
12264		 retvar = retvar->negatedvar;
12265		 break;
12266	
12267	      default:
12268		 SCIPerrorMessage("unknown variable status\n");
12269		 SCIPABORT();
12270		 return NULL; /*lint !e527*/
12271	      }
12272	   }
12273	}
12274	
12275	/** gets corresponding active, fixed, or multi-aggregated problem variables of binary variables and updates the given
12276	 *  negation status of each variable
12277	 */
12278	SCIP_RETCODE SCIPvarsGetProbvarBinary(
12279	   SCIP_VAR***           vars,               /**< pointer to binary problem variables */
12280	   SCIP_Bool**           negatedarr,         /**< pointer to corresponding array to update the negation status */
12281	   int                   nvars               /**< number of variables and values in vars and negated array */
12282	   )
12283	{
12284	   SCIP_VAR** var;
12285	   SCIP_Bool* negated;
12286	   int v;
12287	
12288	   assert(vars != NULL);
12289	   assert(*vars != NULL || nvars == 0);
12290	   assert(negatedarr != NULL);
12291	   assert(*negatedarr != NULL || nvars == 0);
12292	
12293	   for( v = nvars - 1; v >= 0; --v )
12294	   {
12295	      var = &((*vars)[v]);
12296	      negated = &((*negatedarr)[v]);
12297	
12298	      /* get problem variable */
12299	      SCIP_CALL( SCIPvarGetProbvarBinary(var, negated) );
12300	   }
12301	
12302	   return SCIP_OKAY;
12303	}
12304	
12305	
12306	/** gets corresponding active, fixed, or multi-aggregated problem variable of a binary variable and updates the given
12307	 *  negation status (this means you have to assign a value to SCIP_Bool negated before calling this method, usually
12308	 *  FALSE is used)
12309	 */
12310	SCIP_RETCODE SCIPvarGetProbvarBinary(
12311	   SCIP_VAR**            var,                /**< pointer to binary problem variable */
12312	   SCIP_Bool*            negated             /**< pointer to update the negation status */
12313	   )
12314	{
12315	   SCIP_Bool active = FALSE;
12316	#ifndef NDEBUG
12317	   SCIP_Real constant = 0.0;
12318	   SCIP_Bool orignegated;
12319	#endif
12320	
12321	   assert(var != NULL);
12322	   assert(*var != NULL);
12323	   assert(negated != NULL);
12324	   assert(SCIPvarIsBinary(*var));
12325	
12326	#ifndef NDEBUG
12327	   orignegated = *negated;
12328	#endif
12329	
12330	   while( !active && *var != NULL )
12331	   {
12332	      switch( SCIPvarGetStatus(*var) )
12333	      {
12334	      case SCIP_VARSTATUS_ORIGINAL:
12335	         if( (*var)->data.original.transvar == NULL )
12336	            return SCIP_OKAY;
12337	         *var = (*var)->data.original.transvar;
12338	         break;
12339	
12340	      case SCIP_VARSTATUS_LOOSE:
12341	      case SCIP_VARSTATUS_COLUMN:
12342	      case SCIP_VARSTATUS_FIXED:
12343	         active = TRUE;
12344	         break;
12345	
12346	      case SCIP_VARSTATUS_MULTAGGR:
12347	         /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12348	         if ( (*var)->data.multaggr.nvars == 1 )
12349	         {
12350	            assert( (*var)->data.multaggr.vars != NULL );
12351	            assert( (*var)->data.multaggr.scalars != NULL );
12352	            assert( SCIPvarIsBinary((*var)->data.multaggr.vars[0]) );
12353	            assert(!EPSZ((*var)->data.multaggr.scalars[0], 1e-06));
12354	
12355	            /* if not all variables were fully propagated, it might happen that a variable is multi-aggregated to
12356	             * another variable which needs to be fixed
12357	             *
12358	             * e.g. x = y - 1 => (x = 0 && y = 1)
12359	             * e.g. x = y + 1 => (x = 1 && y = 0)
12360	             *
12361	             * is this special case we need to return the muti-aggregation
12362	             */
12363	            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)) )
12364	            {
12365	               assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06));
12366	            }
12367	            else
12368	            {
12369	               /* @note due to fixations, a multi-aggregation can have a constant of zero and a negative scalar or even
12370	                *       a scalar in absolute value unequal to one, in this case this aggregation variable needs to be
12371	                *       fixed to zero, but this should be done by another enforcement; so not depending on the scalar,
12372	                *       we will return the aggregated variable;
12373	                */
12374	               if( !EPSEQ(REALABS((*var)->data.multaggr.scalars[0]), 1.0, 1e-06) )
12375	               {
12376	                  active = TRUE;
12377	                  break;
12378	               }
12379	
12380	               /* @note it may also happen that the constant is larger than 1 or smaller than 0, in that case the
12381	                *       aggregation variable needs to be fixed to one, but this should be done by another enforcement;
12382	                *       so if this is the case, we will return the aggregated variable
12383	                */
12384	               assert(EPSZ((*var)->data.multaggr.constant, 1e-06) || EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06)
12385	                  || EPSZ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1e-06)
12386	                  || EPSEQ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1.0, 1e-06));
12387	
12388	               if( !EPSZ((*var)->data.multaggr.constant, 1e-06) && !EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06) )
12389	               {
12390	                  active = TRUE;
12391	                  break;
12392	               }
12393	
12394	               assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06) || EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
12395	
12396	               if( EPSZ((*var)->data.multaggr.constant, 1e-06) )
12397	               {
12398	                  /* if the scalar is negative, either the aggregation variable is already fixed to zero or has at
12399	                   * least one uplock (that hopefully will enforce this fixation to zero); can it happen that this
12400	                   * variable itself is multi-aggregated again?
12401	                   */
12402	                  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06) ?
12403	                     ((SCIPvarGetUbGlobal((*var)->data.multaggr.vars[0]) < 0.5) ||
12404	                        SCIPvarGetNLocksUpType((*var)->data.multaggr.vars[0], SCIP_LOCKTYPE_MODEL) > 0) : TRUE);
12405	               }
12406	               else
12407	               {
12408	                  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
12409	#ifndef NDEBUG
12410	                  constant += (*negated) != orignegated ? -1.0 : 1.0;
12411	#endif
12412	
12413	                  *negated = !(*negated);
12414	               }
12415	               *var = (*var)->data.multaggr.vars[0];
12416	               break;
12417	            }
12418	         }
12419	         active = TRUE;  /*lint !e838*/
12420	         break;
12421	
12422	      case SCIP_VARSTATUS_AGGREGATED:  /* x = a'*x' + c'  =>  a*x + c == (a*a')*x' + (a*c' + c) */
12423	         assert((*var)->data.aggregate.var != NULL);
12424	         assert(EPSEQ((*var)->data.aggregate.scalar, 1.0, 1e-06) || EPSEQ((*var)->data.aggregate.scalar, -1.0, 1e-06));
12425	         assert(EPSLE((*var)->data.aggregate.var->glbdom.ub - (*var)->data.aggregate.var->glbdom.lb, 1.0, 1e-06));
12426	#ifndef NDEBUG
12427	         constant += (*negated) != orignegated ? -(*var)->data.aggregate.constant : (*var)->data.aggregate.constant;
12428	#endif
12429	
12430	         *negated = ((*var)->data.aggregate.scalar > 0.0) ? *negated : !(*negated);
12431	         *var = (*var)->data.aggregate.var;
12432	         break;
12433	
12434	      case SCIP_VARSTATUS_NEGATED:     /* x =  - x' + c'  =>  a*x + c ==   (-a)*x' + (a*c' + c) */
12435	         assert((*var)->negatedvar != NULL);
12436	#ifndef NDEBUG
12437	         constant += (*negated) != orignegated ? -1.0 : 1.0;
12438	#endif
12439	
12440	         *negated = !(*negated);
12441	         *var = (*var)->negatedvar;
12442	         break;
12443	
12444	      default:
12445	         SCIPerrorMessage("unknown variable status\n");
12446	         return SCIP_INVALIDDATA;
12447	      }
12448	   }
12449	   assert(active == (*var != NULL));
12450	
12451	   if( active )
12452	   {
12453	      assert(SCIPvarIsBinary(*var));
12454	      assert(EPSZ(constant, 1e-06) || EPSEQ(constant, 1.0, 1e-06));
12455	      assert(EPSZ(constant, 1e-06) == ((*negated) == orignegated));
12456	
12457	      return SCIP_OKAY;
12458	   }
12459	   else
12460	   {
12461	      SCIPerrorMessage("active variable path leads to NULL pointer\n");
12462	      return SCIP_INVALIDDATA;
12463	   }
12464	}
12465	
12466	/** transforms given variable, boundtype and bound to the corresponding active, fixed, or multi-aggregated variable
12467	 *  values
12468	 */
12469	SCIP_RETCODE SCIPvarGetProbvarBound(
12470	   SCIP_VAR**            var,                /**< pointer to problem variable */
12471	   SCIP_Real*            bound,              /**< pointer to bound value to transform */
12472	   SCIP_BOUNDTYPE*       boundtype           /**< pointer to type of bound: lower or upper bound */
12473	   )
12474	{
12475	   assert(var != NULL);
12476	   assert(*var != NULL);
12477	   assert(bound != NULL);
12478	   assert(boundtype != NULL);
12479	
12480	   SCIPdebugMessage("get probvar bound %g of type %d of variable <%s>\n", *bound, *boundtype, (*var)->name);
12481	
12482	   switch( SCIPvarGetStatus(*var) )
12483	   {
12484	   case SCIP_VARSTATUS_ORIGINAL:
12485	      if( (*var)->data.original.transvar == NULL )
12486	      {
12487	         SCIPerrorMessage("original variable has no transformed variable attached\n");
12488	         return SCIP_INVALIDDATA;
12489	      }
12490	      *var = (*var)->data.original.transvar;
12491	      SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12492	      break;
12493	
12494	   case SCIP_VARSTATUS_LOOSE:
12495	   case SCIP_VARSTATUS_COLUMN:
12496	   case SCIP_VARSTATUS_FIXED:
12497	      break;
12498	
12499	   case SCIP_VARSTATUS_MULTAGGR:
12500	      /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12501	      if ( (*var)->data.multaggr.nvars == 1 )
12502	      {
12503	         assert( (*var)->data.multaggr.vars != NULL );
12504	         assert( (*var)->data.multaggr.scalars != NULL );
12505	         assert( (*var)->data.multaggr.scalars[0] != 0.0 );
12506	
12507	         (*bound) /= (*var)->data.multaggr.scalars[0];
12508	         (*bound) -= (*var)->data.multaggr.constant/(*var)->data.multaggr.scalars[0];
12509	         if ( (*var)->data.multaggr.scalars[0] < 0.0 )
12510	         {
12511	            if ( *boundtype == SCIP_BOUNDTYPE_LOWER )
12512	               *boundtype = SCIP_BOUNDTYPE_UPPER;
12513	            else
12514	               *boundtype = SCIP_BOUNDTYPE_LOWER;
12515	         }
12516	         *var = (*var)->data.multaggr.vars[0];
12517	         SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12518	      }
12519	      break;
12520	
12521	   case SCIP_VARSTATUS_AGGREGATED:  /* x = a*y + c  ->  y = x/a - c/a */
12522	      assert((*var)->data.aggregate.var != NULL);
12523	      assert((*var)->data.aggregate.scalar != 0.0);
12524	
12525	      (*bound) /= (*var)->data.aggregate.scalar;
12526	      (*bound) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12527	      if( (*var)->data.aggregate.scalar < 0.0 )
12528	      {
12529	         if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12530	            *boundtype = SCIP_BOUNDTYPE_UPPER;
12531	         else
12532	            *boundtype = SCIP_BOUNDTYPE_LOWER;
12533	      }
12534	      *var = (*var)->data.aggregate.var;
12535	      SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12536	      break;
12537	
12538	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
12539	      assert((*var)->negatedvar != NULL);
12540	      assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12541	      assert((*var)->negatedvar->negatedvar == *var);
12542	      (*bound) = (*var)->data.negate.constant - *bound;
12543	      if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12544	         *boundtype = SCIP_BOUNDTYPE_UPPER;
12545	      else
12546	         *boundtype = SCIP_BOUNDTYPE_LOWER;
12547	      *var = (*var)->negatedvar;
12548	      SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12549	      break;
12550	
12551	   default:
12552	      SCIPerrorMessage("unknown variable status\n");
12553	      return SCIP_INVALIDDATA;
12554	   }
12555	
12556	   return SCIP_OKAY;
12557	}
12558	
12559	/** transforms given variable and domain hole to the corresponding active, fixed, or multi-aggregated variable
12560	 *  values
12561	 */
12562	SCIP_RETCODE SCIPvarGetProbvarHole(
12563	   SCIP_VAR**            var,                /**< pointer to problem variable */
12564	   SCIP_Real*            left,               /**< pointer to left bound of open interval in hole to transform */
12565	   SCIP_Real*            right               /**< pointer to right bound of open interval in hole to transform */
12566	   )
12567	{
12568	   assert(var != NULL);
12569	   assert(*var != NULL);
12570	   assert(left != NULL);
12571	   assert(right != NULL);
12572	
12573	   SCIPdebugMessage("get probvar hole (%g,%g) of variable <%s>\n", *left, *right, (*var)->name);
12574	
12575	   switch( SCIPvarGetStatus(*var) )
12576	   {
12577	   case SCIP_VARSTATUS_ORIGINAL:
12578	      if( (*var)->data.original.transvar == NULL )
12579	      {
12580	         SCIPerrorMessage("original variable has no transformed variable attached\n");
12581	         return SCIP_INVALIDDATA;
12582	      }
12583	      *var = (*var)->data.original.transvar;
12584	      SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12585	      break;
12586	
12587	   case SCIP_VARSTATUS_LOOSE:
12588	   case SCIP_VARSTATUS_COLUMN:
12589	   case SCIP_VARSTATUS_FIXED:
12590	   case SCIP_VARSTATUS_MULTAGGR:
12591	      break;
12592	
12593	   case SCIP_VARSTATUS_AGGREGATED:  /* x = a*y + c  ->  y = x/a - c/a */
12594	      assert((*var)->data.aggregate.var != NULL);
12595	      assert((*var)->data.aggregate.scalar != 0.0);
12596	
12597	      /* scale back */
12598	      (*left) /= (*var)->data.aggregate.scalar;
12599	      (*right) /= (*var)->data.aggregate.scalar;
12600	
12601	      /* shift back */
12602	      (*left) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12603	      (*right) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12604	
12605	      *var = (*var)->data.aggregate.var;
12606	
12607	      /* check if the  interval bounds have to swapped */
12608	      if( (*var)->data.aggregate.scalar < 0.0 )
12609	      {
12610	         SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12611	      }
12612	      else
12613	      {
12614	         SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12615	      }
12616	      break;
12617	
12618	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
12619	      assert((*var)->negatedvar != NULL);
12620	      assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12621	      assert((*var)->negatedvar->negatedvar == *var);
12622	
12623	      /* shift and scale back */
12624	      (*left) = (*var)->data.negate.constant - (*left);
12625	      (*right) = (*var)->data.negate.constant - (*right);
12626	
12627	      *var = (*var)->negatedvar;
12628	
12629	      /* through the negated variable the left and right interval bound have to swapped */
12630	      SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12631	      break;
12632	
12633	   default:
12634	      SCIPerrorMessage("unknown variable status\n");
12635	      return SCIP_INVALIDDATA;
12636	   }
12637	
12638	   return SCIP_OKAY;
12639	}
12640	
12641	/** transforms given variable, scalar and constant to the corresponding active, fixed, or
12642	 *  multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable,
12643	 *  "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation
12644	 *  with only one active variable (this can happen due to fixings after the multi-aggregation),
12645	 *  is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0
12646	 */
12647	SCIP_RETCODE SCIPvarGetProbvarSum(
12648	   SCIP_VAR**            var,                /**< pointer to problem variable x in sum a*x + c */
12649	   SCIP_SET*             set,                /**< global SCIP settings */
12650	   SCIP_Real*            scalar,             /**< pointer to scalar a in sum a*x + c */
12651	   SCIP_Real*            constant            /**< pointer to constant c in sum a*x + c */
12652	   )
12653	{
12654	   assert(var != NULL);
12655	   assert(scalar != NULL);
12656	   assert(constant != NULL);
12657	
12658	   while( *var != NULL )
12659	   {
12660	      switch( SCIPvarGetStatus(*var) )
12661	      {
12662	      case SCIP_VARSTATUS_ORIGINAL:
12663	         if( (*var)->data.original.transvar == NULL )
12664	         {
12665	            SCIPerrorMessage("original variable has no transformed variable attached\n");
12666	            return SCIP_INVALIDDATA;
12667	         }
12668	         *var = (*var)->data.original.transvar;
12669	         break;
12670	
12671	      case SCIP_VARSTATUS_LOOSE:
12672	      case SCIP_VARSTATUS_COLUMN:
12673	         return SCIP_OKAY;
12674	
12675	      case SCIP_VARSTATUS_FIXED:       /* x = c'          =>  a*x + c ==             (a*c' + c) */
12676	         if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12677	         {
12678	            if( SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)) )
12679	            {
12680	               assert(*scalar != 0.0);
12681	               if( (*scalar) * (*var)->glbdom.lb > 0.0 )
12682	                  (*constant) = SCIPsetInfinity(set);
12683	               else
12684	                  (*constant) = -SCIPsetInfinity(set);
12685	            }
12686	            else
12687	               (*constant) += *scalar * (*var)->glbdom.lb;
12688	         }
12689	#ifndef NDEBUG
12690	         else
12691	         {
12692	            assert(!SCIPsetIsInfinity(set, (*constant)) || !((*scalar) * (*var)->glbdom.lb < 0.0 &&
12693	                  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12694	            assert(!SCIPsetIsInfinity(set, -(*constant)) || !((*scalar) * (*var)->glbdom.lb > 0.0 &&
12695	                  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12696	         }
12697	#endif
12698	         *scalar = 0.0;
12699	         return SCIP_OKAY;
12700	
12701	      case SCIP_VARSTATUS_MULTAGGR:
12702	         /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12703	         if ( (*var)->data.multaggr.nvars == 1 )
12704	         {
12705	            assert((*var)->data.multaggr.vars != NULL);
12706	            assert((*var)->data.multaggr.scalars != NULL);
12707	            assert((*var)->data.multaggr.vars[0] != NULL);
12708	            if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12709	            {
12710	               /* the multi-aggregation constant can be infinite, if one of the multi-aggregation variables
12711	                * was fixed to +/-infinity; ensure that the constant is set to +/-infinity, too, and the scalar
12712	                * is set to 0.0, because the multi-aggregated variable can be seen as fixed, too
12713	                */
12714	               if( SCIPsetIsInfinity(set, (*var)->data.multaggr.constant)
12715	                  || SCIPsetIsInfinity(set, -((*var)->data.multaggr.constant)) )
12716	               {
12717	                  if( (*scalar) * (*var)->data.multaggr.constant > 0 )
12718	                  {
12719	                     assert(!SCIPsetIsInfinity(set, -(*constant)));
12720	                     (*constant) = SCIPsetInfinity(set);
12721	                  }
12722	                  else
12723	                  {
12724	                     assert(!SCIPsetIsInfinity(set, *constant));
12725	                     (*constant) = -SCIPsetInfinity(set);
12726	                  }
12727	                  (*scalar) = 0.0;
12728	               }
12729	               else
12730	                  (*constant) += *scalar * (*var)->data.multaggr.constant;
12731	            }
12732	            (*scalar) *= (*var)->data.multaggr.scalars[0];
12733	            *var = (*var)->data.multaggr.vars[0];
12734	            break;
12735	         }
12736	         return SCIP_OKAY;
12737	
12738	      case SCIP_VARSTATUS_AGGREGATED:  /* x = a'*x' + c'  =>  a*x + c == (a*a')*x' + (a*c' + c) */
12739	         assert((*var)->data.aggregate.var != NULL);
12740	         assert(!SCIPsetIsInfinity(set, (*var)->data.aggregate.constant)
12741	            && !SCIPsetIsInfinity(set, (*var)->data.aggregate.constant));
12742	         if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12743	            (*constant) += *scalar * (*var)->data.aggregate.constant;
12744	         (*scalar) *= (*var)->data.aggregate.scalar;
12745	         *var = (*var)->data.aggregate.var;
12746	         break;
12747	
12748	      case SCIP_VARSTATUS_NEGATED:     /* x =  - x' + c'  =>  a*x + c ==   (-a)*x' + (a*c' + c) */
12749	         assert((*var)->negatedvar != NULL);
12750	         assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12751	         assert((*var)->negatedvar->negatedvar == *var);
12752	         assert(!SCIPsetIsInfinity(set, (*var)->data.negate.constant)
12753	            && !SCIPsetIsInfinity(set, (*var)->data.negate.constant));
12754	         if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12755	            (*constant) += *scalar * (*var)->data.negate.constant;
12756	         (*scalar) *= -1.0;
12757	         *var = (*var)->negatedvar;
12758	         break;
12759	
12760	      default:
12761	         SCIPerrorMessage("unknown variable status\n");
12762		 SCIPABORT();
12763	         return SCIP_INVALIDDATA; /*lint !e527*/
12764	      }
12765	   }
12766	   *scalar = 0.0;
12767	
12768	   return SCIP_OKAY;
12769	}
12770	
12771	/** retransforms given variable, scalar and constant to the corresponding original variable, scalar
12772	 *  and constant, if possible; if the retransformation is impossible, NULL is returned as variable
12773	 */
12774	SCIP_RETCODE SCIPvarGetOrigvarSum(
12775	   SCIP_VAR**            var,                /**< pointer to problem variable x in sum a*x + c */
12776	   SCIP_Real*            scalar,             /**< pointer to scalar a in sum a*x + c */
12777	   SCIP_Real*            constant            /**< pointer to constant c in sum a*x + c */
12778	   )
12779	{
12780	   SCIP_VAR* parentvar;
12781	
12782	   assert(var != NULL);
12783	   assert(*var != NULL);
12784	   assert(scalar != NULL);
12785	   assert(constant != NULL);
12786	
12787	   while( !SCIPvarIsOriginal(*var) )
12788	   {
12789	      /* if the variable has no parent variables, it was generated during solving and has no corresponding original
12790	       * var
12791	       */
12792	      if( (*var)->nparentvars == 0 )
12793	      {
12794	         /* negated variables do not need to have a parent variables, and negated variables can exist in original
12795	          * space
12796	          */
12797	         if( SCIPvarGetStatus(*var) == SCIP_VARSTATUS_NEGATED &&
12798	            ((*var)->negatedvar->nparentvars == 0 || (*var)->negatedvar->parentvars[0] != *var) )
12799	         {
12800	            *scalar *= -1.0;
12801	            *constant -= (*var)->data.negate.constant * (*scalar);
12802	            *var = (*var)->negatedvar;
12803	
12804	            continue;
12805	         }
12806	         /* if the variables does not have any parent the variables was created during solving and has no original
12807	          * counterpart
12808	          */
12809	         else
12810	         {
12811	            *var = NULL;
12812	
12813	            return SCIP_OKAY;
12814	         }
12815	      }
12816	
12817	      /* follow the link to the first parent variable */
12818	      parentvar = (*var)->parentvars[0];
12819	      assert(parentvar != NULL);
12820	
12821	      switch( SCIPvarGetStatus(parentvar) )
12822	      {
12823	      case SCIP_VARSTATUS_ORIGINAL:
12824	         break;
12825	
12826	      case SCIP_VARSTATUS_COLUMN:
12827	      case SCIP_VARSTATUS_LOOSE:
12828	      case SCIP_VARSTATUS_FIXED:
12829	      case SCIP_VARSTATUS_MULTAGGR:
12830	         SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12831	         return SCIP_INVALIDDATA;
12832	
12833	      case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + b  ->  y = (x-b)/a,  s*y + c = (s/a)*x + c-b*s/a */
12834	         assert(parentvar->data.aggregate.var == *var);
12835	         assert(parentvar->data.aggregate.scalar != 0.0);
12836	         *scalar /= parentvar->data.aggregate.scalar;
12837	         *constant -= parentvar->data.aggregate.constant * (*scalar);
12838	         break;
12839	
12840	      case SCIP_VARSTATUS_NEGATED: /* x = b - y  ->  y = b - x,  s*y + c = -s*x + c+b*s */
12841	         assert(parentvar->negatedvar != NULL);
12842	         assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
12843	         assert(parentvar->negatedvar->negatedvar == parentvar);
12844	         *scalar *= -1.0;
12845	         *constant -= parentvar->data.negate.constant * (*scalar);
12846	         break;
12847	
12848	      default:
12849	         SCIPerrorMessage("unknown variable status\n");
12850	         return SCIP_INVALIDDATA;
12851	      }
12852	
12853	      assert( parentvar != NULL );
12854	      *var = parentvar;
12855	   }
12856	
12857	   return SCIP_OKAY;
12858	}
12859	
12860	/** returns whether the given variable is the direct counterpart of an original problem variable */
12861	SCIP_Bool SCIPvarIsTransformedOrigvar(
12862	   SCIP_VAR*             var                 /**< problem variable */
12863	   )
12864	{
12865	   SCIP_VAR* parentvar;
12866	   assert(var != NULL);
12867	
12868	   if( !SCIPvarIsTransformed(var) || var->nparentvars < 1 )
12869	      return FALSE;
12870	
12871	   assert(var->parentvars != NULL);
12872	   parentvar = var->parentvars[0];
12873	   assert(parentvar != NULL);
12874	
12875	   /* we follow the aggregation tree to the root unless an original variable has been found - the first entries in the parentlist are candidates */
12876	   while( parentvar->nparentvars >= 1 && SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL )
12877	      parentvar = parentvar->parentvars[0];
12878	   assert( parentvar != NULL );
12879	
12880	   return ( SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_ORIGINAL );
12881	}
12882	
12883	/** gets objective value of variable in current SCIP_LP; the value can be different from the objective value stored in
12884	 *  the variable's own data due to diving, that operate only on the LP without updating the variables
12885	 */
12886	SCIP_Real SCIPvarGetObjLP(
12887	   SCIP_VAR*             var                 /**< problem variable */
12888	   )
12889	{
12890	   assert(var != NULL);
12891	
12892	   /* get bounds of attached variables */
12893	   switch( SCIPvarGetStatus(var) )
12894	   {
12895	   case SCIP_VARSTATUS_ORIGINAL:
12896	      assert(var->data.original.transvar != NULL);
12897	      return SCIPvarGetObjLP(var->data.original.transvar);
12898	
12899	   case SCIP_VARSTATUS_COLUMN:
12900	      assert(var->data.col != NULL);
12901	      return SCIPcolGetObj(var->data.col);
12902	
12903	   case SCIP_VARSTATUS_LOOSE:
12904	   case SCIP_VARSTATUS_FIXED:
12905	      return var->obj;
12906	
12907	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
12908	      assert(var->data.aggregate.var != NULL);
12909	      return var->data.aggregate.scalar * SCIPvarGetObjLP(var->data.aggregate.var);
12910	
12911	   case SCIP_VARSTATUS_MULTAGGR:
12912	      SCIPerrorMessage("cannot get the objective value of a multiple aggregated variable\n");
12913	      SCIPABORT();
12914	      return 0.0; /*lint !e527*/
12915	
12916	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
12917	      assert(var->negatedvar != NULL);
12918	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
12919	      assert(var->negatedvar->negatedvar == var);
12920	      return -SCIPvarGetObjLP(var->negatedvar);
12921	
12922	   default:
12923	      SCIPerrorMessage("unknown variable status\n");
12924	      SCIPABORT();
12925	      return 0.0; /*lint !e527*/
12926	   }
12927	}
12928	
12929	/** gets lower bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12930	 *  data due to diving or conflict analysis, that operate only on the LP without updating the variables
12931	 */
12932	SCIP_Real SCIPvarGetLbLP(
12933	   SCIP_VAR*             var,                /**< problem variable */
12934	   SCIP_SET*             set                 /**< global SCIP settings */
12935	   )
12936	{
12937	   assert(var != NULL);
12938	   assert(set != NULL);
12939	   assert(var->scip == set->scip);
12940	
12941	   /* get bounds of attached variables */
12942	   switch( SCIPvarGetStatus(var) )
12943	   {
12944	   case SCIP_VARSTATUS_ORIGINAL:
12945	      assert(var->data.original.transvar != NULL);
12946	      return SCIPvarGetLbLP(var->data.original.transvar, set);
12947	
12948	   case SCIP_VARSTATUS_COLUMN:
12949	      assert(var->data.col != NULL);
12950	      return SCIPcolGetLb(var->data.col);
12951	
12952	   case SCIP_VARSTATUS_LOOSE:
12953	   case SCIP_VARSTATUS_FIXED:
12954	      return var->locdom.lb;
12955	
12956	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
12957	      assert(var->data.aggregate.var != NULL);
12958	      if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set)))
12959	         || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set))) )
12960	      {
12961	         return -SCIPsetInfinity(set);
12962	      }
12963	      else if( var->data.aggregate.scalar > 0.0 )
12964	      {
12965	         /* a > 0 -> get lower bound of y */
12966	         return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12967	      }
12968	      else if( var->data.aggregate.scalar < 0.0 )
12969	      {
12970	         /* a < 0 -> get upper bound of y */
12971	         return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12972	      }
12973	      else
12974	      {
12975	         SCIPerrorMessage("scalar is zero in aggregation\n");
12976	         SCIPABORT();
12977	         return SCIP_INVALID; /*lint !e527*/
12978	      }
12979	
12980	   case SCIP_VARSTATUS_MULTAGGR:
12981	      /**@todo get the sides of the corresponding linear constraint */
12982	      SCIPerrorMessage("getting the bounds of a multiple aggregated variable is not implemented yet\n");
12983	      SCIPABORT();
12984	      return SCIP_INVALID; /*lint !e527*/
12985	
12986	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
12987	      assert(var->negatedvar != NULL);
12988	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
12989	      assert(var->negatedvar->negatedvar == var);
12990	      return var->data.negate.constant - SCIPvarGetUbLP(var->negatedvar, set);
12991	
12992	   default:
12993	      SCIPerrorMessage("unknown variable status\n");
12994	      SCIPABORT();
12995	      return SCIP_INVALID; /*lint !e527*/
12996	   }
12997	}
12998	
12999	/** gets upper bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
13000	 *  data due to diving or conflict analysis, that operate only on the LP without updating the variables
13001	 */
13002	SCIP_Real SCIPvarGetUbLP(
13003	   SCIP_VAR*             var,                /**< problem variable */
13004	   SCIP_SET*             set                 /**< global SCIP settings */
13005	   )
13006	{
13007	   assert(var != NULL);
13008	   assert(set != NULL);
13009	   assert(var->scip == set->scip);
13010	
13011	   /* get bounds of attached variables */
13012	   switch( SCIPvarGetStatus(var) )
13013	   {
13014	   case SCIP_VARSTATUS_ORIGINAL:
13015	      assert(var->data.original.transvar != NULL);
13016	      return SCIPvarGetUbLP(var->data.original.transvar, set);
13017	
13018	   case SCIP_VARSTATUS_COLUMN:
13019	      assert(var->data.col != NULL);
13020	      return SCIPcolGetUb(var->data.col);
13021	
13022	   case SCIP_VARSTATUS_LOOSE:
13023	   case SCIP_VARSTATUS_FIXED:
13024	      return var->locdom.ub;
13025	
13026	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
13027	      assert(var->data.aggregate.var != NULL);
13028	      if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set)))
13029	         || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set))) )
13030	      {
13031	         return SCIPsetInfinity(set);
13032	      }
13033	      if( var->data.aggregate.scalar > 0.0 )
13034	      {
13035	         /* a > 0 -> get upper bound of y */
13036	         return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
13037	      }
13038	      else if( var->data.aggregate.scalar < 0.0 )
13039	      {
13040	         /* a < 0 -> get lower bound of y */
13041	         return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
13042	      }
13043	      else
13044	      {
13045	         SCIPerrorMessage("scalar is zero in aggregation\n");
13046	         SCIPABORT();
13047	         return SCIP_INVALID; /*lint !e527*/
13048	      }
13049	
13050	   case SCIP_VARSTATUS_MULTAGGR:
13051	      SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
13052	      SCIPABORT();
13053	      return SCIP_INVALID; /*lint !e527*/
13054	
13055	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
13056	      assert(var->negatedvar != NULL);
13057	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
13058	      assert(var->negatedvar->negatedvar == var);
13059	      return var->data.negate.constant - SCIPvarGetLbLP(var->negatedvar, set);
13060	
13061	   default:
13062	      SCIPerrorMessage("unknown variable status\n");
13063	      SCIPABORT();
13064	      return SCIP_INVALID; /*lint !e527*/
13065	   }
13066	}
13067	
13068	/** gets primal LP solution value of variable */
13069	SCIP_Real SCIPvarGetLPSol_rec(
13070	   SCIP_VAR*             var                 /**< problem variable */
13071	   )
13072	{
13073	   assert(var != NULL);
13074	
13075	   switch( SCIPvarGetStatus(var) )
13076	   {
13077	   case SCIP_VARSTATUS_ORIGINAL:
13078	      if( var->data.original.transvar == NULL )
13079	         return SCIP_INVALID;
13080	      return SCIPvarGetLPSol(var->data.original.transvar);
13081	
13082	   case SCIP_VARSTATUS_LOOSE:
13083	      return SCIPvarGetBestBoundLocal(var);
13084	
13085	   case SCIP_VARSTATUS_COLUMN:
13086	      assert(var->data.col != NULL);
13087	      return SCIPcolGetPrimsol(var->data.col);
13088	
13089	   case SCIP_VARSTATUS_FIXED:
13090	      assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13091	      return var->locdom.lb;
13092	
13093	   case SCIP_VARSTATUS_AGGREGATED:
13094	   {
13095	      SCIP_Real lpsolval;
13096	
13097	      assert(!var->donotaggr);
13098	      assert(var->data.aggregate.var != NULL);
13099	      lpsolval = SCIPvarGetLPSol(var->data.aggregate.var);
13100	
13101	      /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13102	       * corresponding infinity value instead of performing an arithmetical transformation (compare method
13103	       * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13104	       * (or is called by) a public interface method; instead, we only assert that values are finite
13105	       * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13106	       * positives and negatives if the parameter <numerics/infinity> is modified by the user
13107	       */
13108	      assert(lpsolval > -SCIP_DEFAULT_INFINITY);
13109	      assert(lpsolval < +SCIP_DEFAULT_INFINITY);
13110	      return var->data.aggregate.scalar * lpsolval + var->data.aggregate.constant;
13111	   }
13112	   case SCIP_VARSTATUS_MULTAGGR:
13113	   {
13114	      SCIP_Real primsol;
13115	      int i;
13116	
13117	      assert(!var->donotmultaggr);
13118	      assert(var->data.multaggr.vars != NULL);
13119	      assert(var->data.multaggr.scalars != NULL);
13120	      /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13121	       * assert(var->data.multaggr.nvars >= 2); 
13122	       */
13123	      primsol = var->data.multaggr.constant;
13124	      for( i = 0; i < var->data.multaggr.nvars; ++i )
13125	         primsol += var->data.multaggr.scalars[i] * SCIPvarGetLPSol(var->data.multaggr.vars[i]);
13126	      return primsol;
13127	   }
13128	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
13129	      assert(var->negatedvar != NULL);
13130	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
13131	      assert(var->negatedvar->negatedvar == var);
13132	      return var->data.negate.constant - SCIPvarGetLPSol(var->negatedvar);
13133	
13134	   default:
13135	      SCIPerrorMessage("unknown variable status\n");
13136	      SCIPABORT();
13137	      return SCIP_INVALID; /*lint !e527*/
13138	   }
13139	}
13140	
13141	/** gets primal NLP solution value of variable */
13142	SCIP_Real SCIPvarGetNLPSol_rec(
13143	   SCIP_VAR*             var                 /**< problem variable */
13144	   )
13145	{
13146	   SCIP_Real solval;
13147	   int i;
13148	
13149	   assert(var != NULL);
13150	
13151	   /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13152	   switch( SCIPvarGetStatus(var) )
13153	   {
13154	   case SCIP_VARSTATUS_ORIGINAL:
13155	      return SCIPvarGetNLPSol(var->data.original.transvar);
13156	
13157	   case SCIP_VARSTATUS_LOOSE:
13158	   case SCIP_VARSTATUS_COLUMN:
13159	         return var->nlpsol;
13160	
13161	   case SCIP_VARSTATUS_FIXED:
13162	      assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var));  /*lint !e777*/
13163	      assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var));    /*lint !e777*/
13164	      assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var));   /*lint !e777*/
13165	      return SCIPvarGetLbGlobal(var);
13166	
13167	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  =>  y = (x-c)/a */
13168	      solval = SCIPvarGetNLPSol(var->data.aggregate.var);
13169	      return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13170	
13171	   case SCIP_VARSTATUS_MULTAGGR:
13172	      solval = var->data.multaggr.constant;
13173	      for( i = 0; i < var->data.multaggr.nvars; ++i )
13174	         solval += var->data.multaggr.scalars[i] * SCIPvarGetNLPSol(var->data.multaggr.vars[i]);
13175	      return solval;
13176	
13177	   case SCIP_VARSTATUS_NEGATED:
13178	      solval = SCIPvarGetNLPSol(var->negatedvar);
13179	      return var->data.negate.constant - solval;
13180	
13181	   default:
13182	      SCIPerrorMessage("unknown variable status\n");
13183	      SCIPABORT();
13184	      return SCIP_INVALID; /*lint !e527*/
13185	   }
13186	}
13187	
13188	/** gets pseudo solution value of variable at current node */
13189	static
13190	SCIP_Real SCIPvarGetPseudoSol_rec(
13191	   SCIP_VAR*             var                 /**< problem variable */
13192	   )
13193	{
13194	   SCIP_Real pseudosol;
13195	   int i;
13196	
13197	   assert(var != NULL);
13198	
13199	   switch( SCIPvarGetStatus(var) )
13200	   {
13201	   case SCIP_VARSTATUS_ORIGINAL:
13202	      if( var->data.original.transvar == NULL )
13203	         return SCIP_INVALID;
13204	      return SCIPvarGetPseudoSol(var->data.original.transvar);
13205	
13206	   case SCIP_VARSTATUS_LOOSE:
13207	   case SCIP_VARSTATUS_COLUMN:
13208	      return SCIPvarGetBestBoundLocal(var);
13209	
13210	   case SCIP_VARSTATUS_FIXED:
13211	      assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13212	      return var->locdom.lb;
13213	
13214	   case SCIP_VARSTATUS_AGGREGATED:
13215	   {
13216	      SCIP_Real pseudosolval;
13217	      assert(!var->donotaggr);
13218	      assert(var->data.aggregate.var != NULL);
13219	      /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13220	       * corresponding infinity value instead of performing an arithmetical transformation (compare method
13221	       * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13222	       * (or is called by) a public interface method; instead, we only assert that values are finite
13223	       * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13224	       * positives and negatives if the parameter <numerics/infinity> is modified by the user
13225	       */
13226	      pseudosolval = SCIPvarGetPseudoSol(var->data.aggregate.var);
13227	      assert(pseudosolval > -SCIP_DEFAULT_INFINITY);
13228	      assert(pseudosolval < +SCIP_DEFAULT_INFINITY);
13229	      return var->data.aggregate.scalar * pseudosolval + var->data.aggregate.constant;
13230	   }
13231	   case SCIP_VARSTATUS_MULTAGGR:
13232	      assert(!var->donotmultaggr);
13233	      assert(var->data.multaggr.vars != NULL);
13234	      assert(var->data.multaggr.scalars != NULL);
13235	      /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13236	       * assert(var->data.multaggr.nvars >= 2); 
13237	       */
13238	      pseudosol = var->data.multaggr.constant;
13239	      for( i = 0; i < var->data.multaggr.nvars; ++i )
13240	         pseudosol += var->data.multaggr.scalars[i] * SCIPvarGetPseudoSol(var->data.multaggr.vars[i]);
13241	      return pseudosol;
13242	
13243	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
13244	      assert(var->negatedvar != NULL);
13245	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
13246	      assert(var->negatedvar->negatedvar == var);
13247	      return var->data.negate.constant - SCIPvarGetPseudoSol(var->negatedvar);
13248	
13249	   default:
13250	      SCIPerrorMessage("unknown variable status\n");
13251	      SCIPABORT();
13252	      return SCIP_INVALID; /*lint !e527*/
13253	   }
13254	}
13255	
13256	/** gets current LP or pseudo solution value of variable */
13257	SCIP_Real SCIPvarGetSol(
13258	   SCIP_VAR*             var,                /**< problem variable */
13259	   SCIP_Bool             getlpval            /**< should the LP solution value be returned? */
13260	   )
13261	{
13262	   if( getlpval )
13263	      return SCIPvarGetLPSol(var);
13264	   else
13265	      return SCIPvarGetPseudoSol(var);
13266	}
13267	
13268	/** remembers the current solution as root solution in the problem variables */
13269	void SCIPvarStoreRootSol(
13270	   SCIP_VAR*             var,                /**< problem variable */
13271	   SCIP_Bool             roothaslp           /**< is the root solution from LP? */
13272	   )
13273	{
13274	   assert(var != NULL);
13275	
13276	   var->rootsol = SCIPvarGetSol(var, roothaslp);
13277	}
13278	
13279	/** updates the current solution as best root solution of the given variable if it is better */
13280	void SCIPvarUpdateBestRootSol(
13281	   SCIP_VAR*             var,                /**< problem variable */
13282	   SCIP_SET*             set,                /**< global SCIP settings */
13283	   SCIP_Real             rootsol,            /**< root solution value */
13284	   SCIP_Real             rootredcost,        /**< root reduced cost */
13285	   SCIP_Real             rootlpobjval        /**< objective value of the root LP */
13286	   )
13287	{
13288	   assert(var != NULL);
13289	   assert(set != NULL);
13290	   assert(var->scip == set->scip);
13291	
13292	   /* if reduced cost are zero nothing to update */
13293	   if( SCIPsetIsDualfeasZero(set, rootredcost) )
13294	      return;
13295	
13296	   /* check if we have already a best combination stored */
13297	   if( !SCIPsetIsDualfeasZero(set, var->bestrootredcost) )
13298	   {
13299	      SCIP_Real currcutoffbound;
13300	      SCIP_Real cutoffbound;
13301	      SCIP_Real bound;
13302	
13303	      /* compute the cutoff bound which would improve the corresponding bound with the current stored root solution,
13304	       * root reduced cost, and root LP objective value combination
13305	       */
13306	      if( var->bestrootredcost > 0.0 )
13307	         bound = SCIPvarGetUbGlobal(var);
13308	      else
13309	         bound = SCIPvarGetLbGlobal(var);
13310	
13311	      currcutoffbound = (bound - var->bestrootsol) * var->bestrootredcost + var->bestrootlpobjval;
13312	
13313	      /* compute the cutoff bound which would improve the corresponding bound with new root solution, root reduced
13314	       * cost, and root LP objective value combination
13315	       */
13316	      if( rootredcost > 0.0 )
13317	         bound = SCIPvarGetUbGlobal(var);
13318	      else
13319	         bound = SCIPvarGetLbGlobal(var);
13320	
13321	      cutoffbound = (bound - rootsol) * rootredcost + rootlpobjval;
13322	
13323	      /* check if an improving root solution, root reduced cost, and root LP objective value is at hand */
13324	      if( cutoffbound > currcutoffbound )
13325	      {
13326	         SCIPsetDebugMsg(set, "-> <%s> update potential cutoff bound <%g> -> <%g>\n",
13327	            SCIPvarGetName(var), currcutoffbound, cutoffbound);
13328	
13329	         var->bestrootsol = rootsol;
13330	         var->bestrootredcost = rootredcost;
13331	         var->bestrootlpobjval = rootlpobjval;
13332	      }
13333	   }
13334	   else
13335	   {
13336	      SCIPsetDebugMsg(set, "-> <%s> initialize best root reduced cost information\n", SCIPvarGetName(var));
13337	      SCIPsetDebugMsg(set, "   -> rootsol <%g>\n", rootsol);
13338	      SCIPsetDebugMsg(set, "   -> rootredcost <%g>\n", rootredcost);
13339	      SCIPsetDebugMsg(set, "   -> rootlpobjval <%g>\n", rootlpobjval);
13340	
13341	      var->bestrootsol = rootsol;
13342	      var->bestrootredcost = rootredcost;
13343	      var->bestrootlpobjval = rootlpobjval;
13344	   }
13345	}
13346	
13347	/** returns the solution of the variable in the last root node's relaxation, if the root relaxation is not yet
13348	 *  completely solved, zero is returned
13349	 */
13350	SCIP_Real SCIPvarGetRootSol(
13351	   SCIP_VAR*             var                 /**< problem variable */
13352	   )
13353	{
13354	   SCIP_Real rootsol;
13355	   int i;
13356	
13357	   assert(var != NULL);
13358	
13359	   switch( SCIPvarGetStatus(var) )
13360	   {
13361	   case SCIP_VARSTATUS_ORIGINAL:
13362	      if( var->data.original.transvar == NULL )
13363	         return 0.0;
13364	      return SCIPvarGetRootSol(var->data.original.transvar);
13365	
13366	   case SCIP_VARSTATUS_LOOSE:
13367	   case SCIP_VARSTATUS_COLUMN:
13368	      return var->rootsol;
13369	
13370	   case SCIP_VARSTATUS_FIXED:
13371	      assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13372	      return var->locdom.lb;
13373	
13374	   case SCIP_VARSTATUS_AGGREGATED:
13375	      assert(!var->donotaggr);
13376	      assert(var->data.aggregate.var != NULL);
13377	      /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13378	       * corresponding infinity value instead of performing an arithmetical transformation (compare method
13379	       * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13380	       * (or is called by) a public interface method; instead, we only assert that values are finite
13381	       * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13382	       * positives and negatives if the parameter <numerics/infinity> is modified by the user
13383	       */
13384	      assert(SCIPvarGetRootSol(var->data.aggregate.var) > -SCIP_DEFAULT_INFINITY);
13385	      assert(SCIPvarGetRootSol(var->data.aggregate.var) < +SCIP_DEFAULT_INFINITY);
13386	      return var->data.aggregate.scalar * SCIPvarGetRootSol(var->data.aggregate.var) + var->data.aggregate.constant;
13387	
13388	   case SCIP_VARSTATUS_MULTAGGR:
13389	      assert(!var->donotmultaggr);
13390	      assert(var->data.multaggr.vars != NULL);
13391	      assert(var->data.multaggr.scalars != NULL);
13392	      /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13393	       * assert(var->data.multaggr.nvars >= 2); 
13394	       */
13395	      rootsol = var->data.multaggr.constant;
13396	      for( i = 0; i < var->data.multaggr.nvars; ++i )
13397	         rootsol += var->data.multaggr.scalars[i] * SCIPvarGetRootSol(var->data.multaggr.vars[i]);
13398	      return rootsol;
13399	
13400	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
13401	      assert(var->negatedvar != NULL);
13402	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
13403	      assert(var->negatedvar->negatedvar == var);
13404	      return var->data.negate.constant - SCIPvarGetRootSol(var->negatedvar);
13405	
13406	   default:
13407	      SCIPerrorMessage("unknown variable status\n");
13408	      SCIPABORT();
13409	      return SCIP_INVALID; /*lint !e527*/
13410	   }
13411	}
13412	
13413	/** returns for given variable the reduced cost */
13414	static
13415	SCIP_Real getImplVarRedcost(
13416	   SCIP_VAR*             var,                /**< problem variable */
13417	   SCIP_SET*             set,                /**< global SCIP settings */
13418	   SCIP_Bool             varfixing,          /**< FALSE if for x == 0, TRUE for x == 1 */
13419	   SCIP_STAT*            stat,               /**< problem statistics */
13420	   SCIP_LP*              lp                  /**< current LP data */
13421	   )
13422	{
13423	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN )
13424	   {
13425	      SCIP_COL* col;
13426	      SCIP_Real primsol;
13427	      SCIP_BASESTAT basestat;
13428	      SCIP_Bool lpissolbasic;
13429	
13430	      col = SCIPvarGetCol(var);
13431	      assert(col != NULL);
13432	
13433	      basestat = SCIPcolGetBasisStatus(col);
13434	      lpissolbasic = SCIPlpIsSolBasic(lp);
13435	      primsol = SCIPcolGetPrimsol(col);
13436	
13437	      if( (lpissolbasic && (basestat == SCIP_BASESTAT_LOWER || basestat == SCIP_BASESTAT_UPPER)) ||
13438	         (!lpissolbasic && (SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol) || SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol))) )
13439	      {
13440	         SCIP_Real redcost = SCIPcolGetRedcost(col, stat, lp);
13441	
13442	         assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)) ||
13443	               (lpissolbasic && basestat == SCIP_BASESTAT_LOWER)) ? (!SCIPsetIsDualfeasNegative(set, redcost) ||
13444	                  SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var))) : TRUE);
13445	         assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)) ||
13446	               (lpissolbasic && basestat == SCIP_BASESTAT_UPPER)) ? (!SCIPsetIsDualfeasPositive(set, redcost) ||
13447	                  SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var))) : TRUE);
13448	
13449	         if( (varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_LOWER) ||
13450	                  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)))) ||
13451	            (!varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_UPPER) ||
13452	                  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)))) )
13453	            return redcost;
13454	         else
13455	            return 0.0;
13456	      }
13457	
13458	      return 0.0;
13459	   }
13460	
13461	   return 0.0;
13462	}
13463	
13464	#define MAX_CLIQUELENGTH 50
13465	/** returns for the given binary variable the reduced cost which are given by the variable itself and its implication if
13466	 *  the binary variable is fixed to the given value
13467	 */
13468	SCIP_Real SCIPvarGetImplRedcost(
13469	   SCIP_VAR*             var,                /**< problem variable */
13470	   SCIP_SET*             set,                /**< global SCIP settings */
13471	   SCIP_Bool             varfixing,          /**< FALSE if for x == 0, TRUE for x == 1 */
13472	   SCIP_STAT*            stat,               /**< problem statistics */
13473	   SCIP_PROB*            prob,               /**< transformed problem, or NULL */
13474	   SCIP_LP*              lp                  /**< current LP data */
13475	   )
13476	{
13477	   SCIP_Real implredcost;
13478	   int ncliques;
13479	   int nvars;
13480	
13481	   assert(SCIPvarIsBinary(var));
13482	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
13483	
13484	   /* get reduced cost of given variable */
13485	   implredcost = getImplVarRedcost(var, set, varfixing, stat, lp);
13486	
13487	#ifdef SCIP_MORE_DEBUG
13488	   SCIPsetDebugMsg(set, "variable <%s> itself has reduced cost of %g\n", SCIPvarGetName(var), implredcost);
13489	#endif
13490	
13491	   /* the following algorithm is expensive */
13492	   ncliques = SCIPvarGetNCliques(var, varfixing);
13493	
13494	   if( ncliques > 0 )
13495	   {
13496	      SCIP_CLIQUE** cliques;
13497	      SCIP_CLIQUE* clique;
13498	      SCIP_VAR** clqvars;
13499	      SCIP_VAR** probvars;
13500	      SCIP_VAR* clqvar;
13501	      SCIP_Bool* clqvalues;
13502	      int* entries;
13503	      int* ids;
13504	      SCIP_Real redcost;
13505	      SCIP_Bool cleanedup;
13506	      int nclqvars;
13507	      int nentries;
13508	      int nids;
13509	      int id;
13510	      int c;
13511	      int v;
13512	
13513	      assert(prob != NULL);
13514	      assert(SCIPprobIsTransformed(prob));
13515	
13516	      nentries = SCIPprobGetNVars(prob) - SCIPprobGetNContVars(prob) + 1;
13517	
13518	      SCIP_CALL_ABORT( SCIPsetAllocBufferArray(set, &ids, nentries) );
13519	      nids = 0;
13520	      SCIP_CALL_ABORT( SCIPsetAllocCleanBufferArray(set, &entries, nentries) );
13521	
13522	      cliques = SCIPvarGetCliques(var, varfixing);
13523	      assert(cliques != NULL);
13524	
13525	      for( c = ncliques - 1; c >= 0; --c )
13526	      {
13527	         clique = cliques[c];
13528	         assert(clique != NULL);
13529	         nclqvars = SCIPcliqueGetNVars(clique);
13530	         assert(nclqvars > 0);
13531	
13532	         if( nclqvars > MAX_CLIQUELENGTH )
13533	            continue;
13534	
13535	         clqvars = SCIPcliqueGetVars(clique);
13536	         clqvalues = SCIPcliqueGetValues(clique);
13537	         assert(clqvars != NULL);
13538	         assert(clqvalues != NULL);
13539	
13540	         cleanedup = SCIPcliqueIsCleanedUp(clique);
13541	
13542	         for( v = nclqvars - 1; v >= 0; --v )
13543	         {
13544	            clqvar = clqvars[v];
13545	            assert(clqvar != NULL);
13546	
13547	            /* ignore binary variable which are fixed */
13548	            if( clqvar != var && (cleanedup || SCIPvarIsActive(clqvar)) &&
13549	               (SCIPvarGetLbLocal(clqvar) < 0.5 && SCIPvarGetUbLocal(clqvar) > 0.5) )
13550	            {
13551	               int probindex = SCIPvarGetProbindex(clqvar) + 1;
13552	               assert(0 < probindex && probindex < nentries);
13553	
13554	#if 0
13555	               /* check that the variable was not yet visited or does not appear with two contradicting implications, ->
13556	                * can appear since there is no guarantee that all these infeasible bounds were found
13557	                */
13558	               assert(!entries[probindex] || entries[probindex] == (clqvalues[v] ? probindex : -probindex));
13559	#endif
13560	               if( entries[probindex] == 0 )
13561	               {
13562	                  ids[nids] = probindex;
13563	                  ++nids;
13564	
13565	                  /* mark variable as visited */
13566	                  entries[probindex] = (clqvalues[v] ? probindex : -probindex);
13567	               }
13568	            }
13569	         }
13570	      }
13571	
13572	      probvars = SCIPprobGetVars(prob);
13573	      assert(probvars != NULL);
13574	
13575	      /* add all implied reduced cost */
13576	      for( v = nids - 1; v >= 0; --v )
13577	      {
13578	         id = ids[v];
13579	         assert(0 < id && id < nentries);
13580	         assert(entries[id] != 0);
13581	         assert(probvars[id - 1] != NULL);
13582	         assert(SCIPvarIsActive(probvars[id - 1]));
13583	         assert(SCIPvarIsBinary(probvars[id - 1]));
13584	         assert(SCIPvarGetLbLocal(probvars[id - 1]) < 0.5 && SCIPvarGetUbLocal(probvars[id - 1]) > 0.5);
13585	
13586	         if( (entries[id] > 0) != varfixing )
13587	            redcost = getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13588	         else
13589	            redcost = -getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13590	
13591	         if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13592	            implredcost += redcost;
13593	
13594	         /* reset entries clear buffer array */
13595	         entries[id] = 0;
13596	      }
13597	
13598	      SCIPsetFreeCleanBufferArray(set, &entries);
13599	      SCIPsetFreeBufferArray(set, &ids);
13600	   }
13601	
13602	#ifdef SCIP_MORE_DEBUG
13603	   SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) has implied reduced cost of %g\n", SCIPvarGetName(var), ncliques,
13604	      implredcost);
13605	#endif
13606	
13607	   /* collect non-binary implication information */
13608	   nvars = SCIPimplicsGetNImpls(var->implics, varfixing);
13609	
13610	   if( nvars > 0 )
13611	   {
13612	      SCIP_VAR** vars;
13613	      SCIP_VAR* implvar;
13614	      SCIP_COL* col;
13615	      SCIP_Real* bounds;
13616	      SCIP_BOUNDTYPE* boundtypes;
13617	      SCIP_Real redcost;
13618	      SCIP_Real lb;
13619	      SCIP_Real ub;
13620	      SCIP_Bool lpissolbasic;
13621	      int v;
13622	
13623	      vars =  SCIPimplicsGetVars(var->implics, varfixing);
13624	      boundtypes = SCIPimplicsGetTypes(var->implics, varfixing);
13625	      bounds = SCIPimplicsGetBounds(var->implics, varfixing);
13626	      lpissolbasic = SCIPlpIsSolBasic(lp);
13627	
13628	      for( v = nvars - 1; v >= 0; --v )
13629	      {
13630	         implvar = vars[v];
13631	         assert(implvar != NULL);
13632	
13633	         lb = SCIPvarGetLbLocal(implvar);
13634	         ub = SCIPvarGetUbLocal(implvar);
13635	
13636	         /* ignore binary variable which are fixed or not of column status */
13637	         if( SCIPvarGetStatus(implvar) != SCIP_VARSTATUS_COLUMN || SCIPsetIsFeasEQ(set, lb, ub) )
13638	            continue;
13639	
13640	         col = SCIPvarGetCol(implvar);
13641	         assert(col != NULL);
13642	         redcost = 0.0;
13643	
13644	         /* solved lp with basis information or not? */
13645	         if( lpissolbasic )
13646	         {
13647	            SCIP_BASESTAT basestat = SCIPcolGetBasisStatus(col);
13648	
13649	            /* check if the implication is not not yet applied */
13650	            if( basestat == SCIP_BASESTAT_LOWER && boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, bounds[v], lb) )
13651	            {
13652	               redcost = SCIPcolGetRedcost(col, stat, lp);
13653	               assert(!SCIPsetIsDualfeasNegative(set, redcost));
13654	
13655	               if( !varfixing )
13656	                  redcost *= (lb - bounds[v]);
13657	               else
13658	                  redcost *= (bounds[v] - lb);
13659	            }
13660	            else if( basestat == SCIP_BASESTAT_UPPER && boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, bounds[v], ub) )
13661	            {
13662	               redcost = SCIPcolGetRedcost(col, stat, lp);
13663	               assert(!SCIPsetIsDualfeasPositive(set, redcost));
13664	
13665	               if( varfixing )
13666	                  redcost *= (bounds[v] - ub);
13667	               else
13668	                  redcost *= (ub - bounds[v]);
13669	            }
13670	         }
13671	         else
13672	         {
13673	            SCIP_Real primsol = SCIPcolGetPrimsol(col);
13674	
13675	            /* check if the implication is not not yet applied */
13676	            if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasEQ(set, lb, primsol) && SCIPsetIsFeasGT(set, bounds[v], lb) )
13677	            {
13678	               redcost = SCIPcolGetRedcost(col, stat, lp);
13679	               assert(!SCIPsetIsDualfeasNegative(set, redcost));
13680	
13681	               if( varfixing )
13682	                  redcost *= (lb - bounds[v]);
13683	               else
13684	                  redcost *= (bounds[v] - lb);
13685	            }
13686	            else if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasEQ(set, ub, primsol) && SCIPsetIsFeasLT(set, bounds[v], ub) )
13687	            {
13688	               redcost = SCIPcolGetRedcost(col, stat, lp);
13689	               assert(!SCIPsetIsDualfeasPositive(set, redcost));
13690	
13691	               if( varfixing )
13692	                  redcost *= (bounds[v] - ub);
13693	               else
13694	                  redcost *= (ub - bounds[v]);
13695	            }
13696	         }
13697	
13698	         /* improve implied reduced cost */
13699	         if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13700	            implredcost += redcost;
13701	      }
13702	   }
13703	
13704	#ifdef SCIP_MORE_DEBUG
13705	   SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) and implications (%d) has implied reduced cost of %g\n",
13706	      SCIPvarGetName(var), ncliques, nvars, implredcost);
13707	#endif
13708	
13709	   return implredcost;
13710	}
13711	
13712	/** returns the best solution (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation, if
13713	 *  the root relaxation is not yet completely solved, zero is returned
13714	 */
13715	SCIP_Real SCIPvarGetBestRootSol(
13716	   SCIP_VAR*             var                 /**< problem variable */
13717	   )
13718	{
13719	   SCIP_Real rootsol;
13720	   int i;
13721	
13722	   assert(var != NULL);
13723	
13724	   switch( SCIPvarGetStatus(var) )
13725	   {
13726	   case SCIP_VARSTATUS_ORIGINAL:
13727	      if( var->data.original.transvar == NULL )
13728	         return 0.0;
13729	      return SCIPvarGetBestRootSol(var->data.original.transvar);
13730	
13731	   case SCIP_VARSTATUS_LOOSE:
13732	   case SCIP_VARSTATUS_COLUMN:
13733	      return var->bestrootsol;
13734	
13735	   case SCIP_VARSTATUS_FIXED:
13736	      assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13737	      return var->locdom.lb;
13738	
13739	   case SCIP_VARSTATUS_AGGREGATED:
13740	      assert(!var->donotaggr);
13741	      assert(var->data.aggregate.var != NULL);
13742	      /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13743	       * corresponding infinity value instead of performing an arithmetical transformation (compare method
13744	       * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13745	       * (or is called by) a public interface method; instead, we only assert that values are finite
13746	       * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13747	       * positives and negatives if the parameter <numerics/infinity> is modified by the user
13748	       */
13749	      assert(SCIPvarGetBestRootSol(var->data.aggregate.var) > -SCIP_DEFAULT_INFINITY);
13750	      assert(SCIPvarGetBestRootSol(var->data.aggregate.var) < +SCIP_DEFAULT_INFINITY);
13751	      return var->data.aggregate.scalar * SCIPvarGetBestRootSol(var->data.aggregate.var) + var->data.aggregate.constant;
13752	
13753	   case SCIP_VARSTATUS_MULTAGGR:
13754	      assert(!var->donotmultaggr);
13755	      assert(var->data.multaggr.vars != NULL);
13756	      assert(var->data.multaggr.scalars != NULL);
13757	      /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13758	       * assert(var->data.multaggr.nvars >= 2);
13759	       */
13760	      rootsol = var->data.multaggr.constant;
13761	      for( i = 0; i < var->data.multaggr.nvars; ++i )
13762	         rootsol += var->data.multaggr.scalars[i] * SCIPvarGetBestRootSol(var->data.multaggr.vars[i]);
13763	      return rootsol;
13764	
13765	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
13766	      assert(var->negatedvar != NULL);
13767	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
13768	      assert(var->negatedvar->negatedvar == var);
13769	      return var->data.negate.constant - SCIPvarGetBestRootSol(var->negatedvar);
13770	
13771	   default:
13772	      SCIPerrorMessage("unknown variable status\n");
13773	      SCIPABORT();
13774	      return 0.0; /*lint !e527*/
13775	   }
13776	}
13777	
13778	/** returns the best reduced costs (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation,
13779	 *  if the root relaxation is not yet completely solved, or the variable was no column of the root LP, SCIP_INVALID is
13780	 *  returned
13781	 */
13782	SCIP_Real SCIPvarGetBestRootRedcost(
13783	   SCIP_VAR*             var                 /**< problem variable */
13784	   )
13785	{
13786	   assert(var != NULL);
13787	
13788	   switch( SCIPvarGetStatus(var) )
13789	   {
13790	   case SCIP_VARSTATUS_ORIGINAL:
13791	      if( var->data.original.transvar == NULL )
13792	         return SCIP_INVALID;
13793	      return SCIPvarGetBestRootRedcost(var->data.original.transvar);
13794	
13795	   case SCIP_VARSTATUS_LOOSE:
13796	   case SCIP_VARSTATUS_COLUMN:
13797	      return var->bestrootredcost;
13798	
13799	   case SCIP_VARSTATUS_FIXED:
13800	   case SCIP_VARSTATUS_AGGREGATED:
13801	   case SCIP_VARSTATUS_MULTAGGR:
13802	   case SCIP_VARSTATUS_NEGATED:
13803	      return 0.0;
13804	
13805	   default:
13806	      SCIPerrorMessage("unknown variable status\n");
13807	      SCIPABORT();
13808	      return 0.0; /*lint !e527*/
13809	   }
13810	}
13811	
13812	/** returns the best objective value (w.r.t. root reduced cost propagation) of the root LP which belongs the root
13813	 *  reduced cost which is accessible via SCIPvarGetRootRedcost() or the variable was no column of the root LP,
13814	 *  SCIP_INVALID is returned
13815	 */
13816	SCIP_Real SCIPvarGetBestRootLPObjval(
13817	   SCIP_VAR*             var                 /**< problem variable */
13818	   )
13819	{
13820	   assert(var != NULL);
13821	
13822	   switch( SCIPvarGetStatus(var) )
13823	   {
13824	   case SCIP_VARSTATUS_ORIGINAL:
13825	      if( var->data.original.transvar == NULL )
13826	         return SCIP_INVALID;
13827	      return SCIPvarGetBestRootLPObjval(var->data.original.transvar);
13828	
13829	   case SCIP_VARSTATUS_LOOSE:
13830	   case SCIP_VARSTATUS_COLUMN:
13831	      return var->bestrootlpobjval;
13832	
13833	   case SCIP_VARSTATUS_FIXED:
13834	   case SCIP_VARSTATUS_AGGREGATED:
13835	   case SCIP_VARSTATUS_MULTAGGR:
13836	   case SCIP_VARSTATUS_NEGATED:
13837	      return SCIP_INVALID;
13838	
13839	   default:
13840	      SCIPerrorMessage("unknown variable status\n");
13841	      SCIPABORT();
13842	      return SCIP_INVALID; /*lint !e527*/
13843	   }
13844	}
13845	
13846	/** set the given solution as the best root solution w.r.t. root reduced cost propagation in the variables */
13847	void SCIPvarSetBestRootSol(
13848	   SCIP_VAR*             var,                /**< problem variable */
13849	   SCIP_Real             rootsol,            /**< root solution value */
13850	   SCIP_Real             rootredcost,        /**< root reduced cost */
13851	   SCIP_Real             rootlpobjval        /**< objective value of the root LP */
13852	   )
13853	{
13854	   assert(var != NULL);
13855	
13856	   var->bestrootsol = rootsol;
13857	   var->bestrootredcost = rootredcost;
13858	   var->bestrootlpobjval = rootlpobjval;
13859	}
13860	
13861	/** stores the solution value as relaxation solution in the problem variable */
13862	SCIP_RETCODE SCIPvarSetRelaxSol(
13863	   SCIP_VAR*             var,                /**< problem variable */
13864	   SCIP_SET*             set,                /**< global SCIP settings */
13865	   SCIP_RELAXATION*      relaxation,         /**< global relaxation data */
13866	   SCIP_Real             solval,             /**< solution value in the current relaxation solution */
13867	   SCIP_Bool             updateobj           /**< should the objective value be updated? */
13868	   )
13869	{
13870	   assert(var != NULL);
13871	   assert(relaxation != NULL);
13872	   assert(set != NULL);
13873	   assert(var->scip == set->scip);
13874	
13875	   /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13876	   switch( SCIPvarGetStatus(var) )
13877	   {
13878	   case SCIP_VARSTATUS_ORIGINAL:
13879	      SCIP_CALL( SCIPvarSetRelaxSol(var->data.original.transvar, set, relaxation, solval, updateobj) );
13880	      break;
13881	
13882	   case SCIP_VARSTATUS_LOOSE:
13883	   case SCIP_VARSTATUS_COLUMN:
13884	      if( updateobj )
13885	         SCIPrelaxationSolObjAdd(relaxation, var->obj * (solval - var->relaxsol));
13886	      var->relaxsol = solval;
13887	      break;
13888	
13889	   case SCIP_VARSTATUS_FIXED:
13890	      if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13891	      {
13892	         SCIPerrorMessage("cannot set relaxation solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13893	            SCIPvarGetName(var), var->glbdom.lb, solval);
13894	         return SCIP_INVALIDDATA;
13895	      }
13896	      break;
13897	
13898	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  =>  y = (x-c)/a */
13899	      assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13900	      SCIP_CALL( SCIPvarSetRelaxSol(var->data.aggregate.var, set, relaxation, 
13901	            (solval - var->data.aggregate.constant)/var->data.aggregate.scalar, updateobj) );
13902	      break;
13903	   case SCIP_VARSTATUS_MULTAGGR:
13904	      SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13905	      return SCIP_INVALIDDATA;
13906	
13907	   case SCIP_VARSTATUS_NEGATED:
13908	      SCIP_CALL( SCIPvarSetRelaxSol(var->negatedvar, set, relaxation, var->data.negate.constant - solval, updateobj) );
13909	      break;
13910	
13911	   default:
13912	      SCIPerrorMessage("unknown variable status\n");
13913	      return SCIP_INVALIDDATA;
13914	   }
13915	
13916	   return SCIP_OKAY;
13917	}
13918	
13919	/** returns the solution value of the problem variable in the relaxation solution
13920	 *
13921	 *  @todo Inline this function - similar to SCIPvarGetLPSol_rec.
13922	 */
13923	SCIP_Real SCIPvarGetRelaxSol(
13924	   SCIP_VAR*             var,                /**< problem variable */
13925	   SCIP_SET*             set                 /**< global SCIP settings */
13926	   )
13927	{
13928	   SCIP_Real solvalsum;
13929	   SCIP_Real solval;
13930	   int i;
13931	
13932	   assert(var != NULL);
13933	   assert(set != NULL);
13934	   assert(var->scip == set->scip);
13935	
13936	   /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13937	   switch( SCIPvarGetStatus(var) )
13938	   {
13939	   case SCIP_VARSTATUS_ORIGINAL:
13940	      return SCIPvarGetRelaxSol(var->data.original.transvar, set);
13941	
13942	   case SCIP_VARSTATUS_LOOSE:
13943	   case SCIP_VARSTATUS_COLUMN:
13944	      return var->relaxsol;
13945	
13946	   case SCIP_VARSTATUS_FIXED:
13947	      assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var));  /*lint !e777*/
13948	      assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var));    /*lint !e777*/
13949	      assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var));   /*lint !e777*/
13950	      return SCIPvarGetLbGlobal(var);
13951	
13952	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  =>  y = (x-c)/a */
13953	      solval = SCIPvarGetRelaxSol(var->data.aggregate.var, set);
13954	      if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13955	      {
13956	         if( var->data.aggregate.scalar * solval > 0.0 )
13957	            return SCIPsetInfinity(set);
13958	         if( var->data.aggregate.scalar * solval < 0.0 )
13959	            return -SCIPsetInfinity(set);
13960	      }
13961	      return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13962	
13963	   case SCIP_VARSTATUS_MULTAGGR:
13964	      solvalsum = var->data.multaggr.constant;
13965	      for( i = 0; i < var->data.multaggr.nvars; ++i )
13966	      {
13967	         solval = SCIPvarGetRelaxSol(var->data.multaggr.vars[i], set);
13968	         if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13969	         {
13970	            if( var->data.multaggr.scalars[i] * solval > 0.0 )
13971	               return SCIPsetInfinity(set);
13972	            if( var->data.multaggr.scalars[i] * solval < 0.0 )
13973	               return -SCIPsetInfinity(set);
13974	         }
13975	         solvalsum += var->data.multaggr.scalars[i] * solval;
13976	      }
13977	      return solvalsum;
13978	
13979	   case SCIP_VARSTATUS_NEGATED:
13980	      solval = SCIPvarGetRelaxSol(var->negatedvar, set);
13981	      if( SCIPsetIsInfinity(set, solval) )
13982	         return -SCIPsetInfinity(set);
13983	      if( SCIPsetIsInfinity(set, -solval) )
13984	         return SCIPsetInfinity(set);
13985	      return var->data.negate.constant - solval;
13986	
13987	   default:
13988	      SCIPerrorMessage("unknown variable status\n");
13989	      SCIPABORT();
13990	      return SCIP_INVALID; /*lint !e527*/
13991	   }
13992	}
13993	
13994	/** returns the solution value of the transformed problem variable in the relaxation solution */
13995	SCIP_Real SCIPvarGetRelaxSolTransVar(
13996	   SCIP_VAR*             var                 /**< problem variable */
13997	   )
13998	{
13999	   assert(var != NULL);
14000	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
14001	
14002	   return var->relaxsol;
14003	}
14004	
14005	/** stores the solution value as NLP solution in the problem variable */
14006	SCIP_RETCODE SCIPvarSetNLPSol(
14007	   SCIP_VAR*             var,                /**< problem variable */
14008	   SCIP_SET*             set,                /**< global SCIP settings */
14009	   SCIP_Real             solval              /**< solution value in the current NLP solution */
14010	   )
14011	{
14012	   assert(var != NULL);
14013	   assert(set != NULL);
14014	   assert(var->scip == set->scip);
14015	
14016	   /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
14017	   switch( SCIPvarGetStatus(var) )
14018	   {
14019	   case SCIP_VARSTATUS_ORIGINAL:
14020	      SCIP_CALL( SCIPvarSetNLPSol(var->data.original.transvar, set, solval) );
14021	      break;
14022	
14023	   case SCIP_VARSTATUS_LOOSE:
14024	   case SCIP_VARSTATUS_COLUMN:
14025	      var->nlpsol = solval;
14026	      break;
14027	
14028	   case SCIP_VARSTATUS_FIXED:
14029	      if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
14030	      {
14031	         SCIPerrorMessage("cannot set NLP solution value for variable <%s> fixed to %.15g to different value %.15g\n",
14032	            SCIPvarGetName(var), var->glbdom.lb, solval);
14033	         SCIPABORT();
14034	         return SCIP_INVALIDCALL; /*lint !e527*/
14035	      }
14036	      break;
14037	
14038	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  =>  y = (x-c)/a */
14039	      assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
14040	      SCIP_CALL( SCIPvarSetNLPSol(var->data.aggregate.var, set, (solval - var->data.aggregate.constant)/var->data.aggregate.scalar) );
14041	      break;
14042	
14043	   case SCIP_VARSTATUS_MULTAGGR:
14044	      SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
14045	      SCIPABORT();
14046	      return SCIP_INVALIDCALL; /*lint !e527*/
14047	
14048	   case SCIP_VARSTATUS_NEGATED:
14049	      SCIP_CALL( SCIPvarSetNLPSol(var->negatedvar, set, var->data.negate.constant - solval) );
14050	      break;
14051	
14052	   default:
14053	      SCIPerrorMessage("unknown variable status\n");
14054	      SCIPABORT();
14055	      return SCIP_ERROR; /*lint !e527*/
14056	   }
14057	
14058	   return SCIP_OKAY;
14059	}
14060	
14061	/** returns a weighted average solution value of the variable in all feasible primal solutions found so far */
14062	SCIP_Real SCIPvarGetAvgSol(
14063	   SCIP_VAR*             var                 /**< problem variable */
14064	   )
14065	{
14066	   SCIP_Real avgsol;
14067	   int i;
14068	
14069	   assert(var != NULL);
14070	
14071	   switch( SCIPvarGetStatus(var) )
14072	   {
14073	   case SCIP_VARSTATUS_ORIGINAL:
14074	      if( var->data.original.transvar == NULL )
14075	         return 0.0;
14076	      return SCIPvarGetAvgSol(var->data.original.transvar);
14077	
14078	   case SCIP_VARSTATUS_LOOSE:
14079	   case SCIP_VARSTATUS_COLUMN:
14080	      avgsol = var->primsolavg;
14081	      avgsol = MAX(avgsol, var->glbdom.lb);
14082	      avgsol = MIN(avgsol, var->glbdom.ub);
14083	      return avgsol;
14084	
14085	   case SCIP_VARSTATUS_FIXED:
14086	      assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
14087	      return var->locdom.lb;
14088	
14089	   case SCIP_VARSTATUS_AGGREGATED:
14090	      assert(!var->donotaggr);
14091	      assert(var->data.aggregate.var != NULL);
14092	      return var->data.aggregate.scalar * SCIPvarGetAvgSol(var->data.aggregate.var)
14093	         + var->data.aggregate.constant;
14094	
14095	   case SCIP_VARSTATUS_MULTAGGR:
14096	      assert(!var->donotmultaggr);
14097	      assert(var->data.multaggr.vars != NULL);
14098	      assert(var->data.multaggr.scalars != NULL);
14099	      /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
14100	       * assert(var->data.multaggr.nvars >= 2); 
14101	       */
14102	      avgsol = var->data.multaggr.constant;
14103	      for( i = 0; i < var->data.multaggr.nvars; ++i )
14104	         avgsol += var->data.multaggr.scalars[i] * SCIPvarGetAvgSol(var->data.multaggr.vars[i]);
14105	      return avgsol;
14106	
14107	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
14108	      assert(var->negatedvar != NULL);
14109	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
14110	      assert(var->negatedvar->negatedvar == var);
14111	      return var->data.negate.constant - SCIPvarGetAvgSol(var->negatedvar);
14112	
14113	   default:
14114	      SCIPerrorMessage("unknown variable status\n");
14115	      SCIPABORT();
14116	      return 0.0; /*lint !e527*/
14117	   }
14118	}
14119	
14120	/** returns solution value and index of variable lower bound that is closest to the variable's value in the given primal solution
14121	 *  or current LP solution if no primal solution is given; returns an index of -1 if no variable lower bound is available
14122	 */
14123	void SCIPvarGetClosestVlb(
14124	   SCIP_VAR*             var,                /**< active problem variable */
14125	   SCIP_SOL*             sol,                /**< primal solution, or NULL for LP solution */
14126	   SCIP_SET*             set,                /**< global SCIP settings */
14127	   SCIP_STAT*            stat,               /**< problem statistics */
14128	   SCIP_Real*            closestvlb,         /**< pointer to store the value of the closest variable lower bound */
14129	   int*                  closestvlbidx       /**< pointer to store the index of the closest variable lower bound */
14130	   )
14131	{
14132	   int nvlbs;
14133	
14134	   assert(var != NULL);
14135	   assert(stat != NULL);
14136	   assert(set != NULL);
14137	   assert(var->scip == set->scip);
14138	   assert(closestvlb != NULL);
14139	   assert(closestvlbidx != NULL);
14140	
14141	   *closestvlbidx = -1;
14142	   *closestvlb = SCIP_REAL_MIN;
14143	
14144	   nvlbs = SCIPvarGetNVlbs(var);
14145	   if( nvlbs > 0 )
14146	   {
14147	      SCIP_VAR** vlbvars;
14148	      SCIP_Real* vlbcoefs;
14149	      SCIP_Real* vlbconsts;
14150	      int i;
14151	
14152	      vlbvars = SCIPvarGetVlbVars(var);
14153	      vlbcoefs = SCIPvarGetVlbCoefs(var);
14154	      vlbconsts = SCIPvarGetVlbConstants(var);
14155	
14156	      /* check for cached values */
14157	      if( var->closestvblpcount == stat->lpcount && var->closestvlbidx != -1 && sol == NULL)
14158	      {
14159	         i = var->closestvlbidx;
14160	         assert(0 <= i && i < nvlbs);
14161	         assert(SCIPvarIsActive(vlbvars[i]));
14162	         *closestvlbidx = i;
14163	         *closestvlb = vlbcoefs[i] * SCIPvarGetLPSol(vlbvars[i]) + vlbconsts[i];
14164	      }
14165	      else
14166	      {
14167	         /* search best VUB */
14168	         for( i = 0; i < nvlbs; i++ )
14169	         {
14170	            if( SCIPvarIsActive(vlbvars[i]) )
14171	            {
14172	               SCIP_Real vlbsol;
14173	
14174	               vlbsol = vlbcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vlbvars[i]) : SCIPsolGetVal(sol, set, stat, vlbvars[i])) + vlbconsts[i];
14175	               if( vlbsol > *closestvlb )
14176	               {
14177	                  *closestvlb = vlbsol;
14178	                  *closestvlbidx = i;
14179	               }
14180	            }
14181	         }
14182	
14183	         if( sol == NULL )
14184	         {
14185	            /* update cached value */
14186	            if( var->closestvblpcount != stat->lpcount )
14187	               var->closestvubidx = -1;
14188	            var->closestvlbidx = *closestvlbidx;
14189	            var->closestvblpcount = stat->lpcount;
14190	         }
14191	      }
14192	   }
14193	}
14194	
14195	/** returns solution value and index of variable upper bound that is closest to the variable's value in the given primal solution;
14196	 *  or current LP solution if no primal solution is given; returns an index of -1 if no variable upper bound is available
14197	 */
14198	void SCIPvarGetClosestVub(
14199	   SCIP_VAR*             var,                /**< active problem variable */
14200	   SCIP_SOL*             sol,                /**< primal solution, or NULL for LP solution */
14201	   SCIP_SET*             set,                /**< global SCIP settings */
14202	   SCIP_STAT*            stat,               /**< problem statistics */
14203	   SCIP_Real*            closestvub,         /**< pointer to store the value of the closest variable upper bound */
14204	   int*                  closestvubidx       /**< pointer to store the index of the closest variable upper bound */
14205	   )
14206	{
14207	   int nvubs;
14208	
14209	   assert(var != NULL);
14210	   assert(set != NULL);
14211	   assert(var->scip == set->scip);
14212	   assert(closestvub != NULL);
14213	   assert(closestvubidx != NULL);
14214	
14215	   *closestvubidx = -1;
14216	   *closestvub = SCIP_REAL_MAX;
14217	
14218	   nvubs = SCIPvarGetNVubs(var);
14219	   if( nvubs > 0 )
14220	   {
14221	      SCIP_VAR** vubvars;
14222	      SCIP_Real* vubcoefs;
14223	      SCIP_Real* vubconsts;
14224	      int i;
14225	
14226	      vubvars = SCIPvarGetVubVars(var);
14227	      vubcoefs = SCIPvarGetVubCoefs(var);
14228	      vubconsts = SCIPvarGetVubConstants(var);
14229	
14230	      /* check for cached values */
14231	      if( var->closestvblpcount == stat->lpcount && var->closestvubidx != -1 && sol == NULL)
14232	      {
14233	         i = var->closestvubidx;
14234	         assert(0 <= i && i < nvubs);
14235	         assert(SCIPvarIsActive(vubvars[i]));
14236	         *closestvubidx = i;
14237	         *closestvub = vubcoefs[i] * SCIPvarGetLPSol(vubvars[i]) + vubconsts[i];
14238	      }
14239	      else
14240	      {
14241	         /* search best VUB */
14242	         for( i = 0; i < nvubs; i++ )
14243	         {
14244	            if( SCIPvarIsActive(vubvars[i]) )
14245	            {
14246	               SCIP_Real vubsol;
14247	
14248	               vubsol = vubcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vubvars[i]) : SCIPsolGetVal(sol, set, stat, vubvars[i])) + vubconsts[i];
14249	               if( vubsol < *closestvub )
14250	               {
14251	                  *closestvub = vubsol;
14252	                  *closestvubidx = i;
14253	               }
14254	            }
14255	         }
14256	
14257	         if( sol == NULL )
14258	         {
14259	            /* update cached value */
14260	            if( var->closestvblpcount != stat->lpcount )
14261	               var->closestvlbidx = -1;
14262	            var->closestvubidx = *closestvubidx;
14263	            var->closestvblpcount = stat->lpcount;
14264	         }
14265	      }
14266	   }
14267	}
14268	
14269	/** resolves variable to columns and adds them with the coefficient to the row */
14270	SCIP_RETCODE SCIPvarAddToRow(
14271	   SCIP_VAR*             var,                /**< problem variable */
14272	   BMS_BLKMEM*           blkmem,             /**< block memory */
14273	   SCIP_SET*             set,                /**< global SCIP settings */
14274	   SCIP_STAT*            stat,               /**< problem statistics */
14275	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
14276	   SCIP_PROB*            prob,               /**< problem data */
14277	   SCIP_LP*              lp,                 /**< current LP data */
14278	   SCIP_ROW*             row,                /**< LP row */
14279	   SCIP_Real             val                 /**< value of coefficient */
14280	   )
14281	{
14282	   int i;
14283	
14284	   assert(var != NULL);
14285	   assert(set != NULL);
14286	   assert(var->scip == set->scip);
14287	   assert(row != NULL);
14288	   assert(!SCIPsetIsInfinity(set, REALABS(val)));
14289	
14290	   SCIPsetDebugMsg(set, "adding coefficient %g<%s> to row <%s>\n", val, var->name, row->name);
14291	
14292	   if ( SCIPsetIsZero(set, val) )
14293	      return SCIP_OKAY;
14294	
14295	   switch( SCIPvarGetStatus(var) )
14296	   {
14297	   case SCIP_VARSTATUS_ORIGINAL:
14298	      if( var->data.original.transvar == NULL )
14299	      {
14300	         SCIPerrorMessage("cannot add untransformed original variable <%s> to LP row <%s>\n", var->name, row->name);
14301	         return SCIP_INVALIDDATA;
14302	      }
14303	      SCIP_CALL( SCIPvarAddToRow(var->data.original.transvar, blkmem, set, stat, eventqueue, prob, lp, row, val) );
14304	      return SCIP_OKAY;
14305	
14306	   case SCIP_VARSTATUS_LOOSE:
14307	      /* add globally fixed variables as constant */
14308	      if( SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub) )
14309	      {
14310	         SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->glbdom.lb) );
14311	         return SCIP_OKAY;
14312	      }
14313	      /* convert loose variable into column */
14314	      SCIP_CALL( SCIPvarColumn(var, blkmem, set, stat, prob, lp) );
14315	      assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
14316	      /*lint -fallthrough*/
14317	
14318	   case SCIP_VARSTATUS_COLUMN:
14319	      assert(var->data.col != NULL);
14320	      assert(var->data.col->var == var);
14321	      SCIP_CALL( SCIProwIncCoef(row, blkmem, set, eventqueue, lp, var->data.col, val) );
14322	      return SCIP_OKAY;
14323	
14324	   case SCIP_VARSTATUS_FIXED:
14325	      assert(var->glbdom.lb == var->glbdom.ub); /*lint !e777*/
14326	      assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
14327	      assert(var->locdom.lb == var->glbdom.lb); /*lint !e777*/
14328	      assert(!SCIPsetIsInfinity(set, REALABS(var->locdom.lb)));
14329	      SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->locdom.lb) );
14330	      return SCIP_OKAY;
14331	
14332	   case SCIP_VARSTATUS_AGGREGATED:
14333	      assert(!var->donotaggr);
14334	      assert(var->data.aggregate.var != NULL);
14335	      SCIP_CALL( SCIPvarAddToRow(var->data.aggregate.var, blkmem, set, stat, eventqueue, prob, lp,
14336	            row, var->data.aggregate.scalar * val) );
14337	      SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.aggregate.constant * val) );
14338	      return SCIP_OKAY;
14339	
14340	   case SCIP_VARSTATUS_MULTAGGR:
14341	      assert(!var->donotmultaggr);
14342	      assert(var->data.multaggr.vars != NULL);
14343	      assert(var->data.multaggr.scalars != NULL);
14344	      /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
14345	       * assert(var->data.multaggr.nvars >= 2); 
14346	       */
14347	      for( i = 0; i < var->data.multaggr.nvars; ++i )
14348	      {
14349	         SCIP_CALL( SCIPvarAddToRow(var->data.multaggr.vars[i], blkmem, set, stat, eventqueue, prob, lp,
14350	               row, var->data.multaggr.scalars[i] * val) );
14351	      }
14352	      SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.multaggr.constant * val) );
14353	      return SCIP_OKAY;
14354	
14355	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
14356	      assert(var->negatedvar != NULL);
14357	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
14358	      assert(var->negatedvar->negatedvar == var);
14359	      SCIP_CALL( SCIPvarAddToRow(var->negatedvar, blkmem, set, stat, eventqueue, prob, lp, row, -val) );
14360	      SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.negate.constant * val) );
14361	      return SCIP_OKAY;
14362	
14363	   default:
14364	      SCIPerrorMessage("unknown variable status\n");
14365	      return SCIP_INVALIDDATA;
14366	   }
14367	}
14368	
14369	/* optionally, define this compiler flag to write complete variable histories to a file */
14370	#ifdef SCIP_HISTORYTOFILE
14371	SCIP_Longint counter = 0l;
14372	const char* historypath="."; /* allows for user-defined path; use '.' for calling directory of SCIP */
14373	#include "scip/scip.h"
14374	#endif
14375	
14376	/** updates the pseudo costs of the given variable and the global pseudo costs after a change of
14377	 *  "solvaldelta" in the variable's solution value and resulting change of "objdelta" in the in the LP's objective value
14378	 */
14379	SCIP_RETCODE SCIPvarUpdatePseudocost(
14380	   SCIP_VAR*             var,                /**< problem variable */
14381	   SCIP_SET*             set,                /**< global SCIP settings */
14382	   SCIP_STAT*            stat,               /**< problem statistics */
14383	   SCIP_Real             solvaldelta,        /**< difference of variable's new LP value - old LP value */
14384	   SCIP_Real             objdelta,           /**< difference of new LP's objective value - old LP's objective value */
14385	   SCIP_Real             weight              /**< weight in (0,1] of this update in pseudo cost sum */
14386	   )
14387	{
14388	   SCIP_Real oldrootpseudocosts;
14389	   assert(var != NULL);
14390	   assert(set != NULL);
14391	   assert(var->scip == set->scip);
14392	   assert(stat != NULL);
14393	
14394	   /* check if history statistics should be collected for a variable */
14395	   if( !stat->collectvarhistory )
14396	      return SCIP_OKAY;
14397	
14398	   switch( SCIPvarGetStatus(var) )
14399	   {
14400	   case SCIP_VARSTATUS_ORIGINAL:
14401	      if( var->data.original.transvar == NULL )
14402	      {
14403	         SCIPerrorMessage("cannot update pseudo costs of original untransformed variable\n");
14404	         return SCIP_INVALIDDATA;
14405	      }
14406	      SCIP_CALL( SCIPvarUpdatePseudocost(var->data.original.transvar, set, stat, solvaldelta, objdelta, weight) );
14407	      return SCIP_OKAY;
14408	
14409	   case SCIP_VARSTATUS_LOOSE:
14410	   case SCIP_VARSTATUS_COLUMN:
14411	      /* store old pseudo-costs for root LP best-estimate update */
14412	      oldrootpseudocosts = SCIPvarGetMinPseudocostScore(var, stat, set, SCIPvarGetRootSol(var));
14413	
14414	      /* update history */
14415	      SCIPhistoryUpdatePseudocost(var->history, set, solvaldelta, objdelta, weight);
14416	      SCIPhistoryUpdatePseudocost(var->historycrun, set, solvaldelta, objdelta, weight);
14417	      SCIPhistoryUpdatePseudocost(stat->glbhistory, set, solvaldelta, objdelta, weight);
14418	      SCIPhistoryUpdatePseudocost(stat->glbhistorycrun, set, solvaldelta, objdelta, weight);
14419	
14420	      /* update root LP best-estimate */
14421	      SCIP_CALL( SCIPstatUpdateVarRootLPBestEstimate(stat, set, var, oldrootpseudocosts) );
14422	
14423	      /* append history to file */
14424	#ifdef SCIP_HISTORYTOFILE
14425	   {
14426	      FILE* f;
14427	      char filename[256];
14428	      SCIP_NODE* currentnode;
14429	      SCIP_NODE* parentnode;
14430	      currentnode = SCIPgetFocusNode(set->scip);
14431	      parentnode = SCIPnodeGetParent(currentnode);
14432	
14433	      sprintf(filename, "%s/%s.pse", historypath, SCIPgetProbName(set->scip));
14434	      f = fopen(filename, "a");
14435	      if( NULL != f )
14436	      {
14437	         fprintf(f, "%lld %s \t %lld \t %lld \t %lld \t %d \t %15.9f \t %.3f\n",
14438	            ++counter,
14439	            SCIPvarGetName(var),
14440	            SCIPnodeGetNumber(currentnode),
14441	            parentnode != NULL ? SCIPnodeGetNumber(parentnode) : -1,
14442	            SCIPgetNLPIterations(set->scip),
14443	            SCIPgetDepth(set->scip),
14444	            objdelta,
14445	            solvaldelta);
14446	         fclose(f);
14447	      }
14448	   }
14449	#endif
14450	      return SCIP_OKAY;
14451	
14452	   case SCIP_VARSTATUS_FIXED:
14453	      SCIPerrorMessage("cannot update pseudo cost values of a fixed variable\n");
14454	      return SCIP_INVALIDDATA;
14455	
14456	   case SCIP_VARSTATUS_AGGREGATED:
14457	      assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
14458	      SCIP_CALL( SCIPvarUpdatePseudocost(var->data.aggregate.var, set, stat,
14459	            solvaldelta/var->data.aggregate.scalar, objdelta, weight) );
14460	      return SCIP_OKAY;
14461	
14462	   case SCIP_VARSTATUS_MULTAGGR:
14463	      SCIPerrorMessage("cannot update pseudo cost values of a multi-aggregated variable\n");
14464	      return SCIP_INVALIDDATA;
14465	
14466	   case SCIP_VARSTATUS_NEGATED:
14467	      SCIP_CALL( SCIPvarUpdatePseudocost(var->negatedvar, set, stat, -solvaldelta, objdelta, weight) );
14468	      return SCIP_OKAY;
14469	
14470	   default:
14471	      SCIPerrorMessage("unknown variable status\n");
14472	      return SCIP_INVALIDDATA;
14473	   }
14474	}
14475	
14476	/** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value */
14477	SCIP_Real SCIPvarGetPseudocost(
14478	   SCIP_VAR*             var,                /**< problem variable */
14479	   SCIP_STAT*            stat,               /**< problem statistics */
14480	   SCIP_Real             solvaldelta         /**< difference of variable's new LP value - old LP value */
14481	   )
14482	{
14483	   SCIP_BRANCHDIR dir;
14484	
14485	   assert(var != NULL);
14486	   assert(stat != NULL);
14487	
14488	   switch( SCIPvarGetStatus(var) )
14489	   {
14490	   case SCIP_VARSTATUS_ORIGINAL:
14491	      if( var->data.original.transvar == NULL )
14492	         return SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
14493	      else
14494	         return SCIPvarGetPseudocost(var->data.original.transvar, stat, solvaldelta);
14495	
14496	   case SCIP_VARSTATUS_LOOSE:
14497	   case SCIP_VARSTATUS_COLUMN:
14498	      dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
14499	
14500	      return SCIPhistoryGetPseudocostCount(var->history, dir) > 0.0
14501	         ? SCIPhistoryGetPseudocost(var->history, solvaldelta)
14502	         : SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
14503	
14504	   case SCIP_VARSTATUS_FIXED:
14505	      return 0.0;
14506	
14507	   case SCIP_VARSTATUS_AGGREGATED:
14508	      return SCIPvarGetPseudocost(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
14509	
14510	   case SCIP_VARSTATUS_MULTAGGR:
14511	      return 0.0;
14512	
14513	   case SCIP_VARSTATUS_NEGATED:
14514	      return SCIPvarGetPseudocost(var->negatedvar, stat, -solvaldelta);
14515	
14516	   default:
14517	      SCIPerrorMessage("unknown variable status\n");
14518	      SCIPABORT();
14519	      return 0.0; /*lint !e527*/
14520	   }
14521	}
14522	
14523	/** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value,
14524	 *  only using the pseudo cost information of the current run
14525	 */
14526	SCIP_Real SCIPvarGetPseudocostCurrentRun(
14527	   SCIP_VAR*             var,                /**< problem variable */
14528	   SCIP_STAT*            stat,               /**< problem statistics */
14529	   SCIP_Real             solvaldelta         /**< difference of variable's new LP value - old LP value */
14530	   )
14531	{
14532	   SCIP_BRANCHDIR dir;
14533	
14534	   assert(var != NULL);
14535	   assert(stat != NULL);
14536	
14537	   switch( SCIPvarGetStatus(var) )
14538	   {
14539	   case SCIP_VARSTATUS_ORIGINAL:
14540	      if( var->data.original.transvar == NULL )
14541	         return SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
14542	      else
14543	         return SCIPvarGetPseudocostCurrentRun(var->data.original.transvar, stat, solvaldelta);
14544	
14545	   case SCIP_VARSTATUS_LOOSE:
14546	   case SCIP_VARSTATUS_COLUMN:
14547	      dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
14548	
14549	      return SCIPhistoryGetPseudocostCount(var->historycrun, dir) > 0.0
14550	         ? SCIPhistoryGetPseudocost(var->historycrun, solvaldelta)
14551	         : SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
14552	
14553	   case SCIP_VARSTATUS_FIXED:
14554	      return 0.0;
14555	
14556	   case SCIP_VARSTATUS_AGGREGATED:
14557	      return SCIPvarGetPseudocostCurrentRun(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
14558	
14559	   case SCIP_VARSTATUS_MULTAGGR:
14560	      return 0.0;
14561	
14562	   case SCIP_VARSTATUS_NEGATED:
14563	      return SCIPvarGetPseudocostCurrentRun(var->negatedvar, stat, -solvaldelta);
14564	
14565	   default:
14566	      SCIPerrorMessage("unknown variable status\n");
14567	      SCIPABORT();
14568	      return 0.0; /*lint !e527*/
14569	   }
14570	}
14571	
14572	/** gets the variable's (possible fractional) number of pseudo cost updates for the given direction */
14573	SCIP_Real SCIPvarGetPseudocostCount(
14574	   SCIP_VAR*             var,                /**< problem variable */
14575	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
14576	   )
14577	{
14578	   assert(var != NULL);
14579	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14580	
14581	   switch( SCIPvarGetStatus(var) )
14582	   {
14583	   case SCIP_VARSTATUS_ORIGINAL:
14584	      if( var->data.original.transvar == NULL )
14585	         return 0.0;
14586	      else
14587	         return SCIPvarGetPseudocostCount(var->data.original.transvar, dir);
14588	
14589	   case SCIP_VARSTATUS_LOOSE:
14590	   case SCIP_VARSTATUS_COLUMN:
14591	      return SCIPhistoryGetPseudocostCount(var->history, dir);
14592	
14593	   case SCIP_VARSTATUS_FIXED:
14594	      return 0.0;
14595	
14596	   case SCIP_VARSTATUS_AGGREGATED:
14597	      if( var->data.aggregate.scalar > 0.0 )
14598	         return SCIPvarGetPseudocostCount(var->data.aggregate.var, dir);
14599	      else
14600	         return SCIPvarGetPseudocostCount(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
14601	
14602	   case SCIP_VARSTATUS_MULTAGGR:
14603	      return 0.0;
14604	
14605	   case SCIP_VARSTATUS_NEGATED:
14606	      return SCIPvarGetPseudocostCount(var->negatedvar, SCIPbranchdirOpposite(dir));
14607	
14608	   default:
14609	      SCIPerrorMessage("unknown variable status\n");
14610	      SCIPABORT();
14611	      return 0.0; /*lint !e527*/
14612	   }
14613	}
14614	
14615	/** gets the variable's (possible fractional) number of pseudo cost updates for the given direction,
14616	 *  only using the pseudo cost information of the current run
14617	 */
14618	SCIP_Real SCIPvarGetPseudocostCountCurrentRun(
14619	   SCIP_VAR*             var,                /**< problem variable */
14620	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
14621	   )
14622	{
14623	   assert(var != NULL);
14624	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14625	
14626	   switch( SCIPvarGetStatus(var) )
14627	   {
14628	   case SCIP_VARSTATUS_ORIGINAL:
14629	      if( var->data.original.transvar == NULL )
14630	         return 0.0;
14631	      else
14632	         return SCIPvarGetPseudocostCountCurrentRun(var->data.original.transvar, dir);
14633	
14634	   case SCIP_VARSTATUS_LOOSE:
14635	   case SCIP_VARSTATUS_COLUMN:
14636	      return SCIPhistoryGetPseudocostCount(var->historycrun, dir);
14637	
14638	   case SCIP_VARSTATUS_FIXED:
14639	      return 0.0;
14640	
14641	   case SCIP_VARSTATUS_AGGREGATED:
14642	      if( var->data.aggregate.scalar > 0.0 )
14643	         return SCIPvarGetPseudocostCountCurrentRun(var->data.aggregate.var, dir);
14644	      else
14645	         return SCIPvarGetPseudocostCountCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
14646	
14647	   case SCIP_VARSTATUS_MULTAGGR:
14648	      return 0.0;
14649	
14650	   case SCIP_VARSTATUS_NEGATED:
14651	      return SCIPvarGetPseudocostCountCurrentRun(var->negatedvar, SCIPbranchdirOpposite(dir));
14652	
14653	   default:
14654	      SCIPerrorMessage("unknown variable status\n");
14655	      SCIPABORT();
14656	      return 0.0; /*lint !e527*/
14657	   }
14658	}
14659	
14660	/** compares both possible directions for rounding the given solution value and returns the minimum pseudo-costs of the variable */
14661	SCIP_Real SCIPvarGetMinPseudocostScore(
14662	   SCIP_VAR*             var,                /**< problem variable */
14663	   SCIP_STAT*            stat,               /**< problem statistics */
14664	   SCIP_SET*             set,                /**< global SCIP settings */
14665	   SCIP_Real             solval              /**< solution value, e.g., LP solution value */
14666	   )
14667	{
14668	   SCIP_Real upscore;
14669	   SCIP_Real downscore;
14670	   SCIP_Real solvaldeltaup;
14671	   SCIP_Real solvaldeltadown;
14672	
14673	   /* LP root estimate only works for variables with fractional LP root solution */
14674	   if( SCIPsetIsFeasIntegral(set, solval) )
14675	      return 0.0;
14676	
14677	   /* no min pseudo-cost score is calculated as long as the variable was not initialized in a direction */
14678	   if( SCIPvarGetPseudocostCount(var, SCIP_BRANCHDIR_DOWNWARDS) < 1.0 || SCIPvarGetPseudocostCount(var, SCIP_BRANCHDIR_UPWARDS) < 1.0 )
14679	      return 0.0;
14680	
14681	   /* compute delta's to ceil and floor of root LP solution value */
14682	   solvaldeltaup = SCIPsetCeil(set, solval) - solval;
14683	   solvaldeltadown = SCIPsetFloor(set, solval) - solval;
14684	
14685	   upscore = SCIPvarGetPseudocost(var, stat, solvaldeltaup);
14686	   downscore = SCIPvarGetPseudocost(var, stat, solvaldeltadown);
14687	
14688	   return MIN(upscore, downscore);
14689	}
14690	
14691	/** gets the an estimate of the variable's pseudo cost variance in direction \p dir */
14692	SCIP_Real SCIPvarGetPseudocostVariance(
14693	   SCIP_VAR*             var,                /**< problem variable */
14694	   SCIP_BRANCHDIR        dir,                /**< branching direction (downwards, or upwards) */
14695	   SCIP_Bool             onlycurrentrun      /**< return pseudo cost variance only for current branch and bound run */
14696	   )
14697	{
14698	   assert(var != NULL);
14699	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14700	
14701	   switch( SCIPvarGetStatus(var) )
14702	   {
14703	   case SCIP_VARSTATUS_ORIGINAL:
14704	      if( var->data.original.transvar == NULL )
14705	         return 0.0;
14706	      else
14707	         return SCIPvarGetPseudocostVariance(var->data.original.transvar, dir, onlycurrentrun);
14708	
14709	   case SCIP_VARSTATUS_LOOSE:
14710	   case SCIP_VARSTATUS_COLUMN:
14711	      if( onlycurrentrun )
14712	         return SCIPhistoryGetPseudocostVariance(var->historycrun, dir);
14713	      else
14714	         return SCIPhistoryGetPseudocostVariance(var->history, dir);
14715	
14716	   case SCIP_VARSTATUS_FIXED:
14717	      return 0.0;
14718	
14719	   case SCIP_VARSTATUS_AGGREGATED:
14720	      if( var->data.aggregate.scalar > 0.0 )
14721	         return SCIPvarGetPseudocostVariance(var->data.aggregate.var, dir, onlycurrentrun);
14722	      else
14723	         return SCIPvarGetPseudocostVariance(var->data.aggregate.var, SCIPbranchdirOpposite(dir), onlycurrentrun);
14724	
14725	   case SCIP_VARSTATUS_MULTAGGR:
14726	      return 0.0;
14727	
14728	   case SCIP_VARSTATUS_NEGATED:
14729	      return SCIPvarGetPseudocostVariance(var->negatedvar, SCIPbranchdirOpposite(dir), onlycurrentrun);
14730	
14731	   default:
14732	      SCIPerrorMessage("unknown variable status\n");
14733	      SCIPABORT();
14734	      return 0.0; /*lint !e527*/
14735	   }
14736	}
14737	
14738	/** calculates a confidence bound for this variable under the assumption of normally distributed pseudo costs
14739	 *
14740	 *  The confidence bound \f$ \theta \geq 0\f$ denotes the interval borders \f$ [X - \theta, \ X + \theta]\f$, which contains
14741	 *  the true pseudo costs of the variable, i.e., the expected value of the normal distribution, with a probability
14742	 *  of 2 * clevel - 1.
14743	 *
14744	 *  @return value of confidence bound for this variable
14745	 */
14746	SCIP_Real SCIPvarCalcPscostConfidenceBound(
14747	   SCIP_VAR*             var,                /**< variable in question */
14748	   SCIP_SET*             set,                /**< global SCIP settings */
14749	   SCIP_BRANCHDIR        dir,                /**< the branching direction for the confidence bound */
14750	   SCIP_Bool             onlycurrentrun,     /**< should only the current run be taken into account */
14751	   SCIP_CONFIDENCELEVEL  clevel              /**< confidence level for the interval */
14752	   )
14753	{
14754	   SCIP_Real confidencebound;
14755	
14756	   confidencebound = SCIPvarGetPseudocostVariance(var, dir, onlycurrentrun);
14757	   if( SCIPsetIsFeasPositive(set, confidencebound) )
14758	   {
14759	      SCIP_Real count;
14760	
14761	      if( onlycurrentrun )
14762	         count = SCIPvarGetPseudocostCountCurrentRun(var, dir);
14763	      else
14764	         count = SCIPvarGetPseudocostCount(var, dir);
14765	      /* assertion is valid because variance is positive */
14766	      assert(count >= 1.9);
14767	
14768	      confidencebound /= count; /*lint !e414 division by zero can obviously not occur */
14769	      confidencebound = sqrt(confidencebound);
14770	
14771	      /* the actual, underlying distribution of the mean is a student-t-distribution with degrees of freedom equal to
14772	       * the number of pseudo cost evaluations of this variable in the respective direction. */
14773	      confidencebound *= SCIPstudentTGetCriticalValue(clevel, (int)SCIPsetFloor(set, count) - 1);
14774	   }
14775	   else
14776	      confidencebound = 0.0;
14777	
14778	   return confidencebound;
14779	}
14780	
14781	/** check if the current pseudo cost relative error in a direction violates the given threshold. The Relative
14782	 *  Error is calculated at a specific confidence level
14783	 */
14784	SCIP_Bool SCIPvarIsPscostRelerrorReliable(
14785	   SCIP_VAR*             var,                /**< variable in question */
14786	   SCIP_SET*             set,                /**< global SCIP settings */
14787	   SCIP_STAT*            stat,               /**< problem statistics */
14788	   SCIP_Real             threshold,          /**< threshold for relative errors to be considered reliable (enough) */
14789	   SCIP_CONFIDENCELEVEL  clevel              /**< a given confidence level */
14790	   )
14791	{
14792	   SCIP_Real downsize;
14793	   SCIP_Real upsize;
14794	   SCIP_Real size;
14795	   SCIP_Real relerrorup;
14796	   SCIP_Real relerrordown;
14797	   SCIP_Real relerror;
14798	
14799	   /* check, if the pseudo cost score of the variable is reliable */
14800	   downsize = SCIPvarGetPseudocostCountCurrentRun(var, SCIP_BRANCHDIR_DOWNWARDS);
14801	   upsize = SCIPvarGetPseudocostCountCurrentRun(var, SCIP_BRANCHDIR_UPWARDS);
14802	   size = MIN(downsize, upsize);
14803	
14804	   /* Pseudo costs relative error can only be reliable if both directions have been tried at least twice */
14805	   if( size <= 1.9 )
14806	      return FALSE;
14807	
14808	   /* use the relative error between the current mean pseudo cost value of the candidate and its upper
14809	    * confidence interval bound at confidence level of 95% for individual variable reliability.
14810	    * this is only possible if we have at least 2 measurements and therefore a valid variance estimate.
14811	    */
14812	   if( downsize >= 1.9 )
14813	   {
14814	      SCIP_Real normval;
14815	
14816	      relerrordown = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_DOWNWARDS, TRUE, clevel);
14817	      normval = SCIPvarGetPseudocostCurrentRun(var, stat, -1.0);
14818	      normval = MAX(1.0, normval);
14819	
14820	      relerrordown /= normval;
14821	   }
14822	   else
14823	      relerrordown = 0.0;
14824	
14825	   if( upsize >= 1.9 )
14826	   {
14827	      SCIP_Real normval;
14828	
14829	      relerrorup = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_UPWARDS, TRUE, clevel);
14830	      normval = SCIPvarGetPseudocostCurrentRun(var, stat, +1.0);
14831	      normval = MAX(1.0, normval);
14832	      relerrorup /= normval;
14833	   }
14834	   else
14835	      relerrorup = 0.0;
14836	
14837	   /* consider the relative error threshold violated, if it is violated in at least one branching direction */
14838	   relerror = MAX(relerrorup, relerrordown);
14839	
14840	   return (relerror <= threshold);
14841	}
14842	
14843	/** check if variable pseudo-costs have a significant difference in location. The significance depends on
14844	 *  the choice of \p clevel and on the kind of tested hypothesis. The one-sided hypothesis, which
14845	 *  should be rejected, is that fracy * mu_y >= fracx * mu_x, where mu_y and mu_x denote the
14846	 *  unknown location means of the underlying pseudo-cost distributions of x and y.
14847	 *
14848	 *  This method is applied best if variable x has a better pseudo-cost score than y. The method hypothesizes that y were actually
14849	 *  better than x (despite the current information), meaning that y can be expected to yield branching
14850	 *  decisions as least as good as x in the long run. If the method returns TRUE, the current history information is
14851	 *  sufficient to safely rely on the alternative hypothesis that x yields indeed a better branching score (on average)
14852	 *  than y.
14853	 *
14854	 *  @note The order of x and y matters for the one-sided hypothesis
14855	 *
14856	 *  @note set \p onesided to FALSE if you are not sure which variable is better. The hypothesis tested then reads
14857	 *        fracy * mu_y == fracx * mu_x vs the alternative hypothesis fracy * mu_y != fracx * mu_x.
14858	 *
14859	 *  @return TRUE if the hypothesis can be safely rejected at the given confidence level
14860	 */
14861	SCIP_Bool SCIPvarSignificantPscostDifference(
14862	   SCIP_SET*             set,                /**< global SCIP settings */
14863	   SCIP_STAT*            stat,               /**< problem statistics */
14864	   SCIP_VAR*             varx,               /**< variable x */
14865	   SCIP_Real             fracx,              /**< the fractionality of variable x */
14866	   SCIP_VAR*             vary,               /**< variable y */
14867	   SCIP_Real             fracy,              /**< the fractionality of variable y */
14868	   SCIP_BRANCHDIR        dir,                /**< branching direction */
14869	   SCIP_CONFIDENCELEVEL  clevel,             /**< confidence level for rejecting hypothesis */
14870	   SCIP_Bool             onesided            /**< should a one-sided hypothesis y >= x be tested? */
14871	   )
14872	{
14873	   SCIP_Real meanx;
14874	   SCIP_Real meany;
14875	   SCIP_Real variancex;
14876	   SCIP_Real variancey;
14877	   SCIP_Real countx;
14878	   SCIP_Real county;
14879	   SCIP_Real tresult;
14880	   SCIP_Real realdirection;
14881	
14882	   if( varx == vary )
14883	      return FALSE;
14884	
14885	   countx = SCIPvarGetPseudocostCount(varx, dir);
14886	   county = SCIPvarGetPseudocostCount(vary, dir);
14887	
14888	   /* if not at least 2 measurements were taken, return FALSE */
14889	   if( countx <= 1.9 || county <= 1.9 )
14890	      return FALSE;
14891	
14892	   realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14893	
14894	   meanx = fracx * SCIPvarGetPseudocost(varx, stat, realdirection);
14895	   meany = fracy * SCIPvarGetPseudocost(vary, stat, realdirection);
14896	
14897	   variancex = SQR(fracx) * SCIPvarGetPseudocostVariance(varx, dir, FALSE);
14898	   variancey = SQR(fracy) * SCIPvarGetPseudocostVariance(vary, dir, FALSE);
14899	
14900	   /* if there is no variance, the means are taken from a constant distribution */
14901	   if( SCIPsetIsFeasEQ(set, variancex + variancey, 0.0) )
14902	      return (onesided ? SCIPsetIsFeasGT(set, meanx, meany) : !SCIPsetIsFeasEQ(set, meanx, meany));
14903	
14904	   tresult = SCIPcomputeTwoSampleTTestValue(meanx, meany, variancex, variancey, countx, county);
14905	
14906	   /* for the two-sided hypothesis, just take the absolute of t */
14907	   if( !onesided )
14908	      tresult = REALABS(tresult);
14909	
14910	   return (tresult >= SCIPstudentTGetCriticalValue(clevel, (int)(countx + county - 2)));
14911	}
14912	
14913	/** tests at a given confidence level whether the variable pseudo-costs only have a small probability to
14914	 *  exceed a \p threshold. This is useful to determine if past observations provide enough evidence
14915	 *  to skip an expensive strong-branching step if there is already a candidate that has been proven to yield an improvement
14916	 *  of at least \p threshold.
14917	 *
14918	 *  @note use \p clevel to adjust the level of confidence. For SCIP_CONFIDENCELEVEL_MIN, the method returns TRUE if
14919	 *        the estimated probability to exceed \p threshold is less than 25 %.
14920	 *
14921	 *  @see  SCIP_Confidencelevel for a list of available levels. The used probability limits refer to the one-sided levels
14922	 *        of confidence.
14923	 *
14924	 *  @return TRUE if the variable pseudo-cost probabilistic model is likely to be smaller than \p threshold
14925	 *          at the given confidence level \p clevel.
14926	 */
14927	SCIP_Bool SCIPvarPscostThresholdProbabilityTest(
14928	   SCIP_SET*             set,                /**< global SCIP settings */
14929	   SCIP_STAT*            stat,               /**< problem statistics */
14930	   SCIP_VAR*             var,                /**< variable x */
14931	   SCIP_Real             frac,               /**< the fractionality of variable x */
14932	   SCIP_Real             threshold,          /**< the threshold to test against */
14933	   SCIP_BRANCHDIR        dir,                /**< branching direction */
14934	   SCIP_CONFIDENCELEVEL  clevel              /**< confidence level for rejecting hypothesis */
14935	   )
14936	{
14937	   SCIP_Real mean;
14938	   SCIP_Real variance;
14939	   SCIP_Real count;
14940	   SCIP_Real realdirection;
14941	   SCIP_Real probability;
14942	   SCIP_Real problimit;
14943	
14944	   count = SCIPvarGetPseudocostCount(var, dir);
14945	
14946	   /* if not at least 2 measurements were taken, return FALSE */
14947	   if( count <= 1.9 )
14948	      return FALSE;
14949	
14950	   realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14951	
14952	   mean = frac * SCIPvarGetPseudocost(var, stat, realdirection);
14953	   variance = SQR(frac) * SCIPvarGetPseudocostVariance(var, dir, FALSE);
14954	
14955	   /* if mean is at least threshold, it has at least a 50% probability to exceed threshold, we therefore return FALSE */
14956	   if( SCIPsetIsFeasGE(set, mean, threshold) )
14957	      return FALSE;
14958	
14959	   /* if there is no variance, the means are taken from a constant distribution */
14960	   if( SCIPsetIsFeasEQ(set, variance, 0.0) )
14961	      return SCIPsetIsFeasLT(set, mean, threshold);
14962	
14963	   /* obtain probability of a normally distributed random variable at given mean and variance to yield at most threshold */
14964	   probability = SCIPnormalCDF(mean, variance, threshold);
14965	
14966	   /* determine a probability limit corresponding to the given confidence level */
14967	   switch( clevel )
14968	   {
14969	      case SCIP_CONFIDENCELEVEL_MIN:
14970	         problimit = 0.75;
14971	         break;
14972	      case SCIP_CONFIDENCELEVEL_LOW:
14973	         problimit = 0.875;
14974	         break;
14975	      case SCIP_CONFIDENCELEVEL_MEDIUM:
14976	         problimit = 0.9;
14977	         break;
14978	      case SCIP_CONFIDENCELEVEL_HIGH:
14979	         problimit = 0.95;
14980	         break;
14981	      case SCIP_CONFIDENCELEVEL_MAX:
14982	         problimit = 0.975;
14983	         break;
14984	      default:
14985	         problimit = -1;
14986	         SCIPerrorMessage("Confidence level set to unknown value <%d>", (int)clevel);
14987	         SCIPABORT();
14988	         break;
14989	   }
14990	
14991	   return (probability >= problimit);
14992	}
14993	
14994	/** find the corresponding history entry if already existing, otherwise create new entry */
14995	static
14996	SCIP_RETCODE findValuehistoryEntry(
14997	   SCIP_VAR*             var,                /**< problem variable */
14998	   SCIP_Real             value,              /**< domain value, or SCIP_UNKNOWN */
14999	   BMS_BLKMEM*           blkmem,             /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15000	   SCIP_SET*             set,                /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15001	   SCIP_HISTORY**        history             /**< pointer to store the value based history, or NULL */
15002	   )
15003	{
15004	   assert(var != NULL);
15005	   assert(blkmem != NULL);
15006	   assert(set != NULL);
15007	   assert(history != NULL);
15008	
15009	   (*history) = NULL;
15010	
15011	   if( var->valuehistory == NULL )
15012	   {
15013	      SCIP_CALL( SCIPvaluehistoryCreate(&var->valuehistory, blkmem) );
15014	   }
15015	
15016	   SCIP_CALL( SCIPvaluehistoryFind(var->valuehistory, blkmem, set, value, history) );
15017	
15018	   return SCIP_OKAY;
15019	}
15020	
15021	/** check if value based history should be used */
15022	static
15023	SCIP_Bool useValuehistory(
15024	   SCIP_VAR*             var,                /**< problem variable */
15025	   SCIP_Real             value,              /**< domain value, or SCIP_UNKNOWN */
15026	   SCIP_SET*             set                 /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15027	   )
15028	{
15029	   /* check if the domain value is unknown (not specific) */
15030	   if( value == SCIP_UNKNOWN ) /*lint !e777*/
15031	      return FALSE;
15032	
15033	   assert(set != NULL);
15034	
15035	   /* check if value based history should be collected */
15036	   if( !set->history_valuebased )
15037	      return FALSE;
15038	
15039	   /* value based history is not collected for binary variable since the standard history already contains all information */
15040	   if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
15041	      return FALSE;
15042	
15043	   /* value based history is not collected for continuous variables */
15044	   if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS )
15045	      return FALSE;
15046	
15047	   return TRUE;
15048	}
15049	
15050	/** increases VSIDS of the variable by the given weight */
15051	SCIP_RETCODE SCIPvarIncVSIDS(
15052	   SCIP_VAR*             var,                /**< problem variable */
15053	   BMS_BLKMEM*           blkmem,             /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15054	   SCIP_SET*             set,                /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15055	   SCIP_STAT*            stat,               /**< problem statistics */
15056	   SCIP_BRANCHDIR        dir,                /**< branching direction */
15057	   SCIP_Real             value,              /**< domain value, or SCIP_UNKNOWN */
15058	   SCIP_Real             weight              /**< weight of this update in VSIDS */
15059	   )
15060	{
15061	   assert(var != NULL);
15062	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15063	
15064	   /* check if history statistics should be collected for a variable */
15065	   if( !stat->collectvarhistory )
15066	      return SCIP_OKAY;
15067	
15068	   if( SCIPsetIsZero(set, weight) )
15069	      return SCIP_OKAY;
15070	
15071	   switch( SCIPvarGetStatus(var) )
15072	   {
15073	   case SCIP_VARSTATUS_ORIGINAL:
15074	      if( var->data.original.transvar == NULL )
15075	      {
15076	         SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
15077	         return SCIP_INVALIDDATA;
15078	      }
15079	      SCIP_CALL( SCIPvarIncVSIDS(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15080	      return SCIP_OKAY;
15081	
15082	   case SCIP_VARSTATUS_LOOSE:
15083	   case SCIP_VARSTATUS_COLUMN:
15084	   {
15085	      SCIPhistoryIncVSIDS(var->history, dir, weight);
15086	      SCIPhistoryIncVSIDS(var->historycrun, dir, weight);
15087	
15088	      if( useValuehistory(var, value, set) )
15089	      {
15090	         SCIP_HISTORY* history;
15091	
15092	         SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15093	         assert(history != NULL);
15094	
15095	         SCIPhistoryIncVSIDS(history, dir, weight);
15096	         SCIPsetDebugMsg(set, "variable (<%s> %s %g) + <%g> = <%g>\n", SCIPvarGetName(var), dir == SCIP_BRANCHDIR_UPWARDS ? ">=" : "<=",
15097	            value, weight, SCIPhistoryGetVSIDS(history, dir));
15098	      }
15099	
15100	      return SCIP_OKAY;
15101	   }
15102	   case SCIP_VARSTATUS_FIXED:
15103	      SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
15104	      return SCIP_INVALIDDATA;
15105	
15106	   case SCIP_VARSTATUS_AGGREGATED:
15107	      value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15108	
15109	      if( var->data.aggregate.scalar > 0.0 )
15110	      {
15111	         SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15112	      }
15113	      else
15114	      {
15115	         assert(var->data.aggregate.scalar < 0.0);
15116	         SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15117	      }
15118	      return SCIP_OKAY;
15119	
15120	   case SCIP_VARSTATUS_MULTAGGR:
15121	      SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
15122	      return SCIP_INVALIDDATA;
15123	
15124	   case SCIP_VARSTATUS_NEGATED:
15125	      value = 1.0 - value;
15126	
15127	      SCIP_CALL( SCIPvarIncVSIDS(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15128	      return SCIP_OKAY;
15129	
15130	   default:
15131	      SCIPerrorMessage("unknown variable status\n");
15132	      return SCIP_INVALIDDATA;
15133	   }
15134	}
15135	
15136	/** scales the VSIDS of the variable by the given scalar */
15137	SCIP_RETCODE SCIPvarScaleVSIDS(
15138	   SCIP_VAR*             var,                /**< problem variable */
15139	   SCIP_Real             scalar              /**< scalar to multiply the VSIDSs with */
15140	   )
15141	{
15142	   assert(var != NULL);
15143	
15144	   switch( SCIPvarGetStatus(var) )
15145	   {
15146	   case SCIP_VARSTATUS_ORIGINAL:
15147	      if( var->data.original.transvar == NULL )
15148	      {
15149	         SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
15150	         return SCIP_INVALIDDATA;
15151	      }
15152	      SCIP_CALL( SCIPvarScaleVSIDS(var->data.original.transvar, scalar) );
15153	      return SCIP_OKAY;
15154	
15155	   case SCIP_VARSTATUS_LOOSE:
15156	   case SCIP_VARSTATUS_COLUMN:
15157	   {
15158	      SCIPhistoryScaleVSIDS(var->history, scalar);
15159	      SCIPhistoryScaleVSIDS(var->historycrun, scalar);
15160	      SCIPvaluehistoryScaleVSIDS(var->valuehistory, scalar);
15161	
15162	      return SCIP_OKAY;
15163	   }
15164	   case SCIP_VARSTATUS_FIXED:
15165	      SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
15166	      return SCIP_INVALIDDATA;
15167	
15168	   case SCIP_VARSTATUS_AGGREGATED:
15169	      SCIP_CALL( SCIPvarScaleVSIDS(var->data.aggregate.var, scalar) );
15170	      return SCIP_OKAY;
15171	
15172	   case SCIP_VARSTATUS_MULTAGGR:
15173	      SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
15174	      return SCIP_INVALIDDATA;
15175	
15176	   case SCIP_VARSTATUS_NEGATED:
15177	      SCIP_CALL( SCIPvarScaleVSIDS(var->negatedvar, scalar) );
15178	      return SCIP_OKAY;
15179	
15180	   default:
15181	      SCIPerrorMessage("unknown variable status\n");
15182	      return SCIP_INVALIDDATA;
15183	   }
15184	}
15185	
15186	/** increases the number of active conflicts by one and the overall length of the variable by the given length */
15187	SCIP_RETCODE SCIPvarIncNActiveConflicts(
15188	   SCIP_VAR*             var,                /**< problem variable */
15189	   BMS_BLKMEM*           blkmem,             /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15190	   SCIP_SET*             set,                /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15191	   SCIP_STAT*            stat,               /**< problem statistics */
15192	   SCIP_BRANCHDIR        dir,                /**< branching direction */
15193	   SCIP_Real             value,              /**< domain value, or SCIP_UNKNOWN */
15194	   SCIP_Real             length              /**< length of the conflict */
15195	   )
15196	{
15197	   assert(var != NULL);
15198	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15199	
15200	   /* check if history statistics should be collected for a variable */
15201	   if( !stat->collectvarhistory )
15202	      return SCIP_OKAY;
15203	
15204	   switch( SCIPvarGetStatus(var) )
15205	   {
15206	   case SCIP_VARSTATUS_ORIGINAL:
15207	      if( var->data.original.transvar == NULL )
15208	      {
15209	         SCIPerrorMessage("cannot update conflict score of original untransformed variable\n");
15210	         return SCIP_INVALIDDATA;
15211	      }
15212	      SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.original.transvar, blkmem, set, stat, dir, value, length) );
15213	      return SCIP_OKAY;
15214	
15215	   case SCIP_VARSTATUS_LOOSE:
15216	   case SCIP_VARSTATUS_COLUMN:
15217	   {
15218	      SCIPhistoryIncNActiveConflicts(var->history, dir, length);
15219	      SCIPhistoryIncNActiveConflicts(var->historycrun, dir, length);
15220	
15221	      if( useValuehistory(var, value, set) )
15222	      {
15223	         SCIP_HISTORY* history;
15224	
15225	         SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15226	         assert(history != NULL);
15227	
15228	         SCIPhistoryIncNActiveConflicts(history, dir, length);
15229	      }
15230	
15231	      return SCIP_OKAY;
15232	   }
15233	   case SCIP_VARSTATUS_FIXED:
15234	      SCIPerrorMessage("cannot update conflict score of a fixed variable\n");
15235	      return SCIP_INVALIDDATA;
15236	
15237	   case SCIP_VARSTATUS_AGGREGATED:
15238	      value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15239	
15240	      if( var->data.aggregate.scalar > 0.0 )
15241	      {
15242	         SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, dir, value, length) );
15243	      }
15244	      else
15245	      {
15246	         assert(var->data.aggregate.scalar < 0.0);
15247	         SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
15248	      }
15249	      return SCIP_OKAY;
15250	
15251	   case SCIP_VARSTATUS_MULTAGGR:
15252	      SCIPerrorMessage("cannot update conflict score of a multi-aggregated variable\n");
15253	      return SCIP_INVALIDDATA;
15254	
15255	   case SCIP_VARSTATUS_NEGATED:
15256	      value = 1.0 - value;
15257	
15258	      SCIP_CALL( SCIPvarIncNActiveConflicts(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
15259	      return SCIP_OKAY;
15260	
15261	   default:
15262	      SCIPerrorMessage("unknown variable status\n");
15263	      return SCIP_INVALIDDATA;
15264	   }
15265	}
15266	
15267	/** gets the number of active conflicts containing this variable in given direction */
15268	SCIP_Longint SCIPvarGetNActiveConflicts(
15269	   SCIP_VAR*             var,                /**< problem variable */
15270	   SCIP_STAT*            stat,               /**< problem statistics */
15271	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
15272	   )
15273	{
15274	   assert(var != NULL);
15275	   assert(stat != NULL);
15276	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15277	
15278	   switch( SCIPvarGetStatus(var) )
15279	   {
15280	   case SCIP_VARSTATUS_ORIGINAL:
15281	      if( var->data.original.transvar == NULL )
15282	         return 0;
15283	      else
15284	         return SCIPvarGetNActiveConflicts(var->data.original.transvar, stat, dir);
15285	
15286	   case SCIP_VARSTATUS_LOOSE:
15287	   case SCIP_VARSTATUS_COLUMN:
15288	      return SCIPhistoryGetNActiveConflicts(var->history, dir);
15289	
15290	   case SCIP_VARSTATUS_FIXED:
15291	      return 0;
15292	
15293	   case SCIP_VARSTATUS_AGGREGATED:
15294	      if( var->data.aggregate.scalar > 0.0 )
15295	         return SCIPvarGetNActiveConflicts(var->data.aggregate.var, stat, dir);
15296	      else
15297	         return SCIPvarGetNActiveConflicts(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15298	
15299	   case SCIP_VARSTATUS_MULTAGGR:
15300	      return 0;
15301	
15302	   case SCIP_VARSTATUS_NEGATED:
15303	      return SCIPvarGetNActiveConflicts(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15304	
15305	   default:
15306	      SCIPerrorMessage("unknown variable status\n");
15307	      SCIPABORT();
15308	      return 0; /*lint !e527*/
15309	   }
15310	}
15311	
15312	/** gets the number of active conflicts containing this variable in given direction
15313	 *  in the current run
15314	 */
15315	SCIP_Longint SCIPvarGetNActiveConflictsCurrentRun(
15316	   SCIP_VAR*             var,                /**< problem variable */
15317	   SCIP_STAT*            stat,               /**< problem statistics */
15318	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
15319	   )
15320	{
15321	   assert(var != NULL);
15322	   assert(stat != NULL);
15323	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15324	
15325	   switch( SCIPvarGetStatus(var) )
15326	   {
15327	   case SCIP_VARSTATUS_ORIGINAL:
15328	      if( var->data.original.transvar == NULL )
15329	         return 0;
15330	      else
15331	         return SCIPvarGetNActiveConflictsCurrentRun(var->data.original.transvar, stat, dir);
15332	
15333	   case SCIP_VARSTATUS_LOOSE:
15334	   case SCIP_VARSTATUS_COLUMN:
15335	      return SCIPhistoryGetNActiveConflicts(var->historycrun, dir);
15336	
15337	   case SCIP_VARSTATUS_FIXED:
15338	      return 0;
15339	
15340	   case SCIP_VARSTATUS_AGGREGATED:
15341	      if( var->data.aggregate.scalar > 0.0 )
15342	         return SCIPvarGetNActiveConflictsCurrentRun(var->data.aggregate.var, stat, dir);
15343	      else
15344	         return SCIPvarGetNActiveConflictsCurrentRun(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15345	
15346	   case SCIP_VARSTATUS_MULTAGGR:
15347	      return 0;
15348	
15349	   case SCIP_VARSTATUS_NEGATED:
15350	      return SCIPvarGetNActiveConflictsCurrentRun(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15351	
15352	   default:
15353	      SCIPerrorMessage("unknown variable status\n");
15354	      SCIPABORT();
15355	      return 0; /*lint !e527*/
15356	   }
15357	}
15358	
15359	/** gets the average conflict length in given direction due to branching on the variable */
15360	SCIP_Real SCIPvarGetAvgConflictlength(
15361	   SCIP_VAR*             var,                /**< problem variable */
15362	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
15363	   )
15364	{
15365	   assert(var != NULL);
15366	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15367	
15368	   switch( SCIPvarGetStatus(var) )
15369	   {
15370	   case SCIP_VARSTATUS_ORIGINAL:
15371	      if( var->data.original.transvar == NULL )
15372	         return 0.0;
15373	      else
15374	         return SCIPvarGetAvgConflictlength(var->data.original.transvar, dir);
15375	
15376	   case SCIP_VARSTATUS_LOOSE:
15377	   case SCIP_VARSTATUS_COLUMN:
15378	         return SCIPhistoryGetAvgConflictlength(var->history, dir);
15379	   case SCIP_VARSTATUS_FIXED:
15380	      return 0.0;
15381	
15382	   case SCIP_VARSTATUS_AGGREGATED:
15383	      if( var->data.aggregate.scalar > 0.0 )
15384	         return SCIPvarGetAvgConflictlength(var->data.aggregate.var, dir);
15385	      else
15386	         return SCIPvarGetAvgConflictlength(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
15387	
15388	   case SCIP_VARSTATUS_MULTAGGR:
15389	      return 0.0;
15390	
15391	   case SCIP_VARSTATUS_NEGATED:
15392	      return SCIPvarGetAvgConflictlength(var->negatedvar, SCIPbranchdirOpposite(dir));
15393	
15394	   default:
15395	      SCIPerrorMessage("unknown variable status\n");
15396	      SCIPABORT();
15397	      return 0.0; /*lint !e527*/
15398	   }
15399	}
15400	
15401	/**  gets the average conflict length in given direction due to branching on the variable
15402	 *   in the current run
15403	 */
15404	SCIP_Real SCIPvarGetAvgConflictlengthCurrentRun(
15405	   SCIP_VAR*             var,                /**< problem variable */
15406	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
15407	   )
15408	{
15409	   assert(var != NULL);
15410	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15411	
15412	   switch( SCIPvarGetStatus(var) )
15413	   {
15414	   case SCIP_VARSTATUS_ORIGINAL:
15415	      if( var->data.original.transvar == NULL )
15416	         return 0.0;
15417	      else
15418	         return SCIPvarGetAvgConflictlengthCurrentRun(var->data.original.transvar, dir);
15419	
15420	   case SCIP_VARSTATUS_LOOSE:
15421	   case SCIP_VARSTATUS_COLUMN:
15422	      return  SCIPhistoryGetAvgConflictlength(var->historycrun, dir);
15423	
15424	   case SCIP_VARSTATUS_FIXED:
15425	      return 0.0;
15426	
15427	   case SCIP_VARSTATUS_AGGREGATED:
15428	      if( var->data.aggregate.scalar > 0.0 )
15429	         return SCIPvarGetAvgConflictlengthCurrentRun(var->data.aggregate.var, dir);
15430	      else
15431	         return SCIPvarGetAvgConflictlengthCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
15432	
15433	   case SCIP_VARSTATUS_MULTAGGR:
15434	      return 0.0;
15435	
15436	   case SCIP_VARSTATUS_NEGATED:
15437	      return SCIPvarGetAvgConflictlengthCurrentRun(var->negatedvar, SCIPbranchdirOpposite(dir));
15438	
15439	   default:
15440	      SCIPerrorMessage("unknown variable status\n");
15441	      SCIPABORT();
15442	      return 0.0; /*lint !e527*/
15443	   }
15444	}
15445	
15446	/** increases the number of branchings counter of the variable */
15447	SCIP_RETCODE SCIPvarIncNBranchings(
15448	   SCIP_VAR*             var,                /**< problem variable */
15449	   BMS_BLKMEM*           blkmem,             /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15450	   SCIP_SET*             set,                /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15451	   SCIP_STAT*            stat,               /**< problem statistics */
15452	   SCIP_BRANCHDIR        dir,                /**< branching direction (downwards, or upwards) */
15453	   SCIP_Real             value,              /**< domain value, or SCIP_UNKNOWN */
15454	   int                   depth               /**< depth at which the bound change took place */
15455	   )
15456	{
15457	   assert(var != NULL);
15458	   assert(stat != NULL);
15459	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15460	
15461	   /* check if history statistics should be collected for a variable */
15462	   if( !stat->collectvarhistory )
15463	      return SCIP_OKAY;
15464	
15465	   switch( SCIPvarGetStatus(var) )
15466	   {
15467	   case SCIP_VARSTATUS_ORIGINAL:
15468	      if( var->data.original.transvar == NULL )
15469	      {
15470	         SCIPerrorMessage("cannot update branching counter of original untransformed variable\n");
15471	         return SCIP_INVALIDDATA;
15472	      }
15473	      SCIP_CALL( SCIPvarIncNBranchings(var->data.original.transvar, blkmem, set, stat, dir, value, depth) );
15474	      return SCIP_OKAY;
15475	
15476	   case SCIP_VARSTATUS_LOOSE:
15477	   case SCIP_VARSTATUS_COLUMN:
15478	   {
15479	      SCIPhistoryIncNBranchings(var->history, dir, depth);
15480	      SCIPhistoryIncNBranchings(var->historycrun, dir, depth);
15481	      SCIPhistoryIncNBranchings(stat->glbhistory, dir, depth);
15482	      SCIPhistoryIncNBranchings(stat->glbhistorycrun, dir, depth);
15483	
15484	      if( useValuehistory(var, value, set) )
15485	      {
15486	         SCIP_HISTORY* history;
15487	
15488	         SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15489	         assert(history != NULL);
15490	
15491	         SCIPhistoryIncNBranchings(history, dir, depth);
15492	      }
15493	
15494	      return SCIP_OKAY;
15495	   }
15496	   case SCIP_VARSTATUS_FIXED:
15497	      SCIPerrorMessage("cannot update branching counter of a fixed variable\n");
15498	      return SCIP_INVALIDDATA;
15499	
15500	   case SCIP_VARSTATUS_AGGREGATED:
15501	      value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15502	
15503	      if( var->data.aggregate.scalar > 0.0 )
15504	      {
15505	         SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, dir, value, depth) );
15506	      }
15507	      else
15508	      {
15509	         assert(var->data.aggregate.scalar < 0.0);
15510	         SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
15511	      }
15512	      return SCIP_OKAY;
15513	
15514	   case SCIP_VARSTATUS_MULTAGGR:
15515	      SCIPerrorMessage("cannot update branching counter of a multi-aggregated variable\n");
15516	      return SCIP_INVALIDDATA;
15517	
15518	   case SCIP_VARSTATUS_NEGATED:
15519	      value = 1.0 - value;
15520	
15521	      SCIP_CALL( SCIPvarIncNBranchings(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
15522	      return SCIP_OKAY;
15523	
15524	   default:
15525	      SCIPerrorMessage("unknown variable status\n");
15526	      return SCIP_INVALIDDATA;
15527	   }
15528	}
15529	
15530	/** increases the inference sum of the variable by the given weight */
15531	SCIP_RETCODE SCIPvarIncInferenceSum(
15532	   SCIP_VAR*             var,                /**< problem variable */
15533	   BMS_BLKMEM*           blkmem,             /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15534	   SCIP_SET*             set,                /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15535	   SCIP_STAT*            stat,               /**< problem statistics */
15536	   SCIP_BRANCHDIR        dir,                /**< branching direction (downwards, or upwards) */
15537	   SCIP_Real             value,              /**< domain value, or SCIP_UNKNOWN */
15538	   SCIP_Real             weight              /**< weight of this update in inference score */
15539	   )
15540	{
15541	   assert(var != NULL);
15542	   assert(stat != NULL);
15543	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15544	
15545	   /* check if history statistics should be collected for a variable */
15546	   if( !stat->collectvarhistory )
15547	      return SCIP_OKAY;
15548	
15549	   switch( SCIPvarGetStatus(var) )
15550	   {
15551	   case SCIP_VARSTATUS_ORIGINAL:
15552	      if( var->data.original.transvar == NULL )
15553	      {
15554	         SCIPerrorMessage("cannot update inference counter of original untransformed variable\n");
15555	         return SCIP_INVALIDDATA;
15556	      }
15557	      SCIP_CALL( SCIPvarIncInferenceSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15558	      return SCIP_OKAY;
15559	
15560	   case SCIP_VARSTATUS_LOOSE:
15561	   case SCIP_VARSTATUS_COLUMN:
15562	   {
15563	      SCIPhistoryIncInferenceSum(var->history, dir, weight);
15564	      SCIPhistoryIncInferenceSum(var->historycrun, dir, weight);
15565	      SCIPhistoryIncInferenceSum(stat->glbhistory, dir, weight);
15566	      SCIPhistoryIncInferenceSum(stat->glbhistorycrun, dir, weight);
15567	
15568	      if( useValuehistory(var, value, set) )
15569	      {
15570	         SCIP_HISTORY* history;
15571	
15572	         SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15573	         assert(history != NULL);
15574	
15575	         SCIPhistoryIncInferenceSum(history, dir, weight);
15576	      }
15577	
15578	      return SCIP_OKAY;
15579	   }
15580	   case SCIP_VARSTATUS_FIXED:
15581	      SCIPerrorMessage("cannot update inference counter of a fixed variable\n");
15582	      return SCIP_INVALIDDATA;
15583	
15584	   case SCIP_VARSTATUS_AGGREGATED:
15585	      value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15586	
15587	      if( var->data.aggregate.scalar > 0.0 )
15588	      {
15589	         SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15590	      }
15591	      else
15592	      {
15593	         assert(var->data.aggregate.scalar < 0.0);
15594	         SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15595	      }
15596	      return SCIP_OKAY;
15597	
15598	   case SCIP_VARSTATUS_MULTAGGR:
15599	      SCIPerrorMessage("cannot update inference counter of a multi-aggregated variable\n");
15600	      return SCIP_INVALIDDATA;
15601	
15602	   case SCIP_VARSTATUS_NEGATED:
15603	      value = 1.0 - value;
15604	
15605	      SCIP_CALL( SCIPvarIncInferenceSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15606	      return SCIP_OKAY;
15607	
15608	   default:
15609	      SCIPerrorMessage("unknown variable status\n");
15610	      return SCIP_INVALIDDATA;
15611	   }
15612	}
15613	
15614	/** increases the cutoff sum of the variable by the given weight */
15615	SCIP_RETCODE SCIPvarIncCutoffSum(
15616	   SCIP_VAR*             var,                /**< problem variable */
15617	   BMS_BLKMEM*           blkmem,             /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15618	   SCIP_SET*             set,                /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15619	   SCIP_STAT*            stat,               /**< problem statistics */
15620	   SCIP_BRANCHDIR        dir,                /**< branching direction (downwards, or upwards) */
15621	   SCIP_Real             value,              /**< domain value, or SCIP_UNKNOWN */
15622	   SCIP_Real             weight              /**< weight of this update in cutoff score */
15623	   )
15624	{
15625	   assert(var != NULL);
15626	   assert(stat != NULL);
15627	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15628	
15629	   /* check if history statistics should be collected for a variable */
15630	   if( !stat->collectvarhistory )
15631	      return SCIP_OKAY;
15632	
15633	   switch( SCIPvarGetStatus(var) )
15634	   {
15635	   case SCIP_VARSTATUS_ORIGINAL:
15636	      if( var->data.original.transvar == NULL )
15637	      {
15638	         SCIPerrorMessage("cannot update cutoff sum of original untransformed variable\n");
15639	         return SCIP_INVALIDDATA;
15640	      }
15641	      SCIP_CALL( SCIPvarIncCutoffSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15642	      return SCIP_OKAY;
15643	
15644	   case SCIP_VARSTATUS_LOOSE:
15645	   case SCIP_VARSTATUS_COLUMN:
15646	   {
15647	      SCIPhistoryIncCutoffSum(var->history, dir, weight);
15648	      SCIPhistoryIncCutoffSum(var->historycrun, dir, weight);
15649	      SCIPhistoryIncCutoffSum(stat->glbhistory, dir, weight);
15650	      SCIPhistoryIncCutoffSum(stat->glbhistorycrun, dir, weight);
15651	
15652	      if( useValuehistory(var, value, set) )
15653	      {
15654	         SCIP_HISTORY* history;
15655	
15656	         SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15657	         assert(history != NULL);
15658	
15659	         SCIPhistoryIncCutoffSum(history, dir, weight);
15660	      }
15661	
15662	      return SCIP_OKAY;
15663	   }
15664	   case SCIP_VARSTATUS_FIXED:
15665	      SCIPerrorMessage("cannot update cutoff sum of a fixed variable\n");
15666	      return SCIP_INVALIDDATA;
15667	
15668	   case SCIP_VARSTATUS_AGGREGATED:
15669	      value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15670	
15671	      if( var->data.aggregate.scalar > 0.0 )
15672	      {
15673	         SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15674	      }
15675	      else
15676	      {
15677	         assert(var->data.aggregate.scalar < 0.0);
15678	         SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15679	      }
15680	      return SCIP_OKAY;
15681	
15682	   case SCIP_VARSTATUS_MULTAGGR:
15683	      SCIPerrorMessage("cannot update cutoff sum of a multi-aggregated variable\n");
15684	      return SCIP_INVALIDDATA;
15685	
15686	   case SCIP_VARSTATUS_NEGATED:
15687	      value = 1.0 - value;
15688	
15689	      SCIP_CALL( SCIPvarIncCutoffSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15690	      return SCIP_OKAY;
15691	
15692	   default:
15693	      SCIPerrorMessage("unknown variable status\n");
15694	      return SCIP_INVALIDDATA;
15695	   }
15696	}
15697	
15698	/** returns the number of times, a bound of the variable was changed in given direction due to branching */
15699	SCIP_Longint SCIPvarGetNBranchings(
15700	   SCIP_VAR*             var,                /**< problem variable */
15701	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
15702	   )
15703	{
15704	   assert(var != NULL);
15705	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15706	
15707	   switch( SCIPvarGetStatus(var) )
15708	   {
15709	   case SCIP_VARSTATUS_ORIGINAL:
15710	      if( var->data.original.transvar == NULL )
15711	         return 0;
15712	      else
15713	         return SCIPvarGetNBranchings(var->data.original.transvar, dir);
15714	
15715	   case SCIP_VARSTATUS_LOOSE:
15716	   case SCIP_VARSTATUS_COLUMN:
15717	      return SCIPhistoryGetNBranchings(var->history, dir);
15718	
15719	   case SCIP_VARSTATUS_FIXED:
15720	      return 0;
15721	
15722	   case SCIP_VARSTATUS_AGGREGATED:
15723	      if( var->data.aggregate.scalar > 0.0 )
15724	         return SCIPvarGetNBranchings(var->data.aggregate.var, dir);
15725	      else
15726	         return SCIPvarGetNBranchings(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
15727	
15728	   case SCIP_VARSTATUS_MULTAGGR:
15729	      return 0;
15730	
15731	   case SCIP_VARSTATUS_NEGATED:
15732	      return SCIPvarGetNBranchings(var->negatedvar, SCIPbranchdirOpposite(dir));
15733	
15734	   default:
15735	      SCIPerrorMessage("unknown variable status\n");
15736	      SCIPABORT();
15737	      return 0; /*lint !e527*/
15738	   }
15739	}
15740	
15741	/** returns the number of times, a bound of the variable was changed in given direction due to branching 
15742	 *  in the current run
15743	 */
15744	SCIP_Longint SCIPvarGetNBranchingsCurrentRun(
15745	   SCIP_VAR*             var,                /**< problem variable */
15746	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
15747	   )
15748	{
15749	   assert(var != NULL);
15750	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15751	
15752	   switch( SCIPvarGetStatus(var) )
15753	   {
15754	   case SCIP_VARSTATUS_ORIGINAL:
15755	      if( var->data.original.transvar == NULL )
15756	         return 0;
15757	      else
15758	         return SCIPvarGetNBranchingsCurrentRun(var->data.original.transvar, dir);
15759	
15760	   case SCIP_VARSTATUS_LOOSE:
15761	   case SCIP_VARSTATUS_COLUMN:
15762	      return SCIPhistoryGetNBranchings(var->historycrun, dir);
15763	
15764	   case SCIP_VARSTATUS_FIXED:
15765	      return 0;
15766	
15767	   case SCIP_VARSTATUS_AGGREGATED:
15768	      if( var->data.aggregate.scalar > 0.0 )
15769	         return SCIPvarGetNBranchingsCurrentRun(var->data.aggregate.var, dir);
15770	      else
15771	         return SCIPvarGetNBranchingsCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
15772	
15773	   case SCIP_VARSTATUS_MULTAGGR:
15774	      return 0;
15775	
15776	   case SCIP_VARSTATUS_NEGATED:
15777	      return SCIPvarGetNBranchingsCurrentRun(var->negatedvar, SCIPbranchdirOpposite(dir));
15778	
15779	   default:
15780	      SCIPerrorMessage("unknown variable status\n");
15781	      SCIPABORT();
15782	      return 0; /*lint !e527*/
15783	   }
15784	}
15785	
15786	/** returns the average depth of bound changes in given direction due to branching on the variable */
15787	SCIP_Real SCIPvarGetAvgBranchdepth(
15788	   SCIP_VAR*             var,                /**< problem variable */
15789	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
15790	   )
15791	{
15792	   assert(var != NULL);
15793	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15794	
15795	   switch( SCIPvarGetStatus(var) )
15796	   {
15797	   case SCIP_VARSTATUS_ORIGINAL:
15798	      if( var->data.original.transvar == NULL )
15799	         return 0.0;
15800	      else
15801	         return SCIPvarGetAvgBranchdepth(var->data.original.transvar, dir);
15802	
15803	   case SCIP_VARSTATUS_LOOSE:
15804	   case SCIP_VARSTATUS_COLUMN:
15805	      return  SCIPhistoryGetAvgBranchdepth(var->history, dir);
15806	
15807	   case SCIP_VARSTATUS_FIXED:
15808	      return 0.0;
15809	
15810	   case SCIP_VARSTATUS_AGGREGATED:
15811	      if( var->data.aggregate.scalar > 0.0 )
15812	         return SCIPvarGetAvgBranchdepth(var->data.aggregate.var, dir);
15813	      else
15814	         return SCIPvarGetAvgBranchdepth(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
15815	
15816	   case SCIP_VARSTATUS_MULTAGGR:
15817	      return 0.0;
15818	
15819	   case SCIP_VARSTATUS_NEGATED:
15820	      return SCIPvarGetAvgBranchdepth(var->negatedvar, SCIPbranchdirOpposite(dir));
15821	
15822	   default:
15823	      SCIPerrorMessage("unknown variable status\n");
15824	      SCIPABORT();
15825	      return 0.0; /*lint !e527*/
15826	   }
15827	}
15828	
15829	/** returns the average depth of bound changes in given direction due to branching on the variable
15830	 *  in the current run
15831	 */
15832	SCIP_Real SCIPvarGetAvgBranchdepthCurrentRun(
15833	   SCIP_VAR*             var,                /**< problem variable */
15834	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
15835	   )
15836	{
15837	   assert(var != NULL);
15838	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15839	
15840	   switch( SCIPvarGetStatus(var) )
15841	   {
15842	   case SCIP_VARSTATUS_ORIGINAL:
15843	      if( var->data.original.transvar == NULL )
15844	         return 0.0;
15845	      else
15846	         return SCIPvarGetAvgBranchdepthCurrentRun(var->data.original.transvar, dir);
15847	
15848	   case SCIP_VARSTATUS_LOOSE:
15849	   case SCIP_VARSTATUS_COLUMN:
15850	      return  SCIPhistoryGetAvgBranchdepth(var->historycrun, dir);
15851	
15852	   case SCIP_VARSTATUS_FIXED:
15853	      return 0.0;
15854	
15855	   case SCIP_VARSTATUS_AGGREGATED:
15856	      if( var->data.aggregate.scalar > 0.0 )
15857	         return SCIPvarGetAvgBranchdepthCurrentRun(var->data.aggregate.var, dir);
15858	      else
15859	         return SCIPvarGetAvgBranchdepthCurrentRun(var->data.aggregate.var,
15860	            dir == SCIP_BRANCHDIR_DOWNWARDS ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
15861	
15862	   case SCIP_VARSTATUS_MULTAGGR:
15863	      return 0.0;
15864	
15865	   case SCIP_VARSTATUS_NEGATED:
15866	      return SCIPvarGetAvgBranchdepthCurrentRun(var->negatedvar,
15867	         dir == SCIP_BRANCHDIR_DOWNWARDS ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
15868	
15869	   default:
15870	      SCIPerrorMessage("unknown variable status\n");
15871	      SCIPABORT();
15872	      return 0.0; /*lint !e527*/
15873	   }
15874	}
15875	
15876	/** returns the variable's VSIDS score */
15877	SCIP_Real SCIPvarGetVSIDS_rec(
15878	   SCIP_VAR*             var,                /**< problem variable */
15879	   SCIP_STAT*            stat,               /**< problem statistics */
15880	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
15881	   )
15882	{
15883	   assert(var != NULL);
15884	   assert(stat != NULL);
15885	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15886	
15887	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN )
15888	      return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15889	
15890	   switch( SCIPvarGetStatus(var) )
15891	   {
15892	   case SCIP_VARSTATUS_ORIGINAL:
15893	      if( var->data.original.transvar == NULL )
15894	         return 0.0;
15895	      else
15896	         return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15897	
15898	   case SCIP_VARSTATUS_LOOSE:
15899	   case SCIP_VARSTATUS_COLUMN:
15900	      assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE); /* column case already handled in if condition above */
15901	      return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
15902	
15903	   case SCIP_VARSTATUS_FIXED:
15904	      return 0.0;
15905	
15906	   case SCIP_VARSTATUS_AGGREGATED:
15907	      if( var->data.aggregate.scalar > 0.0 )
15908	         return SCIPvarGetVSIDS(var->data.aggregate.var, stat, dir);
15909	      else
15910	         /* coverity[overrun-local] */
15911	         return SCIPvarGetVSIDS(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15912	
15913	   case SCIP_VARSTATUS_MULTAGGR:
15914	      return 0.0;
15915	
15916	   case SCIP_VARSTATUS_NEGATED:
15917	      /* coverity[overrun-local] */
15918	      return SCIPvarGetVSIDS(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15919	
15920	   default:
15921	      SCIPerrorMessage("unknown variable status\n");
15922	      SCIPABORT();
15923	      return 0.0; /*lint !e527*/
15924	   }
15925	}
15926	
15927	/** returns the variable's VSIDS score only using conflicts of the current run */
15928	SCIP_Real SCIPvarGetVSIDSCurrentRun(
15929	   SCIP_VAR*             var,                /**< problem variable */
15930	   SCIP_STAT*            stat,               /**< problem statistics */
15931	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
15932	   )
15933	{
15934	   assert(var != NULL);
15935	   assert(stat != NULL);
15936	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15937	
15938	   if( dir != SCIP_BRANCHDIR_DOWNWARDS && dir != SCIP_BRANCHDIR_UPWARDS )
15939	   {
15940	      SCIPerrorMessage("invalid branching direction %d when asking for VSIDS value\n", dir);
15941	      return SCIP_INVALID;
15942	   }
15943	
15944	   switch( SCIPvarGetStatus(var) )
15945	   {
15946	   case SCIP_VARSTATUS_ORIGINAL:
15947	      if( var->data.original.transvar == NULL )
15948	         return 0.0;
15949	      else
15950	         return SCIPvarGetVSIDSCurrentRun(var->data.original.transvar, stat, dir);
15951	
15952	   case SCIP_VARSTATUS_LOOSE:
15953	   case SCIP_VARSTATUS_COLUMN:
15954	      return SCIPhistoryGetVSIDS(var->historycrun, dir)/stat->vsidsweight;
15955	
15956	   case SCIP_VARSTATUS_FIXED:
15957	      return 0.0;
15958	
15959	   case SCIP_VARSTATUS_AGGREGATED:
15960	      if( var->data.aggregate.scalar > 0.0 )
15961	         return SCIPvarGetVSIDSCurrentRun(var->data.aggregate.var, stat, dir);
15962	      else
15963	         return SCIPvarGetVSIDSCurrentRun(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15964	
15965	   case SCIP_VARSTATUS_MULTAGGR:
15966	      return 0.0;
15967	
15968	   case SCIP_VARSTATUS_NEGATED:
15969	      return SCIPvarGetVSIDSCurrentRun(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15970	
15971	   default:
15972	      SCIPerrorMessage("unknown variable status\n");
15973	      SCIPABORT();
15974	      return 0.0; /*lint !e527*/
15975	   }
15976	}
15977	
15978	/** returns the number of inferences branching on this variable in given direction triggered */
15979	SCIP_Real SCIPvarGetInferenceSum(
15980	   SCIP_VAR*             var,                /**< problem variable */
15981	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
15982	   )
15983	{
15984	   assert(var != NULL);
15985	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15986	
15987	   switch( SCIPvarGetStatus(var) )
15988	   {
15989	   case SCIP_VARSTATUS_ORIGINAL:
15990	      if( var->data.original.transvar == NULL )
15991	         return 0.0;
15992	      else
15993	         return SCIPvarGetInferenceSum(var->data.original.transvar, dir);
15994	
15995	   case SCIP_VARSTATUS_LOOSE:
15996	   case SCIP_VARSTATUS_COLUMN:
15997	      return SCIPhistoryGetInferenceSum(var->history, dir);
15998	
15999	   case SCIP_VARSTATUS_FIXED:
16000	      return 0.0;
16001	
16002	   case SCIP_VARSTATUS_AGGREGATED:
16003	      if( var->data.aggregate.scalar > 0.0 )
16004	         return SCIPvarGetInferenceSum(var->data.aggregate.var, dir);
16005	      else
16006	         return SCIPvarGetInferenceSum(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
16007	
16008	   case SCIP_VARSTATUS_MULTAGGR:
16009	      return 0.0;
16010	
16011	   case SCIP_VARSTATUS_NEGATED:
16012	      return SCIPvarGetInferenceSum(var->negatedvar, SCIPbranchdirOpposite(dir));
16013	
16014	   default:
16015	      SCIPerrorMessage("unknown variable status\n");
16016	      SCIPABORT();
16017	      return 0.0; /*lint !e527*/
16018	   }
16019	}
16020	
16021	/** returns the number of inferences branching on this variable in given direction triggered
16022	 *  in the current run
16023	 */
16024	SCIP_Real SCIPvarGetInferenceSumCurrentRun(
16025	   SCIP_VAR*             var,                /**< problem variable */
16026	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
16027	   )
16028	{
16029	   assert(var != NULL);
16030	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16031	
16032	   switch( SCIPvarGetStatus(var) )
16033	   {
16034	   case SCIP_VARSTATUS_ORIGINAL:
16035	      if( var->data.original.transvar == NULL )
16036	         return 0.0;
16037	      else
16038	         return SCIPvarGetInferenceSumCurrentRun(var->data.original.transvar, dir);
16039	
16040	   case SCIP_VARSTATUS_LOOSE:
16041	   case SCIP_VARSTATUS_COLUMN:
16042	      return SCIPhistoryGetInferenceSum(var->historycrun, dir);
16043	
16044	   case SCIP_VARSTATUS_FIXED:
16045	      return 0.0;
16046	
16047	   case SCIP_VARSTATUS_AGGREGATED:
16048	      if( var->data.aggregate.scalar > 0.0 )
16049	         return SCIPvarGetInferenceSumCurrentRun(var->data.aggregate.var, dir);
16050	      else
16051	         return SCIPvarGetInferenceSumCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
16052	
16053	   case SCIP_VARSTATUS_MULTAGGR:
16054	      return 0.0;
16055	
16056	   case SCIP_VARSTATUS_NEGATED:
16057	      return SCIPvarGetInferenceSumCurrentRun(var->negatedvar, SCIPbranchdirOpposite(dir));
16058	
16059	   default:
16060	      SCIPerrorMessage("unknown variable status\n");
16061	      SCIPABORT();
16062	      return 0.0; /*lint !e527*/
16063	   }
16064	}
16065	
16066	/** returns the average number of inferences found after branching on the variable in given direction */
16067	SCIP_Real SCIPvarGetAvgInferences(
16068	   SCIP_VAR*             var,                /**< problem variable */
16069	   SCIP_STAT*            stat,               /**< problem statistics */
16070	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
16071	   )
16072	{
16073	   assert(var != NULL);
16074	   assert(stat != NULL);
16075	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16076	
16077	   switch( SCIPvarGetStatus(var) )
16078	   {
16079	   case SCIP_VARSTATUS_ORIGINAL:
16080	      if( var->data.original.transvar == NULL )
16081	         return SCIPhistoryGetAvgInferences(stat->glbhistory, dir);
16082	      else
16083	         return SCIPvarGetAvgInferences(var->data.original.transvar, stat, dir);
16084	
16085	   case SCIP_VARSTATUS_LOOSE:
16086	   case SCIP_VARSTATUS_COLUMN:
16087	      if( SCIPhistoryGetNBranchings(var->history, dir) > 0 )
16088	         return SCIPhistoryGetAvgInferences(var->history, dir);
16089	      else
16090	      {
16091	         int nimpls;
16092	         int ncliques;
16093	
16094	         nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
16095	         ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
16096	         return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistory, dir);  /*lint !e790*/
16097	      }
16098	
16099	   case SCIP_VARSTATUS_FIXED:
16100	      return 0.0;
16101	
16102	   case SCIP_VARSTATUS_AGGREGATED:
16103	      if( var->data.aggregate.scalar > 0.0 )
16104	         return SCIPvarGetAvgInferences(var->data.aggregate.var, stat, dir);
16105	      else
16106	         return SCIPvarGetAvgInferences(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
16107	
16108	   case SCIP_VARSTATUS_MULTAGGR:
16109	      return 0.0;
16110	
16111	   case SCIP_VARSTATUS_NEGATED:
16112	      return SCIPvarGetAvgInferences(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
16113	
16114	   default:
16115	      SCIPerrorMessage("unknown variable status\n");
16116	      SCIPABORT();
16117	      return 0.0; /*lint !e527*/
16118	   }
16119	}
16120	
16121	/** returns the average number of inferences found after branching on the variable in given direction
16122	 *  in the current run
16123	 */
16124	SCIP_Real SCIPvarGetAvgInferencesCurrentRun(
16125	   SCIP_VAR*             var,                /**< problem variable */
16126	   SCIP_STAT*            stat,               /**< problem statistics */
16127	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
16128	   )
16129	{
16130	   assert(var != NULL);
16131	   assert(stat != NULL);
16132	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16133	
16134	   switch( SCIPvarGetStatus(var) )
16135	   {
16136	   case SCIP_VARSTATUS_ORIGINAL:
16137	      if( var->data.original.transvar == NULL )
16138	         return SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir);
16139	      else
16140	         return SCIPvarGetAvgInferencesCurrentRun(var->data.original.transvar, stat, dir);
16141	
16142	   case SCIP_VARSTATUS_LOOSE:
16143	   case SCIP_VARSTATUS_COLUMN:
16144	      if( SCIPhistoryGetNBranchings(var->historycrun, dir) > 0 )
16145	         return SCIPhistoryGetAvgInferences(var->historycrun, dir);
16146	      else
16147	      {
16148	         int nimpls;
16149	         int ncliques;
16150	
16151	         nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
16152	         ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
16153	         return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir);  /*lint !e790*/
16154	      }
16155	
16156	   case SCIP_VARSTATUS_FIXED:
16157	      return 0.0;
16158	
16159	   case SCIP_VARSTATUS_AGGREGATED:
16160	      if( var->data.aggregate.scalar > 0.0 )
16161	         return SCIPvarGetAvgInferencesCurrentRun(var->data.aggregate.var, stat, dir);
16162	      else
16163	         return SCIPvarGetAvgInferencesCurrentRun(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
16164	
16165	   case SCIP_VARSTATUS_MULTAGGR:
16166	      return 0.0;
16167	
16168	   case SCIP_VARSTATUS_NEGATED:
16169	      return SCIPvarGetAvgInferencesCurrentRun(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
16170	
16171	   default:
16172	      SCIPerrorMessage("unknown variable status\n");
16173	      SCIPABORT();
16174	      return 0.0; /*lint !e527*/
16175	   }
16176	}
16177	
16178	/** returns the number of cutoffs branching on this variable in given direction produced */
16179	SCIP_Real SCIPvarGetCutoffSum(
16180	   SCIP_VAR*             var,                /**< problem variable */
16181	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
16182	   )
16183	{
16184	   assert(var != NULL);
16185	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16186	
16187	   switch( SCIPvarGetStatus(var) )
16188	   {
16189	   case SCIP_VARSTATUS_ORIGINAL:
16190	      if( var->data.original.transvar == NULL )
16191	         return 0;
16192	      else
16193	         return SCIPvarGetCutoffSum(var->data.original.transvar, dir);
16194	
16195	   case SCIP_VARSTATUS_LOOSE:
16196	   case SCIP_VARSTATUS_COLUMN:
16197	      return SCIPhistoryGetCutoffSum(var->history, dir);
16198	
16199	   case SCIP_VARSTATUS_FIXED:
16200	      return 0;
16201	
16202	   case SCIP_VARSTATUS_AGGREGATED:
16203	      if( var->data.aggregate.scalar > 0.0 )
16204	         return SCIPvarGetCutoffSum(var->data.aggregate.var, dir);
16205	      else
16206	         return SCIPvarGetCutoffSum(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
16207	
16208	   case SCIP_VARSTATUS_MULTAGGR:
16209	      return 0;
16210	
16211	   case SCIP_VARSTATUS_NEGATED:
16212	      return SCIPvarGetCutoffSum(var->negatedvar, SCIPbranchdirOpposite(dir));
16213	
16214	   default:
16215	      SCIPerrorMessage("unknown variable status\n");
16216	      SCIPABORT();
16217	      return 0; /*lint !e527*/
16218	   }
16219	}
16220	
16221	/** returns the number of cutoffs branching on this variable in given direction produced in the current run */
16222	SCIP_Real SCIPvarGetCutoffSumCurrentRun(
16223	   SCIP_VAR*             var,                /**< problem variable */
16224	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
16225	   )
16226	{
16227	   assert(var != NULL);
16228	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16229	
16230	   switch( SCIPvarGetStatus(var) )
16231	   {
16232	   case SCIP_VARSTATUS_ORIGINAL:
16233	      if( var->data.original.transvar == NULL )
16234	         return 0;
16235	      else
16236	         return SCIPvarGetCutoffSumCurrentRun(var->data.original.transvar, dir);
16237	
16238	   case SCIP_VARSTATUS_LOOSE:
16239	   case SCIP_VARSTATUS_COLUMN:
16240	      return SCIPhistoryGetCutoffSum(var->historycrun, dir);
16241	
16242	   case SCIP_VARSTATUS_FIXED:
16243	      return 0;
16244	
16245	   case SCIP_VARSTATUS_AGGREGATED:
16246	      if( var->data.aggregate.scalar > 0.0 )
16247	         return SCIPvarGetCutoffSumCurrentRun(var->data.aggregate.var, dir);
16248	      else
16249	         return SCIPvarGetCutoffSumCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
16250	
16251	   case SCIP_VARSTATUS_MULTAGGR:
16252	      return 0;
16253	
16254	   case SCIP_VARSTATUS_NEGATED:
16255	      return SCIPvarGetCutoffSumCurrentRun(var->negatedvar, SCIPbranchdirOpposite(dir));
16256	
16257	   default:
16258	      SCIPerrorMessage("unknown variable status\n");
16259	      SCIPABORT();
16260	      return 0; /*lint !e527*/
16261	   }
16262	}
16263	
16264	/** returns the average number of cutoffs found after branching on the variable in given direction */
16265	SCIP_Real SCIPvarGetAvgCutoffs(
16266	   SCIP_VAR*             var,                /**< problem variable */
16267	   SCIP_STAT*            stat,               /**< problem statistics */
16268	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
16269	   )
16270	{
16271	   assert(var != NULL);
16272	   assert(stat != NULL);
16273	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16274	
16275	   switch( SCIPvarGetStatus(var) )
16276	   {
16277	   case SCIP_VARSTATUS_ORIGINAL:
16278	      if( var->data.original.transvar == NULL )
16279	         return SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
16280	      else
16281	         return SCIPvarGetAvgCutoffs(var->data.original.transvar, stat, dir);
16282	
16283	   case SCIP_VARSTATUS_LOOSE:
16284	   case SCIP_VARSTATUS_COLUMN:
16285	      return SCIPhistoryGetNBranchings(var->history, dir) > 0
16286	         ? SCIPhistoryGetAvgCutoffs(var->history, dir)
16287	         : SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
16288	
16289	   case SCIP_VARSTATUS_FIXED:
16290	      return 0.0;
16291	
16292	   case SCIP_VARSTATUS_AGGREGATED:
16293	      if( var->data.aggregate.scalar > 0.0 )
16294	         return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, dir);
16295	      else
16296	         return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
16297	
16298	   case SCIP_VARSTATUS_MULTAGGR:
16299	      return 0.0;
16300	
16301	   case SCIP_VARSTATUS_NEGATED:
16302	      return SCIPvarGetAvgCutoffs(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
16303	
16304	   default:
16305	      SCIPerrorMessage("unknown variable status\n");
16306	      SCIPABORT();
16307	      return 0.0; /*lint !e527*/
16308	   }
16309	}
16310	
16311	/** returns the average number of cutoffs found after branching on the variable in given direction in the current run */
16312	SCIP_Real SCIPvarGetAvgCutoffsCurrentRun(
16313	   SCIP_VAR*             var,                /**< problem variable */
16314	   SCIP_STAT*            stat,               /**< problem statistics */
16315	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
16316	   )
16317	{
16318	   assert(var != NULL);
16319	   assert(stat != NULL);
16320	   assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16321	
16322	   switch( SCIPvarGetStatus(var) )
16323	   {
16324	   case SCIP_VARSTATUS_ORIGINAL:
16325	      if( var->data.original.transvar == NULL )
16326	         return SCIPhistoryGetAvgCutoffs(stat->glbhistorycrun, dir);
16327	      else
16328	         return SCIPvarGetAvgCutoffsCurrentRun(var->data.original.transvar, stat, dir);
16329	
16330	   case SCIP_VARSTATUS_LOOSE:
16331	   case SCIP_VARSTATUS_COLUMN:
16332	      return SCIPhistoryGetNBranchings(var->historycrun, dir) > 0
16333	         ? SCIPhistoryGetAvgCutoffs(var->historycrun, dir)
16334	         : SCIPhistoryGetAvgCutoffs(stat->glbhistorycrun, dir);
16335	
16336	   case SCIP_VARSTATUS_FIXED:
16337	      return 0.0;
16338	
16339	   case SCIP_VARSTATUS_AGGREGATED:
16340	      if( var->data.aggregate.scalar > 0.0 )
16341	         return SCIPvarGetAvgCutoffsCurrentRun(var->data.aggregate.var, stat, dir);
16342	      else
16343	         return SCIPvarGetAvgCutoffsCurrentRun(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
16344	
16345	   case SCIP_VARSTATUS_MULTAGGR:
16346	      return 0.0;
16347	
16348	   case SCIP_VARSTATUS_NEGATED:
16349	      return SCIPvarGetAvgCutoffsCurrentRun(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
16350	
16351	   default:
16352	      SCIPerrorMessage("unknown variable status\n");
16353	      SCIPABORT();
16354	      return 0.0; /*lint !e527*/
16355	   }
16356	}
16357	
16358	/** returns the variable's average GMI efficacy score value generated from simplex tableau rows of this variable */
16359	SCIP_Real SCIPvarGetAvgGMIScore(
16360	   SCIP_VAR*             var,                /**< problem variable */
16361	   SCIP_STAT*            stat                /**< problem statistics */
16362	)
16363	{
16364	   assert(var != NULL);
16365	   assert(stat != NULL);
16366	
16367	   switch( SCIPvarGetStatus(var) )
16368	   {
16369	      case SCIP_VARSTATUS_ORIGINAL:
16370	         if( var->data.original.transvar == NULL )
16371	            return 0.0;
16372	         else
16373	            return SCIPvarGetAvgGMIScore(var->data.original.transvar, stat);
16374	
16375	      case SCIP_VARSTATUS_LOOSE:
16376	      case SCIP_VARSTATUS_COLUMN:
16377	         return SCIPhistoryGetAvgGMIeff(var->history);
16378	
16379	      case SCIP_VARSTATUS_FIXED:
16380	         return 0.0;
16381	
16382	      case SCIP_VARSTATUS_AGGREGATED:
16383	         return SCIPvarGetAvgGMIScore(var->data.aggregate.var, stat);
16384	
16385	      case SCIP_VARSTATUS_MULTAGGR:
16386	         return 0.0;
16387	
16388	      case SCIP_VARSTATUS_NEGATED:
16389	         return SCIPvarGetAvgGMIScore(var->negatedvar, stat);
16390	
16391	      default:
16392	      SCIPerrorMessage("unknown variable status\n");
16393	         SCIPABORT();
16394	         return 0.0; /*lint !e527*/
16395	   }
16396	}
16397	
16398	/** increase the variable's GMI efficacy scores generated from simplex tableau rows of this variable */
16399	SCIP_RETCODE SCIPvarIncGMIeffSum(
16400	   SCIP_VAR*             var,                /**< problem variable */
16401	   SCIP_STAT*            stat,               /**< problem statistics */
16402	   SCIP_Real             gmieff              /**< efficacy of last GMI cut produced when variable was frac and basic */
16403	)
16404	{
16405	   assert(var != NULL);
16406	   assert(stat != NULL);
16407	   assert(gmieff >= 0);
16408	
16409	   switch( SCIPvarGetStatus(var) )
16410	   {
16411	      case SCIP_VARSTATUS_ORIGINAL:
16412	         if( var->data.original.transvar != NULL )
16413	            SCIP_CALL( SCIPvarIncGMIeffSum(var->data.original.transvar, stat, gmieff) );
16414	         return SCIP_OKAY;
16415	
16416	      case SCIP_VARSTATUS_LOOSE:
16417	      case SCIP_VARSTATUS_COLUMN:
16418	         SCIPhistoryIncGMIeffSum(var->history, gmieff);
16419	         return SCIP_OKAY;
16420	
16421	      case SCIP_VARSTATUS_FIXED:
16422	         return SCIP_INVALIDDATA;
16423	
16424	      case SCIP_VARSTATUS_AGGREGATED:
16425	         SCIP_CALL( SCIPvarIncGMIeffSum(var->data.aggregate.var, stat, gmieff) );
16426	         return SCIP_OKAY;
16427	
16428	      case SCIP_VARSTATUS_NEGATED:
16429	         SCIP_CALL( SCIPvarIncGMIeffSum(var->negatedvar, stat, gmieff) );
16430	         return SCIP_OKAY;
16431	
16432	      case SCIP_VARSTATUS_MULTAGGR:
16433	         return SCIP_INVALIDDATA;
16434	
16435	      default:
16436	      SCIPerrorMessage("unknown variable status\n");
16437	         SCIPABORT();
16438	         return SCIP_INVALIDDATA; /*lint !e527*/
16439	   }
16440	}
16441	
16442	/** returns the variable's last GMI efficacy score value generated from a simplex tableau row of this variable */
16443	SCIP_Real SCIPvarGetLastGMIScore(
16444	   SCIP_VAR*             var,                /**< problem variable */
16445	   SCIP_STAT*            stat                /**< problem statistics */
16446	)
16447	{
16448	   assert(var != NULL);
16449	   assert(stat != NULL);
16450	
16451	   switch( SCIPvarGetStatus(var) )
16452	   {
16453	      case SCIP_VARSTATUS_ORIGINAL:
16454	         if( var->data.original.transvar != NULL )
16455	            return SCIPvarGetLastGMIScore(var->data.original.transvar, stat);
16456	         return 0.0;
16457	
16458	      case SCIP_VARSTATUS_LOOSE:
16459	      case SCIP_VARSTATUS_COLUMN:
16460	         return SCIPhistoryGetLastGMIeff(var->history);
16461	
16462	      case SCIP_VARSTATUS_FIXED:
16463	         return 0.0;
16464	
16465	      case SCIP_VARSTATUS_AGGREGATED:
16466	         return SCIPvarGetLastGMIScore(var->data.aggregate.var, stat);
16467	
16468	      case SCIP_VARSTATUS_MULTAGGR:
16469	         return 0.0;
16470	
16471	      case SCIP_VARSTATUS_NEGATED:
16472	         return SCIPvarGetLastGMIScore(var->negatedvar, stat);
16473	
16474	      default:
16475	      SCIPerrorMessage("unknown variable status\n");
16476	         SCIPABORT();
16477	         return 0.0; /*lint !e527*/
16478	   }
16479	}
16480	
16481	
16482	/** sets the variable's last GMI efficacy score value generated from a simplex tableau row of this variable */
16483	SCIP_RETCODE SCIPvarSetLastGMIScore(
16484	   SCIP_VAR*             var,                /**< problem variable */
16485	   SCIP_STAT*            stat,               /**< problem statistics */
16486	   SCIP_Real             gmieff              /**< efficacy of last GMI cut produced when variable was frac and basic */
16487	)
16488	{
16489	   assert(var != NULL);
16490	   assert(stat != NULL);
16491	   assert(gmieff >= 0);
16492	
16493	   switch( SCIPvarGetStatus(var) )
16494	   {
16495	      case SCIP_VARSTATUS_ORIGINAL:
16496	         if( var->data.original.transvar != NULL )
16497	            SCIP_CALL( SCIPvarSetLastGMIScore(var->data.original.transvar, stat, gmieff) );
16498	         return SCIP_OKAY;
16499	
16500	      case SCIP_VARSTATUS_LOOSE:
16501	      case SCIP_VARSTATUS_COLUMN:
16502	         SCIPhistorySetLastGMIeff(var->history, gmieff);
16503	         return SCIP_OKAY;
16504	
16505	      case SCIP_VARSTATUS_FIXED:
16506	         return SCIP_INVALIDDATA;
16507	
16508	      case SCIP_VARSTATUS_AGGREGATED:
16509	         SCIP_CALL( SCIPvarSetLastGMIScore(var->data.aggregate.var, stat, gmieff) );
16510	         return SCIP_OKAY;
16511	
16512	      case SCIP_VARSTATUS_NEGATED:
16513	         SCIP_CALL( SCIPvarSetLastGMIScore(var->negatedvar, stat, gmieff) );
16514	         return SCIP_OKAY;
16515	
16516	      case SCIP_VARSTATUS_MULTAGGR:
16517	         return SCIP_INVALIDDATA;
16518	
16519	      default:
16520	      SCIPerrorMessage("unknown variable status\n");
16521	         SCIPABORT();
16522	         return SCIP_INVALIDDATA; /*lint !e527*/
16523	   }
16524	}
16525	
16526	
16527	
16528	/*
16529	 * information methods for bound changes
16530	 */
16531	
16532	/** creates an artificial bound change information object with depth = INT_MAX and pos = -1 */
16533	SCIP_RETCODE SCIPbdchginfoCreate(
16534	   SCIP_BDCHGINFO**      bdchginfo,          /**< pointer to store bound change information */
16535	   BMS_BLKMEM*           blkmem,             /**< block memory */
16536	   SCIP_VAR*             var,                /**< active variable that changed the bounds */
16537	   SCIP_BOUNDTYPE        boundtype,          /**< type of bound for var: lower or upper bound */
16538	   SCIP_Real             oldbound,           /**< old value for bound */
16539	   SCIP_Real             newbound            /**< new value for bound */
16540	   )
16541	{
16542	   assert(bdchginfo != NULL);
16543	
16544	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, bdchginfo) );
16545	   (*bdchginfo)->oldbound = oldbound;
16546	   (*bdchginfo)->newbound = newbound;
16547	   (*bdchginfo)->var = var;
16548	   (*bdchginfo)->inferencedata.var = var;
16549	   (*bdchginfo)->inferencedata.reason.prop = NULL;
16550	   (*bdchginfo)->inferencedata.info = 0;
16551	   (*bdchginfo)->bdchgidx.depth = INT_MAX;
16552	   (*bdchginfo)->bdchgidx.pos = -1;
16553	   (*bdchginfo)->pos = 0;
16554	   (*bdchginfo)->boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
16555	   (*bdchginfo)->boundtype = boundtype; /*lint !e641*/
16556	   (*bdchginfo)->inferboundtype = boundtype; /*lint !e641*/
16557	   (*bdchginfo)->redundant = FALSE;
16558	
16559	   return SCIP_OKAY;
16560	}
16561	
16562	/** frees a bound change information object */
16563	void SCIPbdchginfoFree(
16564	   SCIP_BDCHGINFO**      bdchginfo,          /**< pointer to store bound change information */
16565	   BMS_BLKMEM*           blkmem              /**< block memory */
16566	   )
16567	{
16568	   assert(bdchginfo != NULL);
16569	
16570	   BMSfreeBlockMemory(blkmem, bdchginfo);
16571	}
16572	
16573	/** returns the bound change information for the last lower bound change on given active problem variable before or
16574	 *  after the bound change with the given index was applied;
16575	 *  returns NULL, if no change to the lower bound was applied up to this point of time
16576	 */
16577	SCIP_BDCHGINFO* SCIPvarGetLbchgInfo(
16578	   SCIP_VAR*             var,                /**< active problem variable */
16579	   SCIP_BDCHGIDX*        bdchgidx,           /**< bound change index representing time on path to current node */
16580	   SCIP_Bool             after               /**< should the bound change with given index be included? */
16581	   )
16582	{
16583	   int i;
16584	
16585	   assert(var != NULL);
16586	   assert(SCIPvarIsActive(var));
16587	
16588	   /* search the correct bound change information for the given bound change index */
16589	   if( after )
16590	   {
16591	      for( i = var->nlbchginfos-1; i >= 0; --i )
16592	      {
16593	         assert(var->lbchginfos[i].var == var);
16594	         assert((SCIP_BOUNDTYPE)var->lbchginfos[i].boundtype == SCIP_BOUNDTYPE_LOWER);
16595	         assert(var->lbchginfos[i].pos == i);
16596	
16597	         /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16598	         if( var->lbchginfos[i].redundant )
16599	            return NULL;
16600	         assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
16601	
16602	         /* if we reached the bound change index, return the current bound change info */
16603	         if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->lbchginfos[i].bdchgidx) )
16604	            return &var->lbchginfos[i];
16605	      }
16606	   }
16607	   else
16608	   {
16609	      for( i = var->nlbchginfos-1; i >= 0; --i )
16610	      {
16611	         assert(var->lbchginfos[i].var == var);
16612	         assert((SCIP_BOUNDTYPE)var->lbchginfos[i].boundtype == SCIP_BOUNDTYPE_LOWER);
16613	         assert(var->lbchginfos[i].pos == i);
16614	
16615	         /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16616	         if( var->lbchginfos[i].redundant )
16617	            return NULL;
16618	         assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
16619	
16620	         /* if we reached the bound change index, return the current bound change info */
16621	         if( SCIPbdchgidxIsEarlier(&var->lbchginfos[i].bdchgidx, bdchgidx) )
16622	            return &var->lbchginfos[i];
16623	      }
16624	   }
16625	
16626	   return NULL;
16627	}
16628	
16629	/** returns the bound change information for the last upper bound change on given active problem variable before or
16630	 *  after the bound change with the given index was applied;
16631	 *  returns NULL, if no change to the upper bound was applied up to this point of time
16632	 */
16633	SCIP_BDCHGINFO* SCIPvarGetUbchgInfo(
16634	   SCIP_VAR*             var,                /**< active problem variable */
16635	   SCIP_BDCHGIDX*        bdchgidx,           /**< bound change index representing time on path to current node */
16636	   SCIP_Bool             after               /**< should the bound change with given index be included? */
16637	   )
16638	{
16639	   int i;
16640	
16641	   assert(var != NULL);
16642	   assert(SCIPvarIsActive(var));
16643	
16644	   /* search the correct bound change information for the given bound change index */
16645	   if( after )
16646	   {
16647	      for( i = var->nubchginfos-1; i >= 0; --i )
16648	      {
16649	         assert(var->ubchginfos[i].var == var);
16650	         assert((SCIP_BOUNDTYPE)var->ubchginfos[i].boundtype == SCIP_BOUNDTYPE_UPPER);
16651	         assert(var->ubchginfos[i].pos == i);
16652	
16653	         /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16654	         if( var->ubchginfos[i].redundant )
16655	            return NULL;
16656	         assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
16657	
16658	         /* if we reached the bound change index, return the current bound change info */
16659	         if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->ubchginfos[i].bdchgidx) )
16660	            return &var->ubchginfos[i];
16661	      }
16662	   }
16663	   else
16664	   {
16665	      for( i = var->nubchginfos-1; i >= 0; --i )
16666	      {
16667	         assert(var->ubchginfos[i].var == var);
16668	         assert((SCIP_BOUNDTYPE)var->ubchginfos[i].boundtype == SCIP_BOUNDTYPE_UPPER);
16669	         assert(var->ubchginfos[i].pos == i);
16670	
16671	         /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16672	         if( var->ubchginfos[i].redundant )
16673	            return NULL;
16674	         assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
16675	
16676	         /* if we reached the bound change index, return the current bound change info */
16677	         if( SCIPbdchgidxIsEarlier(&var->ubchginfos[i].bdchgidx, bdchgidx) )
16678	            return &var->ubchginfos[i];
16679	      }
16680	   }
16681	
16682	   return NULL;
16683	}
16684	
16685	/** returns the bound change information for the last lower or upper bound change on given active problem variable
16686	 *  before or after the bound change with the given index was applied;
16687	 *  returns NULL, if no change to the lower/upper bound was applied up to this point of time
16688	 */
16689	SCIP_BDCHGINFO* SCIPvarGetBdchgInfo(
16690	   SCIP_VAR*             var,                /**< active problem variable */
16691	   SCIP_BOUNDTYPE        boundtype,          /**< type of bound: lower or upper bound */
16692	   SCIP_BDCHGIDX*        bdchgidx,           /**< bound change index representing time on path to current node */
16693	   SCIP_Bool             after               /**< should the bound change with given index be included? */
16694	   )
16695	{
16696	   if( boundtype == SCIP_BOUNDTYPE_LOWER )
16697	      return SCIPvarGetLbchgInfo(var, bdchgidx, after);
16698	   else
16699	   {
16700	      assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16701	      return SCIPvarGetUbchgInfo(var, bdchgidx, after);
16702	   }
16703	}
16704	
16705	/** returns lower bound of variable directly before or after the bound change given by the bound change index
16706	 *  was applied
16707	 *
16708	 *  @deprecated Please use SCIPgetVarLbAtIndex()
16709	 */
16710	SCIP_Real SCIPvarGetLbAtIndex(
16711	   SCIP_VAR*             var,                /**< problem variable */
16712	   SCIP_BDCHGIDX*        bdchgidx,           /**< bound change index representing time on path to current node */
16713	   SCIP_Bool             after               /**< should the bound change with given index be included? */
16714	   )
16715	{
16716	   SCIP_VARSTATUS varstatus;
16717	   assert(var != NULL);
16718	
16719	   varstatus = SCIPvarGetStatus(var);
16720	
16721	   /* get bounds of attached variables */
16722	   switch( varstatus )
16723	   {
16724	   case SCIP_VARSTATUS_ORIGINAL:
16725	      assert(var->data.original.transvar != NULL);
16726	      return SCIPvarGetLbAtIndex(var->data.original.transvar, bdchgidx, after);
16727	
16728	   case SCIP_VARSTATUS_LOOSE:
16729	   case SCIP_VARSTATUS_COLUMN:
16730	      if( bdchgidx == NULL )
16731	         return SCIPvarGetLbLocal(var);
16732	      else
16733	      {
16734	         SCIP_BDCHGINFO* bdchginfo;
16735	
16736	         bdchginfo = SCIPvarGetLbchgInfo(var, bdchgidx, after);
16737	         if( bdchginfo != NULL )
16738	            return SCIPbdchginfoGetNewbound(bdchginfo);
16739	         else
16740	            return var->glbdom.lb;
16741	      }
16742	   case SCIP_VARSTATUS_FIXED:
16743	      return var->glbdom.lb;
16744	
16745	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
16746	      assert(var->data.aggregate.var != NULL);
16747	      /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16748	       * corresponding infinity value instead of performing an arithmetical transformation (compare method
16749	       * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16750	       * (or is called by) a public interface method; instead, we only assert that values are finite
16751	       * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16752	       * positives and negatives if the parameter <numerics/infinity> is modified by the user
16753	       */
16754	      if( var->data.aggregate.scalar > 0.0 )
16755	      {
16756	         /* a > 0 -> get lower bound of y */
16757	         assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16758	         assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16759	         return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16760	            + var->data.aggregate.constant;
16761	      }
16762	      else if( var->data.aggregate.scalar < 0.0 )
16763	      {
16764	         /* a < 0 -> get upper bound of y */
16765	         assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16766	         assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16767	         return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16768	            + var->data.aggregate.constant;
16769	      }
16770	      else
16771	      {
16772	         SCIPerrorMessage("scalar is zero in aggregation\n");
16773	         SCIPABORT();
16774	         return SCIP_INVALID; /*lint !e527*/
16775	      }
16776	
16777	   case SCIP_VARSTATUS_MULTAGGR:
16778	      /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16779	      if ( var->data.multaggr.nvars == 1 )
16780	      {
16781	         assert(var->data.multaggr.vars != NULL);
16782	         assert(var->data.multaggr.scalars != NULL);
16783	         assert(var->data.multaggr.vars[0] != NULL);
16784	
16785	         if( var->data.multaggr.scalars[0] > 0.0 )
16786	         {
16787	            /* a > 0 -> get lower bound of y */
16788	            assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16789	            assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16790	            return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16791	               + var->data.multaggr.constant;
16792	         }
16793	         else if( var->data.multaggr.scalars[0] < 0.0 )
16794	         {
16795	            /* a < 0 -> get upper bound of y */
16796	            assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16797	            assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16798	            return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16799	               + var->data.multaggr.constant;
16800	         }
16801	         else
16802	         {
16803	            SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16804	            SCIPABORT();
16805	            return SCIP_INVALID; /*lint !e527*/
16806	         }
16807	      }
16808	      SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
16809	      SCIPABORT();
16810	      return SCIP_INVALID; /*lint !e527*/
16811	
16812	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
16813	      assert(var->negatedvar != NULL);
16814	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
16815	      assert(var->negatedvar->negatedvar == var);
16816	      return var->data.negate.constant - SCIPvarGetUbAtIndex(var->negatedvar, bdchgidx, after);
16817	   default:
16818	      SCIPerrorMessage("unknown variable status\n");
16819	      SCIPABORT();
16820	      return SCIP_INVALID; /*lint !e527*/
16821	   }
16822	}
16823	
16824	/** returns upper bound of variable directly before or after the bound change given by the bound change index
16825	 *  was applied
16826	 *
16827	 *  @deprecated Please use SCIPgetVarUbAtIndex()
16828	 */
16829	SCIP_Real SCIPvarGetUbAtIndex(
16830	   SCIP_VAR*             var,                /**< problem variable */
16831	   SCIP_BDCHGIDX*        bdchgidx,           /**< bound change index representing time on path to current node */
16832	   SCIP_Bool             after               /**< should the bound change with given index be included? */
16833	   )
16834	{
16835	   SCIP_VARSTATUS varstatus;
16836	   assert(var != NULL);
16837	
16838	   varstatus = SCIPvarGetStatus(var);
16839	
16840	   /* get bounds of attached variables */
16841	   switch( varstatus )
16842	   {
16843	   case SCIP_VARSTATUS_ORIGINAL:
16844	      assert(var->data.original.transvar != NULL);
16845	      return SCIPvarGetUbAtIndex(var->data.original.transvar, bdchgidx, after);
16846	
16847	   case SCIP_VARSTATUS_COLUMN:
16848	   case SCIP_VARSTATUS_LOOSE:
16849	      if( bdchgidx == NULL )
16850	         return SCIPvarGetUbLocal(var);
16851	      else
16852	      {
16853	         SCIP_BDCHGINFO* bdchginfo;
16854	
16855	         bdchginfo = SCIPvarGetUbchgInfo(var, bdchgidx, after);
16856	         if( bdchginfo != NULL )
16857	            return SCIPbdchginfoGetNewbound(bdchginfo);
16858	         else
16859	            return var->glbdom.ub;
16860	      }
16861	
16862	   case SCIP_VARSTATUS_FIXED:
16863	      return var->glbdom.ub;
16864	
16865	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
16866	      assert(var->data.aggregate.var != NULL);
16867	      /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16868	       * corresponding infinity value instead of performing an arithmetical transformation (compare method
16869	       * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16870	       * (or is called by) a public interface method; instead, we only assert that values are finite
16871	       * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16872	       * positives and negatives if the parameter <numerics/infinity> is modified by the user
16873	       */
16874	      if( var->data.aggregate.scalar > 0.0 )
16875	      {
16876	         /* a > 0 -> get lower bound of y */
16877	         assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16878	         assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16879	         return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16880	            + var->data.aggregate.constant;
16881	      }
16882	      else if( var->data.aggregate.scalar < 0.0 )
16883	      {
16884	         /* a < 0 -> get upper bound of y */
16885	         assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16886	         assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16887	         return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16888	            + var->data.aggregate.constant;
16889	      }
16890	      else
16891	      {
16892	         SCIPerrorMessage("scalar is zero in aggregation\n");
16893	         SCIPABORT();
16894	         return SCIP_INVALID; /*lint !e527*/
16895	      }
16896	
16897	   case SCIP_VARSTATUS_MULTAGGR:
16898	      /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16899	      if ( var->data.multaggr.nvars == 1 )
16900	      {
16901	         assert(var->data.multaggr.vars != NULL);
16902	         assert(var->data.multaggr.scalars != NULL);
16903	         assert(var->data.multaggr.vars[0] != NULL);
16904	
16905	         if( var->data.multaggr.scalars[0] > 0.0 )
16906	         {
16907	            /* a > 0 -> get lower bound of y */
16908	            assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16909	            assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16910	            return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16911	               + var->data.multaggr.constant;
16912	         }
16913	         else if( var->data.multaggr.scalars[0] < 0.0 )
16914	         {
16915	            /* a < 0 -> get upper bound of y */
16916	            assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16917	            assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16918	            return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16919	               + var->data.multaggr.constant;
16920	         }
16921	         else
16922	         {
16923	            SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16924	            SCIPABORT();
16925	            return SCIP_INVALID; /*lint !e527*/
16926	         }
16927	      }
16928	      SCIPerrorMessage("cannot get the bounds of a multiple aggregated variable.\n");
16929	      SCIPABORT();
16930	      return SCIP_INVALID; /*lint !e527*/
16931	
16932	   case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
16933	      assert(var->negatedvar != NULL);
16934	      assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
16935	      assert(var->negatedvar->negatedvar == var);
16936	      return var->data.negate.constant - SCIPvarGetLbAtIndex(var->negatedvar, bdchgidx, after);
16937	
16938	   default:
16939	      SCIPerrorMessage("unknown variable status\n");
16940	      SCIPABORT();
16941	      return SCIP_INVALID; /*lint !e527*/
16942	   }
16943	}
16944	
16945	/** returns lower or upper bound of variable directly before or after the bound change given by the bound change index
16946	 *  was applied
16947	 *
16948	 *  @deprecated Please use SCIPgetVarBdAtIndex()
16949	 */
16950	SCIP_Real SCIPvarGetBdAtIndex(
16951	   SCIP_VAR*             var,                /**< problem variable */
16952	   SCIP_BOUNDTYPE        boundtype,          /**< type of bound: lower or upper bound */
16953	   SCIP_BDCHGIDX*        bdchgidx,           /**< bound change index representing time on path to current node */
16954	   SCIP_Bool             after               /**< should the bound change with given index be included? */
16955	   )
16956	{
16957	   if( boundtype == SCIP_BOUNDTYPE_LOWER )
16958	      return SCIPvarGetLbAtIndex(var, bdchgidx, after);
16959	   else
16960	   {
16961	      assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16962	      return SCIPvarGetUbAtIndex(var, bdchgidx, after);
16963	   }
16964	}
16965	
16966	/** returns whether the binary variable was fixed at the time given by the bound change index
16967	 *
16968	 *  @deprecated Please use SCIPgetVarWasFixedAtIndex()
16969	 */
16970	SCIP_Bool SCIPvarWasFixedAtIndex(
16971	   SCIP_VAR*             var,                /**< problem variable */
16972	   SCIP_BDCHGIDX*        bdchgidx,           /**< bound change index representing time on path to current node */
16973	   SCIP_Bool             after               /**< should the bound change with given index be included? */
16974	   )
16975	{
16976	   assert(var != NULL);
16977	   assert(SCIPvarIsBinary(var));
16978	
16979	   /* check the current bounds first in order to decide at which bound change information we have to look
16980	    * (which is expensive because we have to follow the aggregation tree to the active variable)
16981	    */
16982	   return ((SCIPvarGetLbLocal(var) > 0.5 && SCIPvarGetLbAtIndex(var, bdchgidx, after) > 0.5)
16983	      || (SCIPvarGetUbLocal(var) < 0.5 && SCIPvarGetUbAtIndex(var, bdchgidx, after) < 0.5));
16984	}
16985	
16986	/** bound change index representing the initial time before any bound changes took place */
16987	static SCIP_BDCHGIDX initbdchgidx = {-2, 0};
16988	
16989	/** bound change index representing the presolving stage */
16990	static SCIP_BDCHGIDX presolvebdchgidx = {-1, 0};
16991	
16992	/** returns the last bound change index, at which the bounds of the given variable were tightened */
16993	SCIP_BDCHGIDX* SCIPvarGetLastBdchgIndex(
16994	   SCIP_VAR*             var                 /**< problem variable */
16995	   )
16996	{
16997	   SCIP_BDCHGIDX* lbchgidx;
16998	   SCIP_BDCHGIDX* ubchgidx;
16999	
17000	   assert(var != NULL);
17001	
17002	   var = SCIPvarGetProbvar(var);
17003	
17004	   /* check, if variable is original without transformed variable */
17005	   if( var == NULL )
17006	      return &initbdchgidx;
17007	
17008	   /* check, if variable was fixed in presolving */
17009	   if( !SCIPvarIsActive(var) )
17010	      return &presolvebdchgidx;
17011	
17012	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
17013	
17014	   /* get depths of last bound change information for the lower and upper bound */
17015	   lbchgidx = (var->nlbchginfos > 0 && !var->lbchginfos[var->nlbchginfos-1].redundant
17016	      ? &var->lbchginfos[var->nlbchginfos-1].bdchgidx : &initbdchgidx);
17017	   ubchgidx = (var->nubchginfos > 0 && !var->ubchginfos[var->nubchginfos-1].redundant
17018	      ? &var->ubchginfos[var->nubchginfos-1].bdchgidx : &initbdchgidx);
17019	
17020	   if( SCIPbdchgidxIsEarlierNonNull(lbchgidx, ubchgidx) )
17021	      return ubchgidx;
17022	   else
17023	      return lbchgidx;
17024	}
17025	
17026	/** returns the last depth level, at which the bounds of the given variable were tightened;
17027	 *  returns -2, if the variable's bounds are still the global bounds
17028	 *  returns -1, if the variable was fixed in presolving
17029	 */
17030	int SCIPvarGetLastBdchgDepth(
17031	   SCIP_VAR*             var                 /**< problem variable */
17032	   )
17033	{
17034	   SCIP_BDCHGIDX* bdchgidx;
17035	
17036	   bdchgidx = SCIPvarGetLastBdchgIndex(var);
17037	   assert(bdchgidx != NULL);
17038	
17039	   return bdchgidx->depth;
17040	}
17041	
17042	/** returns at which depth in the tree a bound change was applied to the variable that conflicts with the
17043	 *  given bound; returns -1 if the bound does not conflict with the current local bounds of the variable
17044	 */
17045	int SCIPvarGetConflictingBdchgDepth(
17046	   SCIP_VAR*             var,                /**< problem variable */
17047	   SCIP_SET*             set,                /**< global SCIP settings */
17048	   SCIP_BOUNDTYPE        boundtype,          /**< bound type of the conflicting bound */
17049	   SCIP_Real             bound               /**< conflicting bound */
17050	   )
17051	{
17052	   int i;
17053	
17054	   assert(var != NULL);
17055	   assert(set != NULL);
17056	   assert(var->scip == set->scip);
17057	
17058	   if( boundtype == SCIP_BOUNDTYPE_LOWER )
17059	   {
17060	      /* check if the bound is in conflict with the current local bounds */
17061	      if( SCIPsetIsLE(set, bound, var->locdom.ub) )
17062	         return -1;
17063	
17064	      /* check if the bound is in conflict with the global bound */
17065	      if( SCIPsetIsGT(set, bound, var->glbdom.ub) )
17066	         return 0;
17067	
17068	      /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
17069	      assert(var->nubchginfos > 0);
17070	      assert(SCIPsetIsGT(set, bound, var->ubchginfos[var->nubchginfos-1].newbound));
17071	
17072	      /* search for the first conflicting bound change */
17073	      for( i = var->nubchginfos-1; i > 0 && SCIPsetIsGT(set, bound, var->ubchginfos[i-1].newbound); --i )
17074	      {
17075	         assert(var->ubchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
17076	         assert((SCIP_BOUNDTYPE)var->ubchginfos[i].boundtype == SCIP_BOUNDTYPE_UPPER);
17077	      }
17078	      assert(SCIPsetIsGT(set, bound, var->ubchginfos[i].newbound));             /* bound change i is conflicting */
17079	      assert(i == 0 || SCIPsetIsLE(set, bound, var->ubchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
17080	
17081	      /* return the depth at which the first conflicting bound change took place */
17082	      return var->ubchginfos[i].bdchgidx.depth;
17083	   }
17084	   else
17085	   {
17086	      assert(boundtype == SCIP_BOUNDTYPE_UPPER);
17087	
17088	      /* check if the bound is in conflict with the current local bounds */
17089	      if( SCIPsetIsGE(set, bound, var->locdom.lb) )
17090	         return -1;
17091	
17092	      /* check if the bound is in conflict with the global bound */
17093	      if( SCIPsetIsLT(set, bound, var->glbdom.lb) )
17094	         return 0;
17095	
17096	      /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
17097	      assert(var->nlbchginfos > 0);
17098	      assert(SCIPsetIsLT(set, bound, var->lbchginfos[var->nlbchginfos-1].newbound));
17099	
17100	      /* search for the first conflicting bound change */
17101	      for( i = var->nlbchginfos-1; i > 0 && SCIPsetIsLT(set, bound, var->lbchginfos[i-1].newbound); --i )
17102	      {
17103	         assert(var->lbchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
17104	         assert((SCIP_BOUNDTYPE)var->lbchginfos[i].boundtype == SCIP_BOUNDTYPE_LOWER);
17105	      }
17106	      assert(SCIPsetIsLT(set, bound, var->lbchginfos[i].newbound));             /* bound change i is conflicting */
17107	      assert(i == 0 || SCIPsetIsGE(set, bound, var->lbchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
17108	
17109	      /* return the depth at which the first conflicting bound change took place */
17110	      return var->lbchginfos[i].bdchgidx.depth;
17111	   }
17112	}
17113	
17114	/** returns whether the first binary variable was fixed earlier than the second one;
17115	 *  returns FALSE, if the first variable is not fixed, and returns TRUE, if the first variable is fixed, but the
17116	 *  second one is not fixed
17117	 */
17118	SCIP_Bool SCIPvarWasFixedEarlier(
17119	   SCIP_VAR*             var1,               /**< first binary variable */
17120	   SCIP_VAR*             var2                /**< second binary variable */
17121	   )
17122	{
17123	   SCIP_BDCHGIDX* bdchgidx1;
17124	   SCIP_BDCHGIDX* bdchgidx2;
17125	
17126	   assert(var1 != NULL);
17127	   assert(var2 != NULL);
17128	   assert(SCIPvarIsBinary(var1));
17129	   assert(SCIPvarIsBinary(var2));
17130	
17131	   var1 = SCIPvarGetProbvar(var1);
17132	   var2 = SCIPvarGetProbvar(var2);
17133	   assert(var1 != NULL);
17134	   assert(var2 != NULL);
17135	
17136	   /* check, if variables are globally fixed */
17137	   if( !SCIPvarIsActive(var2) || var2->glbdom.lb > 0.5 || var2->glbdom.ub < 0.5 )
17138	      return FALSE;
17139	   if( !SCIPvarIsActive(var1) || var1->glbdom.lb > 0.5 || var1->glbdom.ub < 0.5 )
17140	      return TRUE;
17141	
17142	   assert(SCIPvarGetStatus(var1) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var1) == SCIP_VARSTATUS_COLUMN);
17143	   assert(SCIPvarGetStatus(var2) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var2) == SCIP_VARSTATUS_COLUMN);
17144	   assert(SCIPvarIsBinary(var1));
17145	   assert(SCIPvarIsBinary(var2));
17146	   assert(var1->nlbchginfos + var1->nubchginfos <= 1);
17147	   assert(var2->nlbchginfos + var2->nubchginfos <= 1);
17148	   assert(var1->nlbchginfos == 0 || !var1->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
17149	   assert(var1->nubchginfos == 0 || !var1->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
17150	   assert(var2->nlbchginfos == 0 || !var2->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
17151	   assert(var2->nubchginfos == 0 || !var2->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
17152	
17153	   if( var1->nlbchginfos == 1 )
17154	      bdchgidx1 = &var1->lbchginfos[0].bdchgidx;
17155	   else if( var1->nubchginfos == 1 )
17156	      bdchgidx1 = &var1->ubchginfos[0].bdchgidx;
17157	   else
17158	      bdchgidx1 = NULL;
17159	
17160	   if( var2->nlbchginfos == 1 )
17161	      bdchgidx2 = &var2->lbchginfos[0].bdchgidx;
17162	   else if( var2->nubchginfos == 1 )
17163	      bdchgidx2 = &var2->ubchginfos[0].bdchgidx;
17164	   else
17165	      bdchgidx2 = NULL;
17166	
17167	   return SCIPbdchgidxIsEarlier(bdchgidx1, bdchgidx2);
17168	}
17169	
17170	
17171	
17172	/*
17173	 * Hash functions
17174	 */
17175	
17176	/** gets the key (i.e. the name) of the given variable */
17177	SCIP_DECL_HASHGETKEY(SCIPhashGetKeyVar)
17178	{  /*lint --e{715}*/
17179	   SCIP_VAR* var = (SCIP_VAR*)elem;
17180	
17181	   assert(var != NULL);
17182	   return var->name;
17183	}
17184	
17185	
17186	
17187	
17188	/*
17189	 * simple functions implemented as defines
17190	 */
17191	
17192	/* In debug mode, the following methods are implemented as function calls to ensure
17193	 * type validity.
17194	 * In optimized mode, the methods are implemented as defines to improve performance.
17195	 * However, we want to have them in the library anyways, so we have to undef the defines.
17196	 */
17197	
17198	#undef SCIPboundchgGetNewbound
17199	#undef SCIPboundchgGetVar
17200	#undef SCIPboundchgGetBoundchgtype
17201	#undef SCIPboundchgGetBoundtype
17202	#undef SCIPboundchgIsRedundant
17203	#undef SCIPdomchgGetNBoundchgs
17204	#undef SCIPdomchgGetBoundchg
17205	#undef SCIPholelistGetLeft
17206	#undef SCIPholelistGetRight
17207	#undef SCIPholelistGetNext
17208	#undef SCIPvarGetName
17209	#undef SCIPvarGetNUses
17210	#undef SCIPvarGetData
17211	#undef SCIPvarSetData
17212	#undef SCIPvarSetDelorigData
17213	#undef SCIPvarSetTransData
17214	#undef SCIPvarSetDeltransData
17215	#undef SCIPvarGetStatus
17216	#undef SCIPvarIsOriginal
17217	#undef SCIPvarIsTransformed
17218	#undef SCIPvarIsNegated
17219	#undef SCIPvarGetType
17220	#undef SCIPvarIsBinary
17221	#undef SCIPvarIsIntegral
17222	#undef SCIPvarIsInitial
17223	#undef SCIPvarIsRemovable
17224	#undef SCIPvarIsDeleted
17225	#undef SCIPvarIsDeletable
17226	#undef SCIPvarMarkDeletable
17227	#undef SCIPvarMarkNotDeletable
17228	#undef SCIPvarIsActive
17229	#undef SCIPvarGetIndex
17230	#undef SCIPvarGetProbindex
17231	#undef SCIPvarGetTransVar
17232	#undef SCIPvarGetCol
17233	#undef SCIPvarIsInLP
17234	#undef SCIPvarGetAggrVar
17235	#undef SCIPvarGetAggrScalar
17236	#undef SCIPvarGetAggrConstant
17237	#undef SCIPvarGetMultaggrNVars
17238	#undef SCIPvarGetMultaggrVars
17239	#undef SCIPvarGetMultaggrScalars
17240	#undef SCIPvarGetMultaggrConstant
17241	#undef SCIPvarGetNegatedVar
17242	#undef SCIPvarGetNegationVar
17243	#undef SCIPvarGetNegationConstant
17244	#undef SCIPvarGetObj
17245	#undef SCIPvarGetLbOriginal
17246	#undef SCIPvarGetUbOriginal
17247	#undef SCIPvarGetHolelistOriginal
17248	#undef SCIPvarGetLbGlobal
17249	#undef SCIPvarGetUbGlobal
17250	#undef SCIPvarGetHolelistGlobal
17251	#undef SCIPvarGetBestBoundGlobal
17252	#undef SCIPvarGetWorstBoundGlobal
17253	#undef SCIPvarGetLbLocal
17254	#undef SCIPvarGetUbLocal
17255	#undef SCIPvarGetHolelistLocal
17256	#undef SCIPvarGetBestBoundLocal
17257	#undef SCIPvarGetWorstBoundLocal
17258	#undef SCIPvarGetBestBoundType
17259	#undef SCIPvarGetWorstBoundType
17260	#undef SCIPvarGetLbLazy
17261	#undef SCIPvarGetUbLazy
17262	#undef SCIPvarGetBranchFactor
17263	#undef SCIPvarGetBranchPriority
17264	#undef SCIPvarGetBranchDirection
17265	#undef SCIPvarGetNVlbs
17266	#undef SCIPvarGetVlbVars
17267	#undef SCIPvarGetVlbCoefs
17268	#undef SCIPvarGetVlbConstants
17269	#undef SCIPvarGetNVubs
17270	#undef SCIPvarGetVubVars
17271	#undef SCIPvarGetVubCoefs
17272	#undef SCIPvarGetVubConstants
17273	#undef SCIPvarGetNImpls
17274	#undef SCIPvarGetImplVars
17275	#undef SCIPvarGetImplTypes
17276	#undef SCIPvarGetImplBounds
17277	#undef SCIPvarGetImplIds
17278	#undef SCIPvarGetNCliques
17279	#undef SCIPvarGetCliques
17280	#undef SCIPvarGetLPSol
17281	#undef SCIPvarGetNLPSol
17282	#undef SCIPvarGetBdchgInfoLb
17283	#undef SCIPvarGetNBdchgInfosLb
17284	#undef SCIPvarGetBdchgInfoUb
17285	#undef SCIPvarGetNBdchgInfosUb
17286	#undef SCIPvarGetValuehistory
17287	#undef SCIPvarGetPseudoSol
17288	#undef SCIPvarCatchEvent
17289	#undef SCIPvarDropEvent
17290	#undef SCIPvarGetVSIDS
17291	#undef SCIPvarGetCliqueComponentIdx
17292	#undef SCIPvarIsRelaxationOnly
17293	#undef SCIPvarMarkRelaxationOnly
17294	#undef SCIPbdchgidxGetPos
17295	#undef SCIPbdchgidxIsEarlierNonNull
17296	#undef SCIPbdchgidxIsEarlier
17297	#undef SCIPbdchginfoGetOldbound
17298	#undef SCIPbdchginfoGetNewbound
17299	#undef SCIPbdchginfoGetVar
17300	#undef SCIPbdchginfoGetChgtype
17301	#undef SCIPbdchginfoGetBoundtype
17302	#undef SCIPbdchginfoGetDepth
17303	#undef SCIPbdchginfoGetPos
17304	#undef SCIPbdchginfoGetIdx
17305	#undef SCIPbdchginfoGetInferVar
17306	#undef SCIPbdchginfoGetInferCons
17307	#undef SCIPbdchginfoGetInferProp
17308	#undef SCIPbdchginfoGetInferInfo
17309	#undef SCIPbdchginfoGetInferBoundtype
17310	#undef SCIPbdchginfoIsRedundant
17311	#undef SCIPbdchginfoHasInferenceReason
17312	#undef SCIPbdchginfoIsTighter
17313	
17314	
17315	/** returns the new value of the bound in the bound change data */
17316	SCIP_Real SCIPboundchgGetNewbound(
17317	   SCIP_BOUNDCHG*        boundchg            /**< bound change data */
17318	   )
17319	{
17320	   assert(boundchg != NULL);
17321	
17322	   return boundchg->newbound;
17323	}
17324	
17325	/** returns the variable of the bound change in the bound change data */
17326	SCIP_VAR* SCIPboundchgGetVar(
17327	   SCIP_BOUNDCHG*        boundchg            /**< bound change data */
17328	   )
17329	{
17330	   assert(boundchg != NULL);
17331	
17332	   return boundchg->var;
17333	}
17334	
17335	/** returns the bound change type of the bound change in the bound change data */
17336	SCIP_BOUNDCHGTYPE SCIPboundchgGetBoundchgtype(
17337	   SCIP_BOUNDCHG*        boundchg            /**< bound change data */
17338	   )
17339	{
17340	   assert(boundchg != NULL);
17341	
17342	   return (SCIP_BOUNDCHGTYPE)(boundchg->boundchgtype);
17343	}
17344	
17345	/** returns the bound type of the bound change in the bound change data */
17346	SCIP_BOUNDTYPE SCIPboundchgGetBoundtype(
17347	   SCIP_BOUNDCHG*        boundchg            /**< bound change data */
17348	   )
17349	{
17350	   assert(boundchg != NULL);
17351	
17352	   return (SCIP_BOUNDTYPE)(boundchg->boundtype);
17353	}
17354	
17355	/** returns whether the bound change is redundant due to a more global bound that is at least as strong */
17356	SCIP_Bool SCIPboundchgIsRedundant(
17357	   SCIP_BOUNDCHG*        boundchg            /**< bound change data */
17358	   )
17359	{
17360	   assert(boundchg != NULL);
17361	
17362	   return boundchg->redundant;
17363	}
17364	
17365	/** returns the number of bound changes in the domain change data */
17366	int SCIPdomchgGetNBoundchgs(
17367	   SCIP_DOMCHG*          domchg              /**< domain change data */
17368	   )
17369	{
17370	   return domchg != NULL ? domchg->domchgbound.nboundchgs : 0;
17371	}
17372	
17373	/** returns a particular bound change in the domain change data */
17374	SCIP_BOUNDCHG* SCIPdomchgGetBoundchg(
17375	   SCIP_DOMCHG*          domchg,             /**< domain change data */
17376	   int                   pos                 /**< position of the bound change in the domain change data */
17377	   )
17378	{
17379	   assert(domchg != NULL);
17380	   assert(0 <= pos && pos < (int)domchg->domchgbound.nboundchgs);
17381	
17382	   return &domchg->domchgbound.boundchgs[pos];
17383	}
17384	
17385	/** returns left bound of open interval in hole */
17386	SCIP_Real SCIPholelistGetLeft(
17387	   SCIP_HOLELIST*        holelist            /**< hole list pointer to hole of interest */
17388	   )
17389	{
17390	   assert(holelist != NULL);
17391	
17392	   return holelist->hole.left;
17393	}
17394	
17395	/** returns right bound of open interval in hole */
17396	SCIP_Real SCIPholelistGetRight(
17397	   SCIP_HOLELIST*        holelist            /**< hole list pointer to hole of interest */
17398	   )
17399	{
17400	   assert(holelist != NULL);
17401	
17402	   return holelist->hole.right;
17403	}
17404	
17405	/** returns next hole in list */
17406	SCIP_HOLELIST* SCIPholelistGetNext(
17407	   SCIP_HOLELIST*        holelist            /**< hole list pointer to hole of interest */
17408	   )
17409	{
17410	   assert(holelist != NULL);
17411	
17412	   return holelist->next;
17413	}
17414	
17415	/** returns the name of the variable
17416	 *
17417	 *  @note to change the name of a variable, use SCIPchgVarName() from scip.h
17418	 */
17419	const char* SCIPvarGetName(
17420	   SCIP_VAR*             var                 /**< problem variable */
17421	   )
17422	{
17423	   assert(var != NULL);
17424	
17425	   return var->name;
17426	}
17427	
17428	/** gets number of times, the variable is currently captured */
17429	int SCIPvarGetNUses(
17430	   SCIP_VAR*             var                 /**< problem variable */
17431	   )
17432	{
17433	   assert(var != NULL);
17434	
17435	   return var->nuses;
17436	}
17437	
17438	/** returns the user data of the variable */
17439	SCIP_VARDATA* SCIPvarGetData(
17440	   SCIP_VAR*             var                 /**< problem variable */
17441	   )
17442	{
17443	   assert(var != NULL);
17444	
17445	   return var->vardata;
17446	}
17447	
17448	/** sets the user data for the variable */
17449	void SCIPvarSetData(
17450	   SCIP_VAR*             var,                /**< problem variable */
17451	   SCIP_VARDATA*         vardata             /**< user variable data */
17452	   )
17453	{
17454	   assert(var != NULL);
17455	
17456	   var->vardata = vardata;
17457	}
17458	
17459	/** sets method to free user data for the original variable */
17460	void SCIPvarSetDelorigData(
17461	   SCIP_VAR*             var,                /**< problem variable */
17462	   SCIP_DECL_VARDELORIG  ((*vardelorig))     /**< frees user data of original variable */
17463	   )
17464	{
17465	   assert(var != NULL);
17466	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17467	
17468	   var->vardelorig = vardelorig;
17469	}
17470	
17471	/** sets method to transform user data of the variable */
17472	void SCIPvarSetTransData(
17473	   SCIP_VAR*             var,                /**< problem variable */
17474	   SCIP_DECL_VARTRANS    ((*vartrans))       /**< creates transformed user data by transforming original user data */
17475	   )
17476	{
17477	   assert(var != NULL);
17478	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17479	
17480	   var->vartrans = vartrans;
17481	}
17482	
17483	/** sets method to free transformed user data for the variable */
17484	void SCIPvarSetDeltransData(
17485	   SCIP_VAR*             var,                /**< problem variable */
17486	   SCIP_DECL_VARDELTRANS ((*vardeltrans))    /**< frees user data of transformed variable */
17487	   )
17488	{
17489	   assert(var != NULL);
17490	
17491	   var->vardeltrans = vardeltrans;
17492	}
17493	
17494	/** sets method to copy this variable into sub-SCIPs */
17495	void SCIPvarSetCopyData(
17496	   SCIP_VAR*             var,                /**< problem variable */
17497	   SCIP_DECL_VARCOPY     ((*varcopy))        /**< copy method of the variable */
17498	   )
17499	{
17500	   assert(var != NULL);
17501	
17502	   var->varcopy = varcopy;
17503	}
17504	
17505	/** sets the initial flag of a variable; only possible for original or loose variables */
17506	SCIP_RETCODE SCIPvarSetInitial(
17507	   SCIP_VAR*             var,                /**< problem variable */
17508	   SCIP_Bool             initial             /**< initial flag */
17509	   )
17510	{
17511	   assert(var != NULL);
17512	
17513	   if( (SCIP_VARSTATUS)var->varstatus != SCIP_VARSTATUS_ORIGINAL && (SCIP_VARSTATUS)var->varstatus != SCIP_VARSTATUS_LOOSE )
17514	      return SCIP_INVALIDCALL;
17515	
17516	   var->initial = initial;
17517	
17518	   return SCIP_OKAY;
17519	}
17520	
17521	/** sets the removable flag of a variable; only possible for original or loose variables */
17522	SCIP_RETCODE SCIPvarSetRemovable(
17523	   SCIP_VAR*             var,                /**< problem variable */
17524	   SCIP_Bool             removable           /**< removable flag */
17525	   )
17526	{
17527	   assert(var != NULL);
17528	
17529	   if( (SCIP_VARSTATUS)var->varstatus != SCIP_VARSTATUS_ORIGINAL && (SCIP_VARSTATUS)var->varstatus != SCIP_VARSTATUS_LOOSE )
17530	      return SCIP_INVALIDCALL;
17531	
17532	   var->removable = removable;
17533	
17534	   return SCIP_OKAY;
17535	}
17536	
17537	/** gets status of variable */
17538	SCIP_VARSTATUS SCIPvarGetStatus(
17539	   SCIP_VAR*             var                 /**< problem variable */
17540	   )
17541	{
17542	   assert(var != NULL);
17543	
17544	   return (SCIP_VARSTATUS)(var->varstatus);
17545	}
17546	
17547	/** returns whether the variable belongs to the original problem */
17548	SCIP_Bool SCIPvarIsOriginal(
17549	   SCIP_VAR*             var                 /**< problem variable */
17550	   )
17551	{
17552	   assert(var != NULL);
17553	   assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
17554	
17555	   return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL
17556	      || (SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED
17557	         && SCIPvarGetStatus(var->negatedvar) == SCIP_VARSTATUS_ORIGINAL));
17558	}
17559	
17560	/** returns whether the variable belongs to the transformed problem */
17561	SCIP_Bool SCIPvarIsTransformed(
17562	   SCIP_VAR*             var                 /**< problem variable */
17563	   )
17564	{
17565	   assert(var != NULL);
17566	   assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
17567	
17568	   return (SCIPvarGetStatus(var) != SCIP_VARSTATUS_ORIGINAL
17569	      && (SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED
17570	         || SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_ORIGINAL));
17571	}
17572	
17573	/** returns whether the variable was created by negation of a different variable */
17574	SCIP_Bool SCIPvarIsNegated(
17575	   SCIP_VAR*             var                 /**< problem variable */
17576	   )
17577	{
17578	   assert(var != NULL);
17579	
17580	   return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17581	}
17582	
17583	/** gets type of variable */
17584	SCIP_VARTYPE SCIPvarGetType(
17585	   SCIP_VAR*             var                 /**< problem variable */
17586	   )
17587	{
17588	   assert(var != NULL);
17589	
17590	   return (SCIP_VARTYPE)(var->vartype);
17591	}
17592	
17593	/** returns TRUE if the variable is of binary type; this is the case if:
17594	 *  (1) variable type is binary
17595	 *  (2) variable type is integer or implicit integer and 
17596	 *      (i)  the global lower bound is greater than or equal to zero
17597	 *      (ii) the global upper bound is less than or equal to one
17598	 */
17599	SCIP_Bool SCIPvarIsBinary(
17600	   SCIP_VAR*             var                 /**< problem variable */
17601	   )
17602	{
17603	   assert(var != NULL);
17604	
17605	   return (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY || 
17606	      (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && var->glbdom.lb >= 0.0 && var->glbdom.ub <= 1.0));
17607	}
17608	
17609	/** returns whether variable is of integral type (binary, integer, or implicit integer) */
17610	SCIP_Bool SCIPvarIsIntegral(
17611	   SCIP_VAR*             var                 /**< problem variable */
17612	   )
17613	{
17614	   assert(var != NULL);
17615	
17616	   return (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
17617	}
17618	
17619	/** returns whether variable's column should be present in the initial root LP */
17620	SCIP_Bool SCIPvarIsInitial(
17621	   SCIP_VAR*             var                 /**< problem variable */
17622	   )
17623	{
17624	   assert(var != NULL);
17625	
17626	   return var->initial;
17627	}
17628	
17629	/** returns whether variable's column is removable from the LP (due to aging or cleanup) */
17630	SCIP_Bool SCIPvarIsRemovable(
17631	   SCIP_VAR*             var                 /**< problem variable */
17632	   )
17633	{
17634	   assert(var != NULL);
17635	
17636	   return var->removable;
17637	}
17638	
17639	/** returns whether the variable was deleted from the problem */
17640	SCIP_Bool SCIPvarIsDeleted(
17641	   SCIP_VAR*             var                 /**< problem variable */
17642	   )
17643	{
17644	   assert(var != NULL);
17645	
17646	   return var->deleted;
17647	}
17648	
17649	/** marks the variable to be deletable, i.e., it may be deleted completely from the problem;
17650	 *  method can only be called before the variable is added to the problem by SCIPaddVar() or SCIPaddPricedVar()
17651	 */
17652	void SCIPvarMarkDeletable(
17653	   SCIP_VAR*             var                 /**< problem variable */
17654	   )
17655	{
17656	   assert(var != NULL);
17657	   assert(var->probindex == -1);
17658	
17659	   var->deletable = TRUE;
17660	}
17661	
17662	/** marks the variable to be not deletable from the problem */
17663	void SCIPvarMarkNotDeletable(
17664	   SCIP_VAR*             var
17665	   )
17666	{
17667	   assert(var != NULL);
17668	
17669	   var->deletable = FALSE;
17670	}
17671	
17672	/** marks variable to be deleted from global structures (cliques etc.) when cleaning up
17673	 *
17674	 *  @note: this is not equivalent to marking the variable itself for deletion, this is done by using SCIPvarMarkDeletable()
17675	 */
17676	void SCIPvarMarkDeleteGlobalStructures(
17677	   SCIP_VAR*             var                 /**< problem variable */
17678	   )
17679	{
17680	   assert(var != NULL);
17681	
17682	   var->delglobalstructs = TRUE;
17683	}
17684	
17685	/** returns whether the variable was flagged for deletion from global structures (cliques etc.) */
17686	SCIP_Bool SCIPvarIsMarkedDeleteGlobalStructures(
17687	   SCIP_VAR*             var                 /**< problem variable */
17688	   )
17689	{
17690	   assert(var != NULL);
17691	
17692	   return var->delglobalstructs;
17693	}
17694	
17695	/** returns whether a variable has been introduced to define a relaxation
17696	 *
17697	 * These variables are only valid for the current SCIP solve round,
17698	 * they are not contained in any (checked) constraints, but may be used
17699	 * in cutting planes, for example.
17700	 * Relaxation-only variables are not copied by SCIPcopyVars and cuts
17701	 * that contain these variables are not added as linear constraints when
17702	 * restarting or transferring information from a copied SCIP to a SCIP.
17703	 * Also conflicts with relaxation-only variables are not generated at
17704	 * the moment.
17705	 */
17706	SCIP_Bool SCIPvarIsRelaxationOnly(
17707	   SCIP_VAR*             var                 /**< problem variable */
17708	   )
17709	{
17710	   assert(var != NULL);
17711	
17712	   return var->relaxationonly;
17713	}
17714	
17715	/** marks that this variable has only been introduced to define a relaxation
17716	 *
17717	 * The variable must not have a coefficient in the objective and must be deletable.
17718	 * If it is not marked deletable, it will be marked as deletable, which is only possible
17719	 * before the variable is added to a problem.
17720	 *
17721	 * @see SCIPvarIsRelaxationOnly
17722	 * @see SCIPvarMarkDeletable
17723	 */
17724	void SCIPvarMarkRelaxationOnly(
17725	   SCIP_VAR*             var                 /**< problem variable */
17726	   )
17727	{
17728	   assert(var != NULL);
17729	   assert(SCIPvarGetObj(var) == 0.0);
17730	
17731	   if( !SCIPvarIsDeletable(var) )
17732	      SCIPvarMarkDeletable(var);
17733	
17734	   var->relaxationonly = TRUE;
17735	}
17736	
17737	/** returns whether variable is allowed to be deleted completely from the problem */
17738	SCIP_Bool SCIPvarIsDeletable(
17739	   SCIP_VAR*             var
17740	   )
17741	{
17742	   assert(var != NULL);
17743	
17744	   return var->deletable;
17745	}
17746	
17747	/** returns whether variable is an active (neither fixed nor aggregated) variable */
17748	SCIP_Bool SCIPvarIsActive(
17749	   SCIP_VAR*             var                 /**< problem variable */
17750	   )
17751	{
17752	   assert(var != NULL);
17753	
17754	   return (var->probindex >= 0);
17755	}
17756	
17757	/** gets unique index of variable */
17758	int SCIPvarGetIndex(
17759	   SCIP_VAR*             var                 /**< problem variable */
17760	   )
17761	{
17762	   assert(var != NULL);
17763	
17764	   return var->index;
17765	}
17766	
17767	/** gets position of variable in problem, or -1 if variable is not active */
17768	int SCIPvarGetProbindex(
17769	   SCIP_VAR*             var                 /**< problem variable */
17770	   )
17771	{
17772	   assert(var != NULL);
17773	
17774	   return var->probindex;
17775	}
17776	
17777	/** gets transformed variable of ORIGINAL variable */
17778	SCIP_VAR* SCIPvarGetTransVar(
17779	   SCIP_VAR*             var                 /**< problem variable */
17780	   )
17781	{
17782	   assert(var != NULL);
17783	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17784	
17785	   return var->data.original.transvar;
17786	}
17787	
17788	/** gets column of COLUMN variable */
17789	SCIP_COL* SCIPvarGetCol(
17790	   SCIP_VAR*             var                 /**< problem variable */
17791	   )
17792	{
17793	   assert(var != NULL);
17794	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
17795	
17796	   return var->data.col;
17797	}
17798	
17799	/** returns whether the variable is a COLUMN variable that is member of the current LP */
17800	SCIP_Bool SCIPvarIsInLP(
17801	   SCIP_VAR*             var                 /**< problem variable */
17802	   )
17803	{
17804	   assert(var != NULL);
17805	
17806	   return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN && SCIPcolIsInLP(var->data.col));
17807	}
17808	
17809	/** gets aggregation variable y of an aggregated variable x = a*y + c */
17810	SCIP_VAR* SCIPvarGetAggrVar(
17811	   SCIP_VAR*             var                 /**< problem variable */
17812	   )
17813	{
17814	   assert(var != NULL);
17815	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_AGGREGATED);
17816	   assert(!var->donotaggr);
17817	
17818	   return var->data.aggregate.var;
17819	}
17820	
17821	/** gets aggregation scalar a of an aggregated variable x = a*y + c */
17822	SCIP_Real SCIPvarGetAggrScalar(
17823	   SCIP_VAR*             var                 /**< problem variable */
17824	   )
17825	{
17826	   assert(var != NULL);
17827	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_AGGREGATED);
17828	   assert(!var->donotaggr);
17829	
17830	   return var->data.aggregate.scalar;
17831	}
17832	
17833	/** gets aggregation constant c of an aggregated variable x = a*y + c */
17834	SCIP_Real SCIPvarGetAggrConstant(
17835	   SCIP_VAR*             var                 /**< problem variable */
17836	   )
17837	{
17838	   assert(var != NULL);
17839	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_AGGREGATED);
17840	   assert(!var->donotaggr);
17841	
17842	   return var->data.aggregate.constant;
17843	}
17844	
17845	/** gets number n of aggregation variables of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17846	int SCIPvarGetMultaggrNVars(
17847	   SCIP_VAR*             var                 /**< problem variable */
17848	   )
17849	{
17850	   assert(var != NULL);
17851	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17852	   assert(!var->donotmultaggr);
17853	
17854	   return var->data.multaggr.nvars;
17855	}
17856	
17857	/** gets vector of aggregation variables y of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17858	SCIP_VAR** SCIPvarGetMultaggrVars(
17859	   SCIP_VAR*             var                 /**< problem variable */
17860	   )
17861	{
17862	   assert(var != NULL);
17863	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17864	   assert(!var->donotmultaggr);
17865	
17866	   return var->data.multaggr.vars;
17867	}
17868	
17869	/** gets vector of aggregation scalars a of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17870	SCIP_Real* SCIPvarGetMultaggrScalars(
17871	   SCIP_VAR*             var                 /**< problem variable */
17872	   )
17873	{
17874	   assert(var != NULL);
17875	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17876	   assert(!var->donotmultaggr);
17877	
17878	   return var->data.multaggr.scalars;
17879	}
17880	
17881	/** gets aggregation constant c of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17882	SCIP_Real SCIPvarGetMultaggrConstant(
17883	   SCIP_VAR*             var                 /**< problem variable */
17884	   )
17885	{
17886	   assert(var != NULL);
17887	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17888	   assert(!var->donotmultaggr);
17889	
17890	   return var->data.multaggr.constant;
17891	}
17892	
17893	/** gets the negation of the given variable; may return NULL, if no negation is existing yet */
17894	SCIP_VAR* SCIPvarGetNegatedVar(
17895	   SCIP_VAR*             var                 /**< negated problem variable */
17896	   )
17897	{
17898	   assert(var != NULL);
17899	
17900	   return var->negatedvar;
17901	}
17902	
17903	/** gets the negation variable x of a negated variable x' = offset - x */
17904	SCIP_VAR* SCIPvarGetNegationVar(
17905	   SCIP_VAR*             var                 /**< negated problem variable */
17906	   )
17907	{
17908	   assert(var != NULL);
17909	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17910	
17911	   return var->negatedvar;
17912	}
17913	
17914	/** gets the negation offset of a negated variable x' = offset - x */
17915	SCIP_Real SCIPvarGetNegationConstant(
17916	   SCIP_VAR*             var                 /**< negated problem variable */
17917	   )
17918	{
17919	   assert(var != NULL);
17920	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17921	
17922	   return var->data.negate.constant;
17923	}
17924	
17925	/** gets objective function value of variable */
17926	SCIP_Real SCIPvarGetObj(
17927	   SCIP_VAR*             var                 /**< problem variable */
17928	   )
17929	{
17930	   assert(var != NULL);
17931	
17932	   return var->obj;
17933	}
17934	
17935	/** gets the unchanged objective function value of a variable (ignoring temproray changes performed in probing mode) */
17936	SCIP_Real SCIPvarGetUnchangedObj(
17937	   SCIP_VAR*             var                 /**< problem variable */
17938	   )
17939	{
17940	   assert(var != NULL);
17941	
17942	   return var->unchangedobj;
17943	}
17944	
17945	/** gets corresponding objective value of active, fixed, or multi-aggregated problem variable of given variable
17946	 *  e.g. obj(x) = 1 this method returns for ~x the value -1
17947	 */
17948	SCIP_RETCODE SCIPvarGetAggregatedObj(
17949	   SCIP_VAR*             var,                /**< problem variable */
17950	   SCIP_Real*            aggrobj             /**< pointer to store the aggregated objective value */
17951	   )
17952	{
17953	   SCIP_VAR* probvar = var;
17954	   SCIP_Real mult = 1.0;
17955	
17956	   assert(probvar != NULL);
17957	   assert(aggrobj != NULL);
17958	
17959	   while( probvar != NULL )
17960	   {
17961	      switch( SCIPvarGetStatus(probvar) )
17962	      {
17963	      case SCIP_VARSTATUS_ORIGINAL:
17964	      case SCIP_VARSTATUS_LOOSE:
17965	      case SCIP_VARSTATUS_COLUMN:
17966		 (*aggrobj) = mult * SCIPvarGetObj(probvar);
17967		 return SCIP_OKAY;
17968	
17969	      case SCIP_VARSTATUS_FIXED:
17970		 assert(SCIPvarGetObj(probvar) == 0.0);
17971		 (*aggrobj) = 0.0;
17972	         return SCIP_OKAY;
17973	
17974	      case SCIP_VARSTATUS_MULTAGGR:
17975	         /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17976	         if ( probvar->data.multaggr.nvars == 1 )
17977	         {
17978	            assert( probvar->data.multaggr.vars != NULL );
17979	            assert( probvar->data.multaggr.scalars != NULL );
17980	            assert( probvar->data.multaggr.vars[0] != NULL );
17981	            mult *= probvar->data.multaggr.scalars[0];
17982	            probvar = probvar->data.multaggr.vars[0];
17983	            break;
17984	         }
17985		 else
17986		 {
17987		    SCIP_Real tmpobj;
17988		    int v;
17989	
17990		    (*aggrobj) = 0.0;
17991	
17992		    for( v = probvar->data.multaggr.nvars - 1; v >= 0; --v )
17993		    {
17994		       SCIP_CALL( SCIPvarGetAggregatedObj(probvar->data.multaggr.vars[v], &tmpobj) );
17995		       (*aggrobj) += probvar->data.multaggr.scalars[v] * tmpobj;
17996		    }
17997		    return SCIP_OKAY;
17998		 }
17999	
18000	      case SCIP_VARSTATUS_AGGREGATED:  /* x = a'*x' + c'  =>  a*x + c == (a*a')*x' + (a*c' + c) */
18001	         assert(probvar->data.aggregate.var != NULL);
18002	         mult *= probvar->data.aggregate.scalar;
18003	         probvar = probvar->data.aggregate.var;
18004	         break;
18005	
18006	      case SCIP_VARSTATUS_NEGATED:     /* x =  - x' + c'  =>  a*x + c ==   (-a)*x' + (a*c' + c) */
18007	         assert(probvar->negatedvar != NULL);
18008	         assert(SCIPvarGetStatus(probvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
18009	         assert(probvar->negatedvar->negatedvar == probvar);
18010	         mult *= -1.0;
18011	         probvar = probvar->negatedvar;
18012	         break;
18013	
18014	      default:
18015		 SCIPABORT();
18016		 return SCIP_INVALIDDATA; /*lint !e527*/
18017	      }
18018	   }
18019	
18020	   return SCIP_INVALIDDATA;
18021	}
18022	
18023	/** gets original lower bound of original problem variable (i.e. the bound set in problem creation) */
18024	SCIP_Real SCIPvarGetLbOriginal(
18025	   SCIP_VAR*             var                 /**< original problem variable */
18026	   )
18027	{
18028	   assert(var != NULL);
18029	   assert(SCIPvarIsOriginal(var));
18030	
18031	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL )
18032	      return var->data.original.origdom.lb;
18033	   else
18034	   {
18035	      assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
18036	      assert(var->negatedvar != NULL);
18037	      assert(SCIPvarGetStatus(var->negatedvar) == SCIP_VARSTATUS_ORIGINAL);
18038	
18039	      return var->data.negate.constant - var->negatedvar->data.original.origdom.ub;
18040	   }
18041	}
18042	
18043	/** gets original upper bound of original problem variable (i.e. the bound set in problem creation) */
18044	SCIP_Real SCIPvarGetUbOriginal(
18045	   SCIP_VAR*             var                 /**< original problem variable */
18046	   )
18047	{
18048	   assert(var != NULL);
18049	   assert(SCIPvarIsOriginal(var));
18050	
18051	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL )
18052	      return var->data.original.origdom.ub;
18053	   else
18054	   {
18055	      assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
18056	      assert(var->negatedvar != NULL);
18057	      assert(SCIPvarGetStatus(var->negatedvar) == SCIP_VARSTATUS_ORIGINAL);
18058	
18059	      return var->data.negate.constant - var->negatedvar->data.original.origdom.lb;
18060	   }
18061	}
18062	
18063	/** gets the original hole list of an original variable */
18064	SCIP_HOLELIST* SCIPvarGetHolelistOriginal(
18065	   SCIP_VAR*             var                 /**< problem variable */
18066	   )
18067	{
18068	   assert(var != NULL);
18069	   assert(SCIPvarIsOriginal(var));
18070	
18071	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL )
18072	      return var->data.original.origdom.holelist;
18073	
18074	   return NULL;
18075	}
18076	
18077	/** gets global lower bound of variable */
18078	SCIP_Real SCIPvarGetLbGlobal(
18079	   SCIP_VAR*             var                 /**< problem variable */
18080	   )
18081	{
18082	   assert(var != NULL);
18083	
18084	   return var->glbdom.lb;
18085	}
18086	
18087	/** gets global upper bound of variable */
18088	SCIP_Real SCIPvarGetUbGlobal(
18089	   SCIP_VAR*             var                 /**< problem variable */
18090	   )
18091	{
18092	   assert(var != NULL);
18093	
18094	   return var->glbdom.ub;
18095	}
18096	
18097	/** gets the global hole list of an active variable */
18098	SCIP_HOLELIST* SCIPvarGetHolelistGlobal(
18099	   SCIP_VAR*             var                 /**< problem variable */
18100	   )
18101	{
18102	   assert(var != NULL);
18103	
18104	   return var->glbdom.holelist;
18105	}
18106	
18107	/** gets best global bound of variable with respect to the objective function */
18108	SCIP_Real SCIPvarGetBestBoundGlobal(
18109	   SCIP_VAR*             var                 /**< problem variable */
18110	   )
18111	{
18112	   assert(var != NULL);
18113	
18114	   if( var->obj >= 0.0 )
18115	      return var->glbdom.lb;
18116	   else
18117	      return var->glbdom.ub;
18118	}
18119	
18120	/** gets worst global bound of variable with respect to the objective function */
18121	SCIP_Real SCIPvarGetWorstBoundGlobal(
18122	   SCIP_VAR*             var                 /**< problem variable */
18123	   )
18124	{
18125	   assert(var != NULL);
18126	
18127	   if( var->obj >= 0.0 )
18128	      return var->glbdom.ub;
18129	   else
18130	      return var->glbdom.lb;
18131	}
18132	
18133	/** gets current lower bound of variable */
18134	SCIP_Real SCIPvarGetLbLocal(
18135	   SCIP_VAR*             var                 /**< problem variable */
18136	   )
18137	{
18138	   assert(var != NULL);
18139	
18140	   return var->locdom.lb;
18141	}
18142	
18143	/** gets current upper bound of variable */
18144	SCIP_Real SCIPvarGetUbLocal(
18145	   SCIP_VAR*             var                 /**< problem variable */
18146	   )
18147	{
18148	   assert(var != NULL);
18149	
18150	   return var->locdom.ub;
18151	}
18152	
18153	/** gets the current hole list of an active variable */
18154	SCIP_HOLELIST* SCIPvarGetHolelistLocal(
18155	   SCIP_VAR*             var                 /**< problem variable */
18156	   )
18157	{
18158	   assert(var != NULL);
18159	
18160	   return var->locdom.holelist;
18161	}
18162	
18163	/** gets best local bound of variable with respect to the objective function */
18164	SCIP_Real SCIPvarGetBestBoundLocal(
18165	   SCIP_VAR*             var                 /**< problem variable */
18166	   )
18167	{
18168	   assert(var != NULL);
18169	
18170	   if( var->obj >= 0.0 )
18171	      return var->locdom.lb;
18172	   else
18173	      return var->locdom.ub;
18174	}
18175	
18176	/** gets worst local bound of variable with respect to the objective function */
18177	SCIP_Real SCIPvarGetWorstBoundLocal(
18178	   SCIP_VAR*             var                 /**< problem variable */
18179	   )
18180	{
18181	   assert(var != NULL);
18182	
18183	   if( var->obj >= 0.0 )
18184	      return var->locdom.ub;
18185	   else
18186	      return var->locdom.lb;
18187	}
18188	
18189	/** gets type (lower or upper) of best bound of variable with respect to the objective function */
18190	SCIP_BOUNDTYPE SCIPvarGetBestBoundType(
18191	   SCIP_VAR*             var                 /**< problem variable */
18192	   )
18193	{
18194	   assert(var != NULL);
18195	
18196	   if( var->obj >= 0.0 )
18197	      return SCIP_BOUNDTYPE_LOWER;
18198	   else
18199	      return SCIP_BOUNDTYPE_UPPER;
18200	}
18201	
18202	/** gets type (lower or upper) of worst bound of variable with respect to the objective function */
18203	SCIP_BOUNDTYPE SCIPvarGetWorstBoundType(
18204	   SCIP_VAR*             var                 /**< problem variable */
18205	   )
18206	{
18207	   assert(var != NULL);
18208	
18209	   if( var->obj >= 0.0 )
18210	      return SCIP_BOUNDTYPE_UPPER;
18211	   else
18212	      return SCIP_BOUNDTYPE_LOWER;
18213	}
18214	
18215	/** gets lazy lower bound of variable, returns -infinity if the variable has no lazy lower bound */
18216	SCIP_Real SCIPvarGetLbLazy(
18217	   SCIP_VAR*             var                 /**< problem variable */
18218	   )
18219	{
18220	   assert(var != NULL);
18221	
18222	   return var->lazylb;
18223	}
18224	
18225	/** gets lazy upper bound of variable, returns infinity if the variable has no lazy upper bound */
18226	SCIP_Real SCIPvarGetUbLazy(
18227	   SCIP_VAR*             var                 /**< problem variable */
18228	   )
18229	{
18230	   assert(var != NULL);
18231	
18232	   return var->lazyub;
18233	}
18234	
18235	/** gets the branch factor of the variable; this value can be used in the branching methods to scale the score
18236	 *  values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
18237	 */
18238	SCIP_Real SCIPvarGetBranchFactor(
18239	   SCIP_VAR*             var                 /**< problem variable */
18240	   )
18241	{
18242	   assert(var != NULL);
18243	
18244	   return var->branchfactor;
18245	}
18246	
18247	/** gets the branch priority of the variable; variables with higher priority should always be preferred to variables
18248	 *  with lower priority
18249	 */
18250	int SCIPvarGetBranchPriority(
18251	   SCIP_VAR*             var                 /**< problem variable */
18252	   )
18253	{
18254	   assert(var != NULL);
18255	
18256	   return var->branchpriority;
18257	}
18258	
18259	/** gets the preferred branch direction of the variable (downwards, upwards, or auto) */
18260	SCIP_BRANCHDIR SCIPvarGetBranchDirection(
18261	   SCIP_VAR*             var                 /**< problem variable */
18262	   )
18263	{
18264	   assert(var != NULL);
18265	
18266	   return (SCIP_BRANCHDIR)var->branchdirection;
18267	}
18268	
18269	/** gets number of variable lower bounds x >= b_i*z_i + d_i of given variable x */
18270	int SCIPvarGetNVlbs(
18271	   SCIP_VAR*             var                 /**< problem variable */
18272	   )
18273	{
18274	   assert(var != NULL);
18275	
18276	   return SCIPvboundsGetNVbds(var->vlbs);
18277	}
18278	
18279	/** gets array with bounding variables z_i in variable lower bounds x >= b_i*z_i + d_i of given variable x;
18280	 *  the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
18281	 */
18282	SCIP_VAR** SCIPvarGetVlbVars(
18283	   SCIP_VAR*             var                 /**< problem variable */
18284	   )
18285	{
18286	   assert(var != NULL);
18287	
18288	   return SCIPvboundsGetVars(var->vlbs);
18289	}
18290	
18291	/** gets array with bounding coefficients b_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
18292	SCIP_Real* SCIPvarGetVlbCoefs(
18293	   SCIP_VAR*             var                 /**< problem variable */
18294	   )
18295	{
18296	   assert(var != NULL);
18297	
18298	   return SCIPvboundsGetCoefs(var->vlbs);
18299	}
18300	
18301	/** gets array with bounding constants d_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
18302	SCIP_Real* SCIPvarGetVlbConstants(
18303	   SCIP_VAR*             var                 /**< problem variable */
18304	   )
18305	{
18306	   assert(var != NULL);
18307	
18308	   return SCIPvboundsGetConstants(var->vlbs);
18309	}
18310	
18311	/** gets number of variable upper bounds x <= b_i*z_i + d_i of given variable x */
18312	int SCIPvarGetNVubs(
18313	   SCIP_VAR*             var                 /**< problem variable */
18314	   )
18315	{
18316	   assert(var != NULL);
18317	
18318	   return SCIPvboundsGetNVbds(var->vubs);
18319	}
18320	
18321	/** gets array with bounding variables z_i in variable upper bounds x <= b_i*z_i + d_i of given variable x;
18322	 *  the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
18323	 */
18324	SCIP_VAR** SCIPvarGetVubVars(
18325	   SCIP_VAR*             var                 /**< problem variable */
18326	   )
18327	{
18328	   assert(var != NULL);
18329	
18330	   return SCIPvboundsGetVars(var->vubs);
18331	}
18332	
18333	/** gets array with bounding coefficients b_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
18334	SCIP_Real* SCIPvarGetVubCoefs(
18335	   SCIP_VAR*             var                 /**< problem variable */
18336	   )
18337	{
18338	   assert(var != NULL);
18339	
18340	   return SCIPvboundsGetCoefs(var->vubs);
18341	}
18342	
18343	/** gets array with bounding constants d_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
18344	SCIP_Real* SCIPvarGetVubConstants(
18345	   SCIP_VAR*             var                 /**< problem variable */
18346	   )
18347	{
18348	   assert(var != NULL);
18349	
18350	   return SCIPvboundsGetConstants(var->vubs);
18351	}
18352	
18353	/** gets number of implications  y <= b or y >= b for x == 0 or x == 1 of given active problem variable x, 
18354	 *  there are no implications for nonbinary variable x
18355	 */
18356	int SCIPvarGetNImpls(
18357	   SCIP_VAR*             var,                /**< active problem variable */
18358	   SCIP_Bool             varfixing           /**< FALSE for implications for x == 0, TRUE for x == 1 */
18359	   )
18360	{
18361	   assert(var != NULL);
18362	   assert(SCIPvarIsActive(var));
18363	
18364	   return SCIPimplicsGetNImpls(var->implics, varfixing);
18365	}
18366	
18367	/** gets array with implication variables y of implications  y <= b or y >= b for x == 0 or x == 1 of given active
18368	 *  problem variable x, there are no implications for nonbinary variable x;
18369	 *  the implications are sorted such that implications with binary implied variables precede the ones with non-binary
18370	 *  implied variables, and as a second criteria, the implied variables are sorted by increasing variable index
18371	 *  (see SCIPvarGetIndex())
18372	 */
18373	SCIP_VAR** SCIPvarGetImplVars(
18374	   SCIP_VAR*             var,                /**< active problem variable */
18375	   SCIP_Bool             varfixing           /**< FALSE for implications for x == 0, TRUE for x == 1 */
18376	   )
18377	{
18378	   assert(var != NULL);
18379	   assert(SCIPvarIsActive(var));
18380	
18381	   return SCIPimplicsGetVars(var->implics, varfixing);
18382	}
18383	
18384	/** gets array with implication types of implications  y <= b or y >= b for x == 0 or x == 1 of given active problem
18385	 *  variable x (SCIP_BOUNDTYPE_UPPER if y <= b, SCIP_BOUNDTYPE_LOWER if y >= b), 
18386	 *  there are no implications for nonbinary variable x
18387	 */
18388	SCIP_BOUNDTYPE* SCIPvarGetImplTypes(
18389	   SCIP_VAR*             var,                /**< active problem variable */
18390	   SCIP_Bool             varfixing           /**< FALSE for implications for x == 0, TRUE for x == 1 */
18391	   )
18392	{
18393	   assert(var != NULL);
18394	   assert(SCIPvarIsActive(var));
18395	
18396	   return SCIPimplicsGetTypes(var->implics, varfixing);
18397	}
18398	
18399	/** gets array with implication bounds b of implications  y <= b or y >= b for x == 0 or x == 1 of given active problem
18400	 *  variable x, there are no implications for nonbinary variable x
18401	 */
18402	SCIP_Real* SCIPvarGetImplBounds(
18403	   SCIP_VAR*             var,                /**< active problem variable */
18404	   SCIP_Bool             varfixing           /**< FALSE for implications for x == 0, TRUE for x == 1 */
18405	   )
18406	{
18407	   assert(var != NULL);
18408	   assert(SCIPvarIsActive(var));
18409	
18410	   return SCIPimplicsGetBounds(var->implics, varfixing);
18411	}
18412	
18413	/** Gets array with unique ids of implications  y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
18414	 *  there are no implications for nonbinary variable x.
18415	 *  If an implication is a shortcut, i.e., it was added as part of the transitive closure of another implication,
18416	 *  its id is negative, otherwise it is nonnegative.
18417	 */
18418	int* SCIPvarGetImplIds(
18419	   SCIP_VAR*             var,                /**< active problem variable */
18420	   SCIP_Bool             varfixing           /**< FALSE for implications for x == 0, TRUE for x == 1 */
18421	   )
18422	{
18423	   assert(var != NULL);
18424	   assert(SCIPvarIsActive(var));
18425	
18426	   return SCIPimplicsGetIds(var->implics, varfixing);
18427	}
18428	
18429	/** gets number of cliques, the active variable is contained in */
18430	int SCIPvarGetNCliques(
18431	   SCIP_VAR*             var,                /**< active problem variable */
18432	   SCIP_Bool             varfixing           /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
18433	   )
18434	{
18435	   assert(var != NULL);
18436	
18437	   return SCIPcliquelistGetNCliques(var->cliquelist, varfixing);
18438	}
18439	
18440	/** gets array of cliques, the active variable is contained in */
18441	SCIP_CLIQUE** SCIPvarGetCliques(
18442	   SCIP_VAR*             var,                /**< active problem variable */
18443	   SCIP_Bool             varfixing           /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
18444	   )
18445	{
18446	   assert(var != NULL);
18447	
18448	   return SCIPcliquelistGetCliques(var->cliquelist, varfixing);
18449	}
18450	
18451	/** gets primal LP solution value of variable */
18452	SCIP_Real SCIPvarGetLPSol(
18453	   SCIP_VAR*             var                 /**< problem variable */
18454	   )
18455	{
18456	   assert(var != NULL);
18457	
18458	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN )
18459	      return SCIPcolGetPrimsol(var->data.col);
18460	   else
18461	      return SCIPvarGetLPSol_rec(var);
18462	}
18463	
18464	/** gets primal NLP solution value of variable */
18465	SCIP_Real SCIPvarGetNLPSol(
18466	   SCIP_VAR*             var                 /**< problem variable */
18467	   )
18468	{
18469	   assert(var != NULL);
18470	
18471	   if( (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE) )
18472	      return var->nlpsol;
18473	   else
18474	      return SCIPvarGetNLPSol_rec(var);
18475	}
18476	
18477	/** return lower bound change info at requested position */
18478	SCIP_BDCHGINFO* SCIPvarGetBdchgInfoLb(
18479	   SCIP_VAR*             var,                /**< problem variable */
18480	   int                   pos                 /**< requested position */
18481	   )
18482	{
18483	   assert(pos >= 0);
18484	   assert(pos < var->nlbchginfos);
18485	
18486	   return &var->lbchginfos[pos];
18487	} 
18488	
18489	/** gets the number of lower bound change info array */
18490	int SCIPvarGetNBdchgInfosLb(
18491	   SCIP_VAR*             var                 /**< problem variable */
18492	   )
18493	{
18494	   return var->nlbchginfos;
18495	} 
18496	
18497	/** return upper bound change info at requested position */
18498	SCIP_BDCHGINFO* SCIPvarGetBdchgInfoUb(
18499	   SCIP_VAR*             var,                /**< problem variable */
18500	   int                   pos                 /**< requested position */
18501	   )
18502	{
18503	   assert(pos >= 0);
18504	   assert(pos < var->nubchginfos);
18505	
18506	   return &var->ubchginfos[pos];
18507	} 
18508	
18509	/** gets the number upper bound change info array */
18510	int SCIPvarGetNBdchgInfosUb(
18511	   SCIP_VAR*             var                 /**< problem variable */
18512	   )
18513	{
18514	   assert(var != NULL);
18515	
18516	   return var->nubchginfos;
18517	} 
18518	
18519	/** returns the value based history for the variable */
18520	SCIP_VALUEHISTORY* SCIPvarGetValuehistory(
18521	   SCIP_VAR*             var                 /**< problem variable */
18522	   )
18523	{
18524	   assert(var != NULL);
18525	
18526	   return var->valuehistory;
18527	}
18528	
18529	/** gets pseudo solution value of variable */
18530	SCIP_Real SCIPvarGetPseudoSol(
18531	   SCIP_VAR*             var                 /**< problem variable */
18532	   )
18533	{
18534	   assert(var != NULL);
18535	
18536	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN )
18537	      return SCIPvarGetBestBoundLocal(var);
18538	   else
18539	      return SCIPvarGetPseudoSol_rec(var);
18540	}
18541	
18542	/** returns the variable's VSIDS score */
18543	SCIP_Real SCIPvarGetVSIDS(
18544	   SCIP_VAR*             var,                /**< problem variable */
18545	   SCIP_STAT*            stat,               /**< problem statistics */
18546	   SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
18547	   )
18548	{
18549	   assert(var != NULL);
18550	
18551	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN )
18552	      return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
18553	   else
18554	      return SCIPvarGetVSIDS_rec(var, stat, dir);
18555	}
18556	
18557	/** includes event handler with given data in variable's event filter */
18558	SCIP_RETCODE SCIPvarCatchEvent(
18559	   SCIP_VAR*             var,                /**< problem variable */
18560	   BMS_BLKMEM*           blkmem,             /**< block memory */
18561	   SCIP_SET*             set,                /**< global SCIP settings */
18562	   SCIP_EVENTTYPE        eventtype,          /**< event type to catch */
18563	   SCIP_EVENTHDLR*       eventhdlr,          /**< event handler to call for the event processing */
18564	   SCIP_EVENTDATA*       eventdata,          /**< event data to pass to the event handler for the event processing */
18565	   int*                  filterpos           /**< pointer to store position of event filter entry, or NULL */
18566	   )
18567	{
18568	   assert(var != NULL);
18569	   assert(set != NULL);
18570	   assert(var->scip == set->scip);
18571	   assert(var->eventfilter != NULL);
18572	   assert((eventtype & ~SCIP_EVENTTYPE_VARCHANGED) == 0);
18573	   assert((eventtype & SCIP_EVENTTYPE_VARCHANGED) != 0);
18574	   assert(SCIPvarIsTransformed(var));
18575	
18576	   SCIPsetDebugMsg(set, "catch event of type 0x%" SCIP_EVENTTYPE_FORMAT " of variable <%s> with handler %p and data %p\n",
18577	      eventtype, var->name, (void*)eventhdlr, (void*)eventdata);
18578	
18579	   SCIP_CALL( SCIPeventfilterAdd(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
18580	
18581	   return SCIP_OKAY;
18582	}
18583	
18584	/** deletes event handler with given data from variable's event filter */
18585	SCIP_RETCODE SCIPvarDropEvent(
18586	   SCIP_VAR*             var,                /**< problem variable */
18587	   BMS_BLKMEM*           blkmem,             /**< block memory */
18588	   SCIP_SET*             set,                /**< global SCIP settings */
18589	   SCIP_EVENTTYPE        eventtype,          /**< event type mask of dropped event */
18590	   SCIP_EVENTHDLR*       eventhdlr,          /**< event handler to call for the event processing */
18591	   SCIP_EVENTDATA*       eventdata,          /**< event data to pass to the event handler for the event processing */
18592	   int                   filterpos           /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
18593	   )
18594	{
18595	   assert(var != NULL);
18596	   assert(set != NULL);
18597	   assert(var->scip == set->scip);
18598	   assert(var->eventfilter != NULL);
18599	   assert(SCIPvarIsTransformed(var));
18600	
18601	   SCIPsetDebugMsg(set, "drop event of variable <%s> with handler %p and data %p\n", var->name, (void*)eventhdlr,
18602	         (void*)eventdata);
18603	
18604	   SCIP_CALL( SCIPeventfilterDel(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
18605	
18606	   return SCIP_OKAY;
18607	}
18608	
18609	/** returns the position of the bound change index */
18610	int SCIPbdchgidxGetPos(
18611	   SCIP_BDCHGIDX*        bdchgidx            /**< bound change index */
18612	   )
18613	{
18614	   assert(bdchgidx != NULL);
18615	
18616	   return bdchgidx->pos;
18617	}
18618	
18619	/** returns whether first bound change index belongs to an earlier applied bound change than second one */
18620	SCIP_Bool SCIPbdchgidxIsEarlierNonNull(
18621	   SCIP_BDCHGIDX*        bdchgidx1,          /**< first bound change index */
18622	   SCIP_BDCHGIDX*        bdchgidx2           /**< second bound change index */
18623	   )
18624	{
18625	   assert(bdchgidx1 != NULL);
18626	   assert(bdchgidx1->depth >= -2);
18627	   assert(bdchgidx1->pos >= 0);
18628	   assert(bdchgidx2 != NULL);
18629	   assert(bdchgidx2->depth >= -2);
18630	   assert(bdchgidx2->pos >= 0);
18631	
18632	   return (bdchgidx1->depth < bdchgidx2->depth)
18633	      || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
18634	}
18635	
18636	/** returns whether first bound change index belongs to an earlier applied bound change than second one;
18637	 *  if a bound change index is NULL, the bound change index represents the current time, i.e. the time after the
18638	 *  last bound change was applied to the current node
18639	 */
18640	SCIP_Bool SCIPbdchgidxIsEarlier(
18641	   SCIP_BDCHGIDX*        bdchgidx1,          /**< first bound change index, or NULL */
18642	   SCIP_BDCHGIDX*        bdchgidx2           /**< second bound change index, or NULL */
18643	   )
18644	{
18645	   assert(bdchgidx1 == NULL || bdchgidx1->depth >= -2);
18646	   assert(bdchgidx1 == NULL || bdchgidx1->pos >= 0);
18647	   assert(bdchgidx2 == NULL || bdchgidx2->depth >= -2);
18648	   assert(bdchgidx2 == NULL || bdchgidx2->pos >= 0);
18649	
18650	   if( bdchgidx1 == NULL )
18651	      return FALSE;
18652	   else if( bdchgidx2 == NULL )
18653	      return TRUE;
18654	   else
18655	      return (bdchgidx1->depth < bdchgidx2->depth)
18656	         || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
18657	}
18658	
18659	/** returns old bound that was overwritten for given bound change information */
18660	SCIP_Real SCIPbdchginfoGetOldbound(
18661	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18662	   )
18663	{
18664	   assert(bdchginfo != NULL);
18665	
18666	   return bdchginfo->oldbound;
18667	}
18668	
18669	/** returns new bound installed for given bound change information */
18670	SCIP_Real SCIPbdchginfoGetNewbound(
18671	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18672	   )
18673	{
18674	   assert(bdchginfo != NULL);
18675	
18676	   return bdchginfo->newbound;
18677	}
18678	
18679	/** returns variable that belongs to the given bound change information */
18680	SCIP_VAR* SCIPbdchginfoGetVar(
18681	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18682	   )
18683	{
18684	   assert(bdchginfo != NULL);
18685	
18686	   return bdchginfo->var;
18687	}
18688	
18689	/** returns whether the bound change information belongs to a branching decision or a deduction */
18690	SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(
18691	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18692	   )
18693	{
18694	   assert(bdchginfo != NULL);
18695	
18696	   return (SCIP_BOUNDCHGTYPE)(bdchginfo->boundchgtype);
18697	}
18698	
18699	/** returns whether the bound change information belongs to a lower or upper bound change */
18700	SCIP_BOUNDTYPE SCIPbdchginfoGetBoundtype(
18701	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18702	   )
18703	{
18704	   assert(bdchginfo != NULL);
18705	
18706	   return (SCIP_BOUNDTYPE)(bdchginfo->boundtype);
18707	}
18708	
18709	/** returns depth level of given bound change information */
18710	int SCIPbdchginfoGetDepth(
18711	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18712	   )
18713	{
18714	   assert(bdchginfo != NULL);
18715	
18716	   return bdchginfo->bdchgidx.depth;
18717	}
18718	
18719	/** returns bound change position in its depth level of given bound change information */
18720	int SCIPbdchginfoGetPos(
18721	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18722	   )
18723	{
18724	   assert(bdchginfo != NULL);
18725	
18726	   return bdchginfo->bdchgidx.pos;
18727	}
18728	
18729	/** returns bound change index of given bound change information */
18730	SCIP_BDCHGIDX* SCIPbdchginfoGetIdx(
18731	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18732	   )
18733	{
18734	   assert(bdchginfo != NULL);
18735	
18736	   return &bdchginfo->bdchgidx;
18737	}
18738	
18739	/** returns inference variable of given bound change information */
18740	SCIP_VAR* SCIPbdchginfoGetInferVar(
18741	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18742	   )
18743	{
18744	   assert(bdchginfo != NULL);
18745	   assert((SCIP_BOUNDCHGTYPE)bdchginfo->boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER
18746	      || (SCIP_BOUNDCHGTYPE)bdchginfo->boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER);
18747	
18748	   return bdchginfo->inferencedata.var;
18749	}
18750	
18751	/** returns inference constraint of given bound change information */
18752	SCIP_CONS* SCIPbdchginfoGetInferCons(
18753	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18754	   )
18755	{
18756	   assert(bdchginfo != NULL);
18757	   assert((SCIP_BOUNDCHGTYPE)bdchginfo->boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER);
18758	   assert(bdchginfo->inferencedata.reason.cons != NULL);
18759	
18760	   return bdchginfo->inferencedata.reason.cons;
18761	}
18762	
18763	/** returns inference propagator of given bound change information, or NULL if no propagator was responsible */
18764	SCIP_PROP* SCIPbdchginfoGetInferProp(
18765	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18766	   )
18767	{
18768	   assert(bdchginfo != NULL);
18769	   assert((SCIP_BOUNDCHGTYPE)bdchginfo->boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER);
18770	
18771	   return bdchginfo->inferencedata.reason.prop;
18772	}
18773	
18774	/** returns inference user information of given bound change information */
18775	int SCIPbdchginfoGetInferInfo(
18776	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18777	   )
18778	{
18779	   assert(bdchginfo != NULL);
18780	   assert((SCIP_BOUNDCHGTYPE)bdchginfo->boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER
18781	      || (SCIP_BOUNDCHGTYPE)bdchginfo->boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER);
18782	
18783	   return bdchginfo->inferencedata.info;
18784	}
18785	
18786	/** returns inference bound of inference variable of given bound change information */
18787	SCIP_BOUNDTYPE SCIPbdchginfoGetInferBoundtype(
18788	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18789	   )
18790	{
18791	   assert(bdchginfo != NULL);
18792	   assert((SCIP_BOUNDCHGTYPE)bdchginfo->boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER
18793	      || (SCIP_BOUNDCHGTYPE)bdchginfo->boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER);
18794	
18795	   return (SCIP_BOUNDTYPE)(bdchginfo->inferboundtype);
18796	}
18797	
18798	/** returns the relaxed bound change type */
18799	SCIP_Real SCIPbdchginfoGetRelaxedBound(
18800	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change to add to the conflict set */
18801	   )
18802	{
18803	   return ((SCIP_BOUNDTYPE)(bdchginfo->boundtype) == SCIP_BOUNDTYPE_LOWER ? bdchginfo->var->conflictrelaxedlb : bdchginfo->var->conflictrelaxedub);
18804	}
18805	
18806	
18807	/** returns whether the bound change information belongs to a redundant bound change */
18808	SCIP_Bool SCIPbdchginfoIsRedundant(
18809	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18810	   )
18811	{
18812	   assert(bdchginfo != NULL);
18813	   assert(bdchginfo->redundant == (bdchginfo->oldbound == bdchginfo->newbound)); /*lint !e777*/
18814	
18815	   return bdchginfo->redundant;
18816	}
18817	
18818	/** returns whether the bound change has an inference reason (constraint or propagator), that can be resolved */
18819	SCIP_Bool SCIPbdchginfoHasInferenceReason(
18820	   SCIP_BDCHGINFO*       bdchginfo           /**< bound change information */
18821	   )
18822	{
18823	   assert(bdchginfo != NULL);
18824	
18825	   return ((SCIP_BOUNDCHGTYPE)bdchginfo->boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER)
18826	      || ((SCIP_BOUNDCHGTYPE)bdchginfo->boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER
18827	         && bdchginfo->inferencedata.reason.prop != NULL);
18828	}
18829	
18830	/** for two bound change informations belonging to the same variable and bound, returns whether the first bound change
18831	 *  has a tighter new bound as the second bound change
18832	 */
18833	SCIP_Bool SCIPbdchginfoIsTighter(
18834	   SCIP_BDCHGINFO*       bdchginfo1,         /**< first bound change information */
18835	   SCIP_BDCHGINFO*       bdchginfo2          /**< second bound change information */
18836	   )
18837	{
18838	   assert(bdchginfo1 != NULL);
18839	   assert(bdchginfo2 != NULL);
18840	   assert(bdchginfo1->var == bdchginfo2->var);
18841	   assert(bdchginfo1->boundtype == bdchginfo2->boundtype);
18842	
18843	   return (SCIPbdchginfoGetBoundtype(bdchginfo1) == SCIP_BOUNDTYPE_LOWER
18844	      ? bdchginfo1->newbound > bdchginfo2->newbound
18845	      : bdchginfo1->newbound < bdchginfo2->newbound);
18846	}
18847