1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This file is part of the program and library             */
4    	/*         SCIP --- Solving Constraint Integer Programs                      */
5    	/*                                                                           */
6    	/*    Copyright (C) 2002-2020 Konrad-Zuse-Zentrum                            */
7    	/*                            fuer Informationstechnik Berlin                */
8    	/*                                                                           */
9    	/*  SCIP is distributed under the terms of the ZIB Academic License.         */
10   	/*                                                                           */
11   	/*  You should have received a copy of the ZIB Academic License              */
12   	/*  along with SCIP; see the file COPYING. If not visit scipopt.org.         */
13   	/*                                                                           */
14   	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15   	
16   	/**@file   misc_rowprep.c
17   	 * @ingroup OTHER_CFILES
18   	 * @brief  linear inequalities in preparation
19   	 * @author Stefan Vigerske
20   	 * @author Benjamin Mueller
21   	 * @author Felipe Serrano
22   	 */
23   	
24   	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
25   	
26   	#include "scip/pub_misc_rowprep.h"
27   	#include "scip/pub_misc_sort.h"
28   	#include "scip/pub_var.h"
29   	#include "scip/scip_lp.h"
30   	#include "scip/scip_mem.h"
31   	#include "scip/scip_message.h"
32   	#include "scip/scip_numerics.h"
33   	#include "scip/scip_sepa.h"
34   	#include "scip/scip_sol.h"
35   	#include "scip/scip_tree.h"
36   	#include "scip/struct_misc.h"
37   	#include "scip/struct_scip.h"
38   	#include "scip/set.h"
39   	
40   	#define ROWPREP_SCALEUP_VIOLNONZERO    (10.0*SCIPepsilon(scip))    /**< minimal violation for considering up-scaling of rowprep (we want to avoid upscaling very small violations) */
41   	#define ROWPREP_SCALEUP_MINVIOLFACTOR  2.0                         /**< scale up will target a violation of ~MINVIOLFACTOR*minviol, where minviol is given by caller */
42   	#define ROWPREP_SCALEUP_MAXMINCOEF     (1.0 / SCIPfeastol(scip))   /**< scale up only if min. coef is below this number (before scaling) */
43   	#define ROWPREP_SCALEUP_MAXMAXCOEF     SCIPgetHugeValue(scip)      /**< scale up only if max. coef will not exceed this number by scaling */
44   	#define ROWPREP_SCALEUP_MAXSIDE        SCIPgetHugeValue(scip)      /**< scale up only if side will not exceed this number by scaling */
45   	#define ROWPREP_SCALEDOWN_MINMAXCOEF   (1.0 / SCIPfeastol(scip))   /**< scale down if max. coef is at least this number (before scaling) */
46   	#define ROWPREP_SCALEDOWN_MINCOEF      SCIPfeastol(scip)           /**< scale down only if min. coef does not drop below this number by scaling */
47   	
48   	#ifndef M_SQRT2
49   	#define M_SQRT2 sqrt(2.0)
50   	#endif
51   	
52   	/** adds a variable to the `rowprep->modifiedvars` array, if recording of modification has been enabled and the variable is not fixed */
53   	static
54   	SCIP_RETCODE rowprepRecordModifiedVar(
55   	   SCIP*                 scip,               /**< SCIP data structure */
56   	   SCIP_ROWPREP*         rowprep,            /**< rowprep */
57   	   SCIP_VAR*             var                 /**< variable to add */
58   	   )
59   	{
60   	   int oldsize;
61   	
62   	   if( !rowprep->recordmodifications )
63   	      return SCIP_OKAY;
64   	
65   	   /* do not record for fixed variables, as they are not suitable for branching */
66   	   if( SCIPisRelEQ(scip, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)) )
67   	   {
68   	      SCIPdebugMsg(scip, "skip recording modification for fixed variable <%s>[%g,%g]\n", SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var));
69   	      return SCIP_OKAY;
70   	   }
71   	
72   	   /* increase modifiedvars array size */
73   	   if( rowprep->nmodifiedvars >= rowprep->modifiedvarssize )
74   	   {
75   	      oldsize = rowprep->modifiedvarssize;
76   	      rowprep->modifiedvarssize = SCIPcalcMemGrowSize(scip, rowprep->nmodifiedvars + 1);
77   	
78   	      SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &rowprep->modifiedvars, oldsize, rowprep->modifiedvarssize) );
79   	   }
80   	
81   	   rowprep->modifiedvars[rowprep->nmodifiedvars] = var;
82   	   ++rowprep->nmodifiedvars;
83   	
84   	   return SCIP_OKAY;
85   	}
86   	
87   	/** sort terms by absolute value of coefficients, from largest to smallest */
88   	static
89   	SCIP_RETCODE rowprepCleanupSortTerms(
90   	   SCIP*                 scip,               /**< SCIP data structure */
91   	   SCIP_ROWPREP*         rowprep             /**< rowprep to be sorted */
92   	   )
93   	{
94   	   int i;
95   	
96   	   assert(scip != NULL);
97   	   assert(rowprep != NULL);
98   	
99   	   /* special treatment for cuts with few variables */
100  	   switch( rowprep->nvars )
101  	   {
102  	      case 0:
103  	      case 1:
104  	         break;
105  	
106  	      case 2:
107  	      {
108  	         if( REALABS(rowprep->coefs[0]) < REALABS(rowprep->coefs[1]) )
109  	         {
110  	            SCIP_Real tmp1;
111  	            SCIP_VAR* tmp2;
112  	
113  	            tmp1 = rowprep->coefs[0];
114  	            rowprep->coefs[0] = rowprep->coefs[1];
115  	            rowprep->coefs[1] = tmp1;
116  	
117  	            tmp2 = rowprep->vars[0];
118  	            rowprep->vars[0] = rowprep->vars[1];
119  	            rowprep->vars[1] = tmp2;
120  	         }
121  	         break;
122  	      }
123  	
124  	      default :
125  	      {
126  	         SCIP_Real* abscoefs;
127  	
128  	         SCIP_CALL( SCIPallocBufferArray(scip, &abscoefs, rowprep->nvars) );
129  	         for( i = 0; i < rowprep->nvars; ++i )
130  	            abscoefs[i] = REALABS(rowprep->coefs[i]);
131  	         SCIPsortDownRealRealPtr(abscoefs, rowprep->coefs, (void**)rowprep->vars, rowprep->nvars);
132  	         SCIPfreeBufferArray(scip, &abscoefs);
133  	      }
134  	   }
135  	
136  	   /* forget about coefs that are exactly zero (unlikely to have some) */
137  	   while( rowprep->nvars > 0 && rowprep->coefs[rowprep->nvars-1] == 0.0 )
138  	      --rowprep->nvars;
139  	
140  	   return SCIP_OKAY;
141  	}
142  	
143  	/** try to improve coef range by aggregating row with variable bounds
144  	 *
145  	 * Assumes terms have been sorted by rowprepCleanupSortTerms().
146  	 */
147  	static
148  	SCIP_RETCODE rowprepCleanupImproveCoefrange(
149  	   SCIP*                 scip,               /**< SCIP data structure */
150  	   SCIP_ROWPREP*         rowprep,            /**< rowprep to be improve */
151  	   SCIP_SOL*             sol,                /**< solution that we try to cut off, or NULL for LP solution */
152  	   SCIP_Real             maxcoefrange        /**< maximal allowed coefficients range */
153  	   )
154  	{
155  	   SCIP_VAR* var;
156  	   SCIP_Real lb;
157  	   SCIP_Real ub;
158  	   SCIP_Real ref;
159  	   SCIP_Real coef;
160  	   SCIP_Real mincoef;
161  	   SCIP_Real maxcoef;
162  	   SCIP_Real loss[2];
163  	   int maxcoefidx;
164  	   int pos;
165  	
166  	   maxcoefidx = 0;
167  	   if( rowprep->nvars > 0 )
168  	   {
169  	      maxcoef = REALABS(rowprep->coefs[0]);
170  	      mincoef = REALABS(rowprep->coefs[rowprep->nvars-1]);
171  	   }
172  	   else
173  	      mincoef = maxcoef = 1.0;
174  	
175  	   /* eliminate minimal or maximal coefs as long as coef range is too large
176  	    * this is likely going to eliminate coefs that are within eps of 0.0
177  	    * if not, then we do so after scaling (or should we enforce this here?)
178  	    */
179  	   while( maxcoef / mincoef > maxcoefrange  )
180  	   {
181  	      SCIPdebugMsg(scip, "cut coefficients have very large range: mincoef = %g maxcoef = %g\n", mincoef, maxcoef);
182  	
183  	      /* max/min can only be > 1 if there is more than one var
184  	       * we need this below for updating the max/min coef after eliminating a term
185  	       */
186  	      assert(rowprep->nvars > 1);
187  	
188  	      /* try to reduce coef range by aggregating with variable bounds
189  	       * that is, eliminate a term like a*x from a*x + ... <= side by adding -a*x <= -a*lb(x)
190  	       * with ref(x) the reference point we try to eliminate, this would weaken the cut by a*(lb(x)-ref(x))
191  	       *
192  	       * we consider eliminating either the term with maximal or the one with minimal coefficient,
193  	       * taking the one that leads to the least weakening of the cut
194  	       *
195  	       * TODO (suggested by @bzfserra, see !496):
196  	       * - Also one could think of not completely removing the coefficient but do an aggregation that makes the coefficient look better. For instance:
197  	       *   say you have $`a x + 0.1 y \leq r`$ and $`y`$ has only an upper bound, $`y \leq b`$,
198  	       *   then you can't really remove $`y`$. However, you could aggregate it with $`0.9 \cdot (y \leq b)`$ to get
199  	       *   $`a x + y \leq r + 0.9 b`$, which has better numerics (and hopefully still cuts the point... actually, if for the point you want to separate, $`y^* = b`$, then the violation is the same)
200  	       */
201  	
202  	      for( pos = 0; pos < 2; ++pos )
203  	      {
204  	         var = rowprep->vars[pos ? rowprep->nvars-1 : maxcoefidx];
205  	         coef = rowprep->coefs[pos ? rowprep->nvars-1 : maxcoefidx];
206  	         lb = SCIPvarGetLbLocal(var);
207  	         ub = SCIPvarGetUbLocal(var);
208  	         ref = SCIPgetSolVal(scip, sol, var);
209  	         assert(coef != 0.0);
210  	
211  	         /* make sure reference point is something reasonable within the bounds, preferable the value from the solution */
212  	         if( SCIPisInfinity(scip, REALABS(ref)) )
213  	            ref = 0.0;
214  	         ref = MAX(lb, MIN(ub, ref));
215  	
216  	         /* check whether we can eliminate coef*var from rowprep and how much we would loose w.r.t. ref(x) */
217  	         if( ((coef > 0.0 && rowprep->sidetype == SCIP_SIDETYPE_RIGHT) || (coef < 0.0 && rowprep->sidetype == SCIP_SIDETYPE_LEFT)) )
218  	         {
219  	            /* we would need to aggregate with -coef*var <= -coef*lb(x) */
220  	            if( SCIPisInfinity(scip, -lb) )
221  	               loss[pos] = SCIP_INVALID;
222  	            else
223  	               loss[pos] = REALABS(coef) * (ref - lb);
224  	         }
225  	         else
226  	         {
227  	            assert((coef < 0.0 && rowprep->sidetype == SCIP_SIDETYPE_RIGHT) || (coef > 0.0 && rowprep->sidetype == SCIP_SIDETYPE_LEFT));
228  	            /* we would need to aggregate with -coef*var >= -coef*ub(x) */
229  	            if( SCIPisInfinity(scip, ub) )
230  	               loss[pos] = SCIP_INVALID;
231  	            else
232  	               loss[pos] = REALABS(coef) * (ub - ref);
233  	         }
234  	         assert(loss[pos] >= 0.0);  /* assuming SCIP_INVALID >= 0 */
235  	
236  	         SCIPdebugMsg(scip, "aggregating %g*<%s> %c= ... with <%s>[%g] %c= %g looses %g\n",
237  	            coef, SCIPvarGetName(var), rowprep->sidetype == SCIP_SIDETYPE_RIGHT ? '<' : '>',
238  	            SCIPvarGetName(var), ref,
239  	            ((coef > 0.0 && rowprep->sidetype == SCIP_SIDETYPE_RIGHT) || (coef < 0.0 && rowprep->sidetype == SCIP_SIDETYPE_LEFT)) ? '>' : '<',
240  	            ((coef > 0.0 && rowprep->sidetype == SCIP_SIDETYPE_RIGHT) || (coef < 0.0 && rowprep->sidetype == SCIP_SIDETYPE_LEFT)) ? lb : ub, loss[pos]);
241  	      }
242  	
243  	      /*lint --e{777} */
244  	      if( loss[0] == SCIP_INVALID && loss[1] == SCIP_INVALID )
245  	         break;  /* cannot eliminate coefficient */
246  	
247  	      /* select position with smaller loss */
248  	      pos = (loss[1] == SCIP_INVALID || loss[1] > loss[0]) ? 0 : 1;
249  	
250  	      /* now do the actual elimination */
251  	      var = rowprep->vars[pos ? rowprep->nvars-1 : maxcoefidx];
252  	      coef = rowprep->coefs[pos ? rowprep->nvars-1 : maxcoefidx];
253  	
254  	      /* eliminate coef*var from rowprep: increase side */
255  	      if( ((coef > 0.0 && rowprep->sidetype == SCIP_SIDETYPE_RIGHT) || (coef < 0.0 && rowprep->sidetype == SCIP_SIDETYPE_LEFT)) )
256  	      {
257  	         /* we aggregate with -coef*var <= -coef*lb(x) */
258  	         assert(!SCIPisInfinity(scip, -SCIPvarGetLbLocal(var)));
259  	         SCIProwprepAddConstant(rowprep, coef * SCIPvarGetLbLocal(var));
260  	         rowprep->local |= SCIPisGT(scip, SCIPvarGetLbLocal(var), SCIPvarGetLbGlobal(var));
261  	      }
262  	      else
263  	      {
264  	         assert((coef < 0.0 && rowprep->sidetype == SCIP_SIDETYPE_RIGHT) || (coef > 0.0 && rowprep->sidetype == SCIP_SIDETYPE_LEFT));
265  	         /* we aggregate with -coef*var >= -coef*ub(x) */
266  	         assert(!SCIPisInfinity(scip, SCIPvarGetUbLocal(var)));
267  	         SCIProwprepAddConstant(rowprep, coef * SCIPvarGetUbLocal(var));
268  	         rowprep->local |= SCIPisLT(scip, SCIPvarGetUbLocal(var), SCIPvarGetUbGlobal(var));
269  	      }
270  	
271  	      /* eliminate coef*var from rowprep: remove coef */
272  	      if( pos == 0 )
273  	      {
274  	         /* set first term to zero */
275  	         rowprep->coefs[maxcoefidx] = 0.0;
276  	
277  	         /* update index */
278  	         ++maxcoefidx;
279  	
280  	         /* update maxcoef */
281  	         maxcoef = REALABS(rowprep->coefs[maxcoefidx]);
282  	      }
283  	      else
284  	      {
285  	         /* forget last term */
286  	         --rowprep->nvars;
287  	
288  	         /* update mincoef */
289  	         mincoef = REALABS(rowprep->coefs[rowprep->nvars-1]);
290  	      }
291  	
292  	      /* (potentially) remember the variable that has been removed here */
293  	      SCIP_CALL( rowprepRecordModifiedVar(scip, rowprep, var) );
294  	   }
295  	
296  	   /* if maximal coefs were removed, then there are now 0's in the beginning of the coefs array
297  	    * -> move all remaining coefs and vars up front
298  	    */
299  	   if( maxcoefidx > 0 )
300  	   {
301  	      int i;
302  	      for( i = maxcoefidx; i < rowprep->nvars; ++i )
303  	      {
304  	         rowprep->vars[i-maxcoefidx] = rowprep->vars[i];
305  	         rowprep->coefs[i-maxcoefidx] = rowprep->coefs[i];
306  	      }
307  	      rowprep->nvars -= maxcoefidx;
308  	   }
309  	
310  	   return SCIP_OKAY;
311  	}
312  	
313  	
314  	/** scales up rowprep if it seems useful */
315  	static
316  	void rowprepCleanupScaleup(
317  	   SCIP*                 scip,               /**< SCIP data structure */
318  	   SCIP_ROWPREP*         rowprep,            /**< rowprep to be improve */
319  	   SCIP_Real*            viol,               /**< violation of cut in sol (input and output) */
320  	   SCIP_Real             minviol             /**< minimal violation we try to achieve */
321  	   )
322  	{
323  	   SCIP_Real scalefactor;
324  	   SCIP_Real mincoef;
325  	   SCIP_Real maxcoef;
326  	
327  	   assert(scip != NULL);
328  	   assert(rowprep != NULL);
329  	   assert(viol != NULL);
330  	
331  	   /* if violation is very small than better don't scale up */
332  	   if( *viol < ROWPREP_SCALEUP_VIOLNONZERO )
333  	      return;
334  	
335  	   /* if violation is already above minviol, then nothing to do */
336  	   if( *viol >= minviol )
337  	      return;
338  	   assert(!SCIPisInfinity(scip, *viol));
339  	
340  	   /* if violation is sufficiently positive (>10*eps), but has not reached minviol,
341  	    * then consider scaling up to reach approx MINVIOLFACTOR*minviol
342  	    */
343  	   scalefactor = ROWPREP_SCALEUP_MINVIOLFACTOR * minviol / *viol;
344  	
345  	   /* scale by approx. scalefactor, if minimal coef is not so large yet and maximal coef and rhs don't get huge by doing so (or have been so before) */
346  	   mincoef = rowprep->nvars > 0 ? REALABS(rowprep->coefs[rowprep->nvars-1]) : 1.0;
347  	   maxcoef = rowprep->nvars > 0 ? REALABS(rowprep->coefs[0]) : 1.0;
348  	   if( mincoef < ROWPREP_SCALEUP_MAXMINCOEF && scalefactor * maxcoef < ROWPREP_SCALEUP_MAXMAXCOEF && scalefactor * REALABS(rowprep->side) < ROWPREP_SCALEUP_MAXSIDE )
349  	   {
350  	      int scaleexp;
351  	
352  	      /* SCIPinfoMessage(scip, NULL, "scale up by ~%g, viol=%g: ", scalefactor, myviol);
353  	         SCIPprintRowprep(scip, rowprep, NULL); */
354  	
355  	      /* SCIPscaleRowprep returns the actually applied scale factor */
356  	      scaleexp = SCIPscaleRowprep(rowprep, scalefactor);
357  	      *viol = ldexp(*viol, scaleexp);
358  	
359  	      /* SCIPinfoMessage(scip, NULL, "scaled up by %g, viol=%g: ", ldexp(1.0, scaleexp), myviol);
360  	         SCIPprintRowprep(scip, rowprep, NULL); */
361  	   }
362  	}
363  	
364  	/** scales down rowprep if it improves coefs and keeps rowprep violated */
365  	static
366  	void rowprepCleanupScaledown(
367  	   SCIP*                 scip,               /**< SCIP data structure */
368  	   SCIP_ROWPREP*         rowprep,            /**< rowprep to be improve */
369  	   SCIP_Real*            viol,               /**< violation of cut in sol (input and output) */
370  	   SCIP_Real             minviol             /**< minimal violation we try to keep */
371  	   )
372  	{
373  	   SCIP_Real scalefactor;
374  	
375  	   /* if maxcoef < ROWPREP_SCALEDOWN_MINMAXCOEF (or no terms), then don't consider scaling down */
376  	   if( rowprep->nvars == 0 || REALABS(rowprep->coefs[0]) < ROWPREP_SCALEDOWN_MINMAXCOEF )
377  	      return;
378  	
379  	   /* consider scaling down so that maxcoef ~ 10 */
380  	   scalefactor = 10.0 / REALABS(rowprep->coefs[0]);
381  	
382  	   /* if minimal violation would be lost by scaling down, then increase scalefactor such that minviol is still reached */
383  	   if( *viol > minviol && !SCIPisInfinity(scip, *viol) && scalefactor * *viol < minviol )
384  	   {
385  	      assert(minviol > 0.0);  /* since viol >= 0, the if-condition should ensure that minviol > 0 */
386  	      assert(*viol > 0.0);    /* since minviol > 0, the if-condition ensures viol > 0 */
387  	      scalefactor = ROWPREP_SCALEUP_MINVIOLFACTOR * minviol / *viol;
388  	   }
389  	
390  	   /* scale by approx. scalefactor if scaling down and minimal coef does not get too small
391  	    * myviol < minviol (-> scalefactor > 1) or mincoef < feastol before scaling is possible, in which case we also don't scale down
392  	    */
393  	   if( scalefactor < 1.0 && scalefactor * REALABS(rowprep->coefs[rowprep->nvars-1]) > ROWPREP_SCALEDOWN_MINCOEF )
394  	   {
395  	      int scaleexp;
396  	
397  	      /* SCIPinfoMessage(scip, NULL, "scale down by ~%g, viol=%g: ", scalefactor, myviol);
398  	         SCIPprintRowprep(scip, rowprep, NULL); */
399  	
400  	      scaleexp = SCIPscaleRowprep(rowprep, scalefactor);
401  	      if( !SCIPisInfinity(scip, *viol) )
402  	         *viol = ldexp(*viol, scaleexp);
403  	
404  	      /* SCIPinfoMessage(scip, NULL, "scaled down by %g, viol=%g: ", ldexp(1.0, scaleexp), myviol);
405  	         SCIPprintRowprep(scip, rowprep, NULL); */
406  	   }
407  	}
408  	
409  	/** rounds almost integral coefs to integrals, thereby trying to relax the cut */
410  	static
411  	SCIP_RETCODE rowprepCleanupIntegralCoefs(
412  	   SCIP*                 scip,               /**< SCIP data structure */
413  	   SCIP_ROWPREP*         rowprep,            /**< rowprep to be improve */
414  	   SCIP_Real*            viol                /**< NULL or violation of cut in sol (input), set to SCIP_INVALID if some coef changed */
415  	   )
416  	{
417  	   SCIP_Real coef;
418  	   SCIP_Real roundcoef;
419  	   int i;
420  	
421  	   assert(scip != NULL);
422  	   assert(rowprep != NULL);
423  	
424  	   /* Coefficients smaller than epsilon are rounded to 0.0 when added to row and
425  	    * coefficients very close to integral values are rounded to integers when added to LP.
426  	    * Both cases can be problematic if variable value is very large (bad numerics).
427  	    * Thus, we anticipate by rounding coef here, but also modify constant so that cut is still valid (if possible),
428  	    * i.e., bound coef[i]*x by round(coef[i])*x + (coef[i]-round(coef[i])) * bound(x).
429  	    * Or in other words, we aggregate with the variable bound.
430  	    *
431  	    * If the required bound of x is not finite, then only round coef (introduces an error).
432  	    * @TODO If only the opposite bound is available, then one could move the coefficient
433  	    *   away from the closest integer so that the SCIP_ROW won't try to round it.
434  	    */
435  	   for( i = 0; i < rowprep->nvars; ++i )
436  	   {
437  	      coef = rowprep->coefs[i];
438  	      roundcoef = SCIPround(scip, coef);
439  	      if( coef != roundcoef && SCIPisEQ(scip, coef, roundcoef) ) /*lint !e777*/
440  	      {
441  	         SCIP_Real xbnd;
442  	         SCIP_VAR* var;
443  	
444  	         var = rowprep->vars[i];
445  	         if( rowprep->sidetype == SCIP_SIDETYPE_RIGHT )
446  	            if( rowprep->local )
447  	               xbnd = coef > roundcoef ? SCIPvarGetLbLocal(var)  : SCIPvarGetUbLocal(var);
448  	            else
449  	               xbnd = coef > roundcoef ? SCIPvarGetLbGlobal(var) : SCIPvarGetUbGlobal(var);
450  	         else
451  	            if( rowprep->local )
452  	               xbnd = coef > roundcoef ? SCIPvarGetUbLocal(var)  : SCIPvarGetLbLocal(var);
453  	            else
454  	               xbnd = coef > roundcoef ? SCIPvarGetUbGlobal(var) : SCIPvarGetLbGlobal(var);
455  	
456  	         if( !SCIPisInfinity(scip, REALABS(xbnd)) )
457  	         {
458  	            /* if there is a bound, then relax row side so rounding coef will not introduce an error */
459  	            SCIPdebugMsg(scip, "var <%s> [%g,%g] has almost integral coef %.15g, round coefficient to %g and add constant %g\n",
460  	               SCIPvarGetName(var), SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var), coef, roundcoef, (coef-roundcoef) * xbnd);
461  	            SCIProwprepAddConstant(rowprep, (coef-roundcoef) * xbnd);
462  	         }
463  	         else
464  	         {
465  	            /* if there is no bound, then we make the coef integral, too, even though this will introduce an error
466  	             * however, SCIP_ROW would do this anyway, but doing this here might eliminate some epsilon coefs (so they don't determine mincoef below)
467  	             * and helps to get a more accurate row violation value
468  	             */
469  	            SCIPdebugMsg(scip, "var <%s> [%g,%g] has almost integral coef %.15g, round coefficient to %g without relaxing side (!)\n",
470  	               SCIPvarGetName(var), SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var), coef, roundcoef);
471  	         }
472  	         rowprep->coefs[i] = roundcoef;
473  	         if( viol != NULL )
474  	            *viol = SCIP_INVALID;
475  	
476  	         /* (potentially) remember the variable which coef has been modified here */
477  	         SCIP_CALL( rowprepRecordModifiedVar(scip, rowprep, var) );
478  	      }
479  	   }
480  	
481  	   /* forget about coefs that became exactly zero by the above step */
482  	   while( rowprep->nvars > 0 && rowprep->coefs[rowprep->nvars-1] == 0.0 )
483  	      --rowprep->nvars;
484  	
485  	   return SCIP_OKAY;
486  	}
487  	
488  	/** relaxes almost zero side */
489  	static
490  	void rowprepCleanupSide(
491  	   SCIP*                 scip,               /**< SCIP data structure */
492  	   SCIP_ROWPREP*         rowprep,            /**< rowprep to be improve */
493  	   SCIP_Real*            viol                /**< NULL or violation of cut in sol (input), set to SCIP_INVALID if some coef changed */
494  	   )
495  	{
496  	   /* SCIP_ROW handling will replace a side close to 0 by 0.0, even if that makes the row more restrictive
497  	    * we thus relax the side here so that it will either be 0 now or will not be rounded to 0 later
498  	    */
499  	   if( rowprep->side == 0.0 || !SCIPisZero(scip, rowprep->side) )
500  	      return;
501  	
502  	   if( rowprep->side > 0.0 && rowprep->sidetype == SCIP_SIDETYPE_RIGHT )
503  	      rowprep->side =  1.1*SCIPepsilon(scip);
504  	   else if( rowprep->side < 0.0 && rowprep->sidetype == SCIP_SIDETYPE_LEFT )
505  	      rowprep->side = -1.1*SCIPepsilon(scip);
506  	   else
507  	      rowprep->side = 0.0;
508  	
509  	   if( rowprep->recordmodifications )
510  	      rowprep->modifiedside = TRUE;
511  	
512  	   if( viol != NULL )
513  	      *viol = SCIP_INVALID;
514  	}
515  	
516  	/** creates a SCIP_ROWPREP datastructure
517  	 *
518  	 * Initial row represents 0 &le; 0.
519  	 */
520  	SCIP_RETCODE SCIPcreateRowprep(
521  	   SCIP*                 scip,               /**< SCIP data structure */
522  	   SCIP_ROWPREP**        rowprep,            /**< buffer to store pointer to rowprep */
523  	   SCIP_SIDETYPE         sidetype,           /**< whether cut will be or lower-equal or larger-equal type */
524  	   SCIP_Bool             local               /**< whether cut will be valid only locally */
525  	   )
526  	{
527  	   assert(scip != NULL);
528  	   assert(rowprep != NULL);
529  	
530  	   SCIP_CALL( SCIPallocBlockMemory(scip, rowprep) );
531  	   BMSclearMemory(*rowprep);
532  	
533  	   (*rowprep)->sidetype = sidetype;
534  	   (*rowprep)->local = local;
535  	
536  	   return SCIP_OKAY;
537  	}
538  	
539  	/** frees a SCIP_ROWPREP datastructure */
540  	void SCIPfreeRowprep(
541  	   SCIP*                 scip,               /**< SCIP data structure */
542  	   SCIP_ROWPREP**        rowprep             /**< pointer that stores pointer to rowprep */
543  	   )
544  	{
545  	   assert(scip != NULL);
546  	   assert(rowprep != NULL);
547  	   assert(*rowprep != NULL);
548  	
549  	   SCIPfreeBlockMemoryArrayNull(scip, &(*rowprep)->vars, (*rowprep)->varssize);
550  	   SCIPfreeBlockMemoryArrayNull(scip, &(*rowprep)->coefs, (*rowprep)->varssize);
551  	   SCIPfreeBlockMemoryArrayNull(scip, &(*rowprep)->modifiedvars, (*rowprep)->modifiedvarssize);
552  	   SCIPfreeBlockMemory(scip, rowprep);
553  	}
554  	
555  	/** creates a copy of a SCIP_ROWPREP datastructure */
556  	SCIP_RETCODE SCIPcopyRowprep(
557  	   SCIP*                 scip,               /**< SCIP data structure */
558  	   SCIP_ROWPREP**        target,             /**< buffer to store pointer of rowprep copy */
559  	   SCIP_ROWPREP*         source              /**< rowprep to copy */
560  	   )
561  	{
562  	   assert(scip != NULL);
563  	   assert(target != NULL);
564  	   assert(source != NULL);
565  	
566  	   SCIP_CALL( SCIPduplicateBlockMemory(scip, target, source) );
567  	   if( source->coefs != NULL )
568  	   {
569  	      SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*target)->coefs, source->coefs, source->varssize) );
570  	   }
571  	   if( source->vars != NULL )
572  	   {
573  	      SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*target)->vars, source->vars, source->varssize) );
574  	   }
575  	
576  	   (*target)->recordmodifications = FALSE;
577  	   (*target)->modifiedvars = NULL;
578  	   (*target)->modifiedvarssize = 0;
579  	   (*target)->nmodifiedvars = 0;
580  	   (*target)->modifiedside = FALSE;
581  	
582  	   return SCIP_OKAY;
583  	}
584  	
585  	/** gives number of terms in rowprep */
586  	int SCIProwprepGetNVars(
587  	   SCIP_ROWPREP*         rowprep             /**< rowprep */
588  	   )
589  	{
590  	   assert(rowprep != NULL);
591  	
592  	   return rowprep->nvars;
593  	}
594  	
595  	/** gives variables of rowprep (feel free to modify) */
596  	SCIP_VAR** SCIProwprepGetVars(
597  	   SCIP_ROWPREP*         rowprep             /**< rowprep */
598  	   )
599  	{
600  	   assert(rowprep != NULL);
601  	
602  	   return rowprep->vars;
603  	}
604  	
605  	/** gives coefficients of rowprep (feel free to modify) */
606  	SCIP_Real* SCIProwprepGetCoefs(
607  	   SCIP_ROWPREP*         rowprep             /**< rowprep */
608  	   )
609  	{
610  	   assert(rowprep != NULL);
611  	
612  	   return rowprep->coefs;
613  	}
614  	
615  	/** gives side of rowprep */
616  	SCIP_Real SCIProwprepGetSide(
617  	   SCIP_ROWPREP*         rowprep             /**< rowprep */
618  	   )
619  	{
620  	   assert(rowprep != NULL);
621  	
622  	   return rowprep->side;
623  	}
624  	
625  	/** gives kind of inequality of rowprep */
626  	SCIP_SIDETYPE SCIProwprepGetSidetype(
627  	   SCIP_ROWPREP*         rowprep             /**< rowprep */
628  	   )
629  	{
630  	   assert(rowprep != NULL);
631  	
632  	   return rowprep->sidetype;
633  	}
634  	
635  	/** returns whether rowprep is locally valid only */
636  	SCIP_Bool SCIProwprepIsLocal(
637  	   SCIP_ROWPREP*         rowprep             /**< rowprep */
638  	   )
639  	{
640  	   assert(rowprep != NULL);
641  	
642  	   return rowprep->local;
643  	}
644  	
645  	/** returns name of rowprep (feel free to modify) */
646  	char* SCIProwprepGetName(
647  	   SCIP_ROWPREP*         rowprep             /**< rowprep */
648  	   )
649  	{
650  	   assert(rowprep != NULL);
651  	
652  	   return rowprep->name;
653  	}
654  	
655  	/** returns number of variables which coefficients were modified in cleanup */
656  	int SCIProwprepGetNModifiedVars(
657  	   SCIP_ROWPREP*         rowprep             /**< rowprep */
658  	   )
659  	{
660  	   assert(rowprep != NULL);
661  	
662  	   return rowprep->nmodifiedvars;
663  	}
664  	
665  	/** returns variables which coefficients were modified in cleanup */
666  	SCIP_VAR** SCIProwprepGetModifiedVars(
667  	   SCIP_ROWPREP*         rowprep             /**< rowprep */
668  	   )
669  	{
670  	   assert(rowprep != NULL);
671  	
672  	   return rowprep->modifiedvars;
673  	}
674  	
675  	/** resets rowprep to have 0 terms and side 0.0 */
676  	void SCIProwprepReset(
677  	   SCIP_ROWPREP*         rowprep             /**< rowprep */
678  	   )
679  	{
680  	   assert(rowprep != NULL);
681  	
682  	   rowprep->nvars = 0;
683  	   rowprep->side = 0.0;
684  	
685  	   rowprep->recordmodifications = FALSE;
686  	   rowprep->nmodifiedvars = 0;
687  	   rowprep->modifiedside = FALSE;
688  	}
689  	
690  	#ifdef NDEBUG
691  	#undef SCIProwprepAddSide
692  	#undef SCIProwprepAddConstant
693  	#endif
694  	
695  	/** adds constant value to side of rowprep */
696  	void SCIProwprepAddSide(
697  	   SCIP_ROWPREP*         rowprep,            /**< rowprep */
698  	   SCIP_Real             side                /**< constant value to be added to side */
699  	   )
700  	{
701  	   assert(rowprep != NULL);
702  	
703  	   rowprep->side += side;
704  	}
705  	
706  	/** adds constant term to rowprep
707  	 *
708  	 * Substracts constant from side.
709  	 */
710  	void SCIProwprepAddConstant(
711  	   SCIP_ROWPREP*         rowprep,            /**< rowprep */
712  	   SCIP_Real             constant            /**< constant value to be added */
713  	   )
714  	{
715  	   SCIProwprepAddSide(rowprep, -constant);
716  	}
717  	
718  	/** sets side type of rowprep */
719  	void SCIProwprepSetSidetype(
720  	   SCIP_ROWPREP*         rowprep,            /**< rowprep */
721  	   SCIP_SIDETYPE         sidetype            /**< new side type */
722  	   )
723  	{
724  	   assert(rowprep != NULL);
725  	
726  	   rowprep->sidetype = sidetype;
727  	}
728  	
729  	/** sets whether rowprep is local */
730  	void SCIProwprepSetLocal(
731  	   SCIP_ROWPREP*         rowprep,            /**< rowprep */
732  	   SCIP_Bool             islocal             /**< whether rowprep is local */
733  	   )
734  	{
735  	   assert(rowprep != NULL);
736  	
737  	   rowprep->local = islocal;
738  	}
739  	
740  	/** enables recording for where modifications were done in cleanup */
741  	void SCIProwprepRecordModifications(
742  	   SCIP_ROWPREP*         rowprep             /**< rowprep */
743  	   )
744  	{
745  	   assert(rowprep != NULL);
746  	
747  	   rowprep->recordmodifications = TRUE;
748  	}
749  	
750  	/** prints a rowprep */
751  	void SCIPprintRowprep(
752  	   SCIP*                 scip,               /**< SCIP data structure */
753  	   SCIP_ROWPREP*         rowprep,            /**< rowprep to be printed */
754  	   FILE*                 file                /**< file to print to, or NULL for stdout */
755  	   )
756  	{
757  	   int i;
758  	
759  	   assert(scip != NULL);
760  	   assert(rowprep != NULL);
761  	
762  	   if( *rowprep->name != '\0' )
763  	   {
764  	      SCIPinfoMessage(scip, file, "[%s](%c) ", rowprep->name, rowprep->local ? 'l' : 'g');
765  	   }
766  	
767  	   for( i = 0; i < rowprep->nvars; ++i )
768  	   {
769  	      SCIPinfoMessage(scip, file, "%+.15g*<%s> ", rowprep->coefs[i], SCIPvarGetName(rowprep->vars[i]));
770  	   }
771  	
772  	   SCIPinfoMessage(scip, file, rowprep->sidetype == SCIP_SIDETYPE_LEFT ? ">= %.15g\n" : "<= %.15g\n", rowprep->side);
773  	}
774  	
775  	/** prints a rowprep and values in solution */
776  	void SCIPprintRowprepSol(
777  	   SCIP*                 scip,               /**< SCIP data structure */
778  	   SCIP_ROWPREP*         rowprep,            /**< rowprep to be printed */
779  	   SCIP_SOL*             sol,                /**< solution for activity */
780  	   FILE*                 file                /**< file to print to, or NULL for stdout */
781  	   )
782  	{
783  	   SCIP_VAR* var;
784  	   SCIP_Real coef;
785  	   SCIP_Real term;
786  	   SCIP_Real maxterm;
787  	   SCIP_Real activity;
788  	   SCIP_Real violation;
789  	   int maxtermidx;
790  	   int i;
791  	
792  	   assert(scip != NULL);
793  	   assert(rowprep != NULL);
794  	
795  	   if( *rowprep->name != '\0' )
796  	   {
797  	      SCIPinfoMessage(scip, file, "[%s](%c) ", rowprep->name, rowprep->local ? 'l' : 'g');
798  	   }
799  	
800  	   activity = 0.0;
801  	   maxterm = REALABS(rowprep->side);
802  	   maxtermidx = -1;
803  	   for( i = 0; i < rowprep->nvars; ++i )
804  	   {
805  	      coef = rowprep->coefs[i];
806  	      var = rowprep->vars[i];
807  	      SCIPinfoMessage(scip, file, "%+.15g*<%s>(%.15g) ", coef, SCIPvarGetName(var), SCIPgetSolVal(scip, sol, var));
808  	
809  	      term = coef * SCIPgetSolVal(scip, sol, var);
810  	      if( REALABS(term) > maxterm )
811  	      {
812  	         maxterm = term;
813  	         maxtermidx = i;
814  	      }
815  	
816  	      activity += term;
817  	   }
818  	
819  	   SCIPinfoMessage(scip, file, rowprep->sidetype == SCIP_SIDETYPE_LEFT ? ">= %.15g" : "<= %.15g", rowprep->side);
820  	
821  	   if( rowprep->sidetype == SCIP_SIDETYPE_RIGHT )
822  	      /* cut is activity <= side -> violation is activity - side (if positive) */
823  	      violation = activity - rowprep->side;
824  	   else
825  	      /* cut is activity >= side -> violation is side - activity (if positive) */
826  	      violation = rowprep->side - activity;
827  	
828  	   SCIPinfoMessage(scip, file, "; activity %.15g", activity);
829  	   SCIPinfoMessage(scip, file, "; violation %e", violation);
830  	   SCIPinfoMessage(scip, file, "; maxterm %e at pos %d\n", maxterm, maxtermidx);
831  	}
832  	
833  	/** ensures that rowprep has space for at least given number of additional terms
834  	 *
835  	 * Useful when knowing in advance how many terms will be added.
836  	 */
837  	SCIP_RETCODE SCIPensureRowprepSize(
838  	   SCIP*                 scip,               /**< SCIP data structure */
839  	   SCIP_ROWPREP*         rowprep,            /**< rowprep */
840  	   int                   size                /**< number of additional terms for which to alloc space in rowprep */
841  	   )
842  	{
843  	   int oldsize;
844  	
845  	   assert(scip != NULL);
846  	   assert(rowprep != NULL);
847  	   assert(size >= 0);
848  	
849  	   if( rowprep->varssize >= rowprep->nvars + size )
850  	      return SCIP_OKAY;  /* already enough space left */
851  	
852  	   /* realloc vars and coefs array */
853  	   oldsize = rowprep->varssize;
854  	   rowprep->varssize = SCIPcalcMemGrowSize(scip, rowprep->nvars + size);
855  	
856  	   SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &rowprep->vars,  oldsize, rowprep->varssize) );
857  	   SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &rowprep->coefs, oldsize, rowprep->varssize) );
858  	
859  	   return SCIP_OKAY;
860  	}
861  	
862  	/** adds a term coef*var to a rowprep */
863  	SCIP_RETCODE SCIPaddRowprepTerm(
864  	   SCIP*                 scip,               /**< SCIP data structure */
865  	   SCIP_ROWPREP*         rowprep,            /**< rowprep */
866  	   SCIP_VAR*             var,                /**< variable to add */
867  	   SCIP_Real             coef                /**< coefficient to add */
868  	   )
869  	{
870  	   assert(scip != NULL);
871  	   assert(rowprep != NULL);
872  	   assert(var != NULL);
873  	
874  	   if( coef == 0.0 )
875  	      return SCIP_OKAY;
876  	
877  	   SCIP_CALL( SCIPensureRowprepSize(scip, rowprep, 1) );
878  	   assert(rowprep->varssize > rowprep->nvars);
879  	
880  	   rowprep->vars[rowprep->nvars] = var;
881  	   rowprep->coefs[rowprep->nvars] = coef;
882  	   ++rowprep->nvars;
883  	
884  	   return SCIP_OKAY;
885  	}
886  	
887  	/** adds several terms coef*var to a rowprep */
888  	SCIP_RETCODE SCIPaddRowprepTerms(
889  	   SCIP*                 scip,               /**< SCIP data structure */
890  	   SCIP_ROWPREP*         rowprep,            /**< rowprep */
891  	   int                   nvars,              /**< number of terms to add */
892  	   SCIP_VAR**            vars,               /**< variables to add */
893  	   SCIP_Real*            coefs               /**< coefficients to add */
894  	   )
895  	{
896  	   assert(scip != NULL);
897  	   assert(rowprep != NULL);
898  	   assert(vars != NULL || nvars == 0);
899  	   assert(coefs != NULL || nvars == 0);
900  	
901  	   if( nvars == 0 )
902  	      return SCIP_OKAY;
903  	
904  	   SCIP_CALL( SCIPensureRowprepSize(scip, rowprep, nvars) );
905  	   assert(rowprep->varssize >= rowprep->nvars + nvars);
906  	
907  	   /*lint --e{866} */
908  	   BMScopyMemoryArray(rowprep->vars + rowprep->nvars, vars, nvars);
909  	   BMScopyMemoryArray(rowprep->coefs + rowprep->nvars, coefs, nvars);
910  	   rowprep->nvars += nvars;
911  	
912  	   return SCIP_OKAY;
913  	}
914  	
915  	/** computes violation of rowprep in a given solution
916  	 *
917  	 * Can return whether the violation value is reliable from a floating-point accuracy point of view.
918  	 * The value will not be deemed reliable when its calculation involved the subtraction of large numbers.
919  	 * To be precise, the violation of an inequality \f$ \sum_i a_ix_i \leq b \f$ in a solution \f$x^*\f$ is deemed
920  	 * reliable if \f$ |\sum_i a_ix^*_i - b| \geq 2^{-50} \max (|b|, \max_i |a_ix^*_i|) \f$.
921  	 */
922  	SCIP_Real SCIPgetRowprepViolation(
923  	   SCIP*                 scip,               /**< SCIP data structure */
924  	   SCIP_ROWPREP*         rowprep,            /**< rowprep */
925  	   SCIP_SOL*             sol,                /**< solution or NULL for LP solution */
926  	   SCIP_Bool*            reliable            /**< buffer to store whether computed violation is reliable (numerically), or NULL if not of interest */
927  	   )
928  	{
929  	   SCIP_Real activity;
930  	   SCIP_Real maxterm;
931  	   SCIP_Real term;
932  	   SCIP_Real violation;
933  	   SCIP_Real val;
934  	   int i;
935  	
936  	   activity = 0.0;
937  	   maxterm = REALABS(rowprep->side);
938  	   for( i = 0; i < rowprep->nvars; ++i )
939  	   {
940  	      /* Loose variable have the best bound as LP solution value.
941  	       * HOWEVER, they become column variables when they are added to a row (via SCIPaddVarsToRow below).
942  	       * When this happens, their LP solution value changes to 0.0!
943  	       * So when calculating the row activity for an LP solution, we treat loose variable as if they were already column variables.
944  	       */
945  	      if( sol != NULL || SCIPvarGetStatus(rowprep->vars[i]) != SCIP_VARSTATUS_LOOSE )
946  	      {
947  	         val = SCIPgetSolVal(scip, sol, rowprep->vars[i]);
948  	
949  	         /* If a variable is at infinity, then this should lead to an immediate decision.
950  	          * Having different contradicting infinities is something I would now know how to handle and am ignoring now.
951  	          */
952  	         if( SCIPisInfinity(scip, val * (rowprep->coefs[i] >= 0.0 ? 1.0 : -1.0)) )
953  	         {
954  	            /* activity = SCIPinfinity(scip); */
955  	            if( reliable != NULL )
956  	               *reliable = TRUE;
957  	            if( rowprep->sidetype == SCIP_SIDETYPE_RIGHT )
958  	               return SCIPinfinity(scip);  /* infinity <= side -> always violated */
959  	            else
960  	               return 0.0;  /* infinity >= side -> never violated */
961  	         }
962  	         if( SCIPisInfinity(scip, val * (rowprep->coefs[i] >= 0.0 ? -1.0 : 1.0)) )
963  	         {
964  	            /* activity = -SCIPinfinity(scip); */
965  	            if( reliable != NULL )
966  	               *reliable = TRUE;
967  	            if( rowprep->sidetype == SCIP_SIDETYPE_RIGHT )
968  	               return 0.0;  /* -infinity <= side -> never violated */
969  	            else
970  	               return SCIPinfinity(scip);  /* -infinity >= side -> always violated */
971  	         }
972  	
973  	         term = rowprep->coefs[i] * val;
974  	         activity += term;
975  	
976  	         if( reliable != NULL && REALABS(term) > maxterm )
977  	            maxterm = REALABS(term);
978  	      }
979  	   }
980  	
981  	   if( rowprep->sidetype == SCIP_SIDETYPE_RIGHT )
982  	      /* cut is activity <= side -> violation is activity - side (if positive) */
983  	      violation = activity - rowprep->side;
984  	   else
985  	      /* cut is activity >= side -> violation is side - activity (if positive) */
986  	      violation = rowprep->side - activity;
987  	
988  	   /* In double precision, the mantissa (or significand) of a floating point number has 52 bit.
989  	    * Therefore, if the exponent in the violation is 52 (or more) less than the one of maxterm,
990  	    * then it is essentially random.
991  	    * We require here that the exponents differ by at most 50.
992  	    * To be more robust w.r.t. scaling of the row, we look at the exponent of the quotient maxterm/violation
993  	    * instead of the difference of the exponents of maxterm and violation.
994  	    */
995  	   if( reliable != NULL )
996  	   {
997  	      if( violation != 0.0 )
998  	      {
999  	         int exponent;
1000 	         (void) frexp(maxterm / violation, &exponent);  /* difference in exponents for maxterm and violation */
1001 	         *reliable = exponent <= 50;
1002 	      }
1003 	      else
1004 	         *reliable = TRUE;  /* not clear how to evaluate reliability here, so think positive */
1005 	   }
1006 	
1007 	   return MAX(violation, 0.0);
1008 	}
1009 	
1010 	/** computes violation of rowprep in a given solution and reports whether that value seem numerically reliable
1011 	 *
1012 	 * @see SCIPgetRowprepViolation()
1013 	 */
1014 	SCIP_Bool SCIPisRowprepViolationReliable(
1015 	   SCIP*                 scip,               /**< SCIP data structure */
1016 	   SCIP_ROWPREP*         rowprep,            /**< rowprep */
1017 	   SCIP_SOL*             sol                 /**< solution or NULL for LP solution */
1018 	   )
1019 	{
1020 	   SCIP_Bool reliable;
1021 	
1022 	   assert(scip != NULL);
1023 	   assert(rowprep != NULL);
1024 	
1025 	   (void) SCIPgetRowprepViolation(scip, rowprep, sol, &reliable);
1026 	
1027 	   return reliable;
1028 	}
1029 	
1030 	/** Merge terms that use same variable and eliminate zero coefficients.
1031 	 *
1032 	 * Removes a variable if its bounds have a relative difference of below epsilon.
1033 	 * Local bounds are checked for local rows, otherwise global bounds are used.
1034 	 * If the bounds are not absolute equal, the bound that relaxes the row is used.
1035 	 *
1036 	 * Terms are sorted by variable (see SCIPvarComp()) after return.
1037 	 */
1038 	void SCIPmergeRowprepTerms(
1039 	   SCIP*                 scip,               /**< SCIP data structure */
1040 	   SCIP_ROWPREP*         rowprep             /**< rowprep to be cleaned up */
1041 	   )
1042 	{
1043 	   int i;
1044 	   int j;
1045 	
1046 	   assert(scip != NULL);
1047 	   assert(rowprep != NULL);
1048 	
1049 	   if( rowprep->nvars <= 1 )
1050 	      return;
1051 	
1052 	   /* sort terms by variable index */
1053 	   SCIPsortPtrReal((void**)rowprep->vars, rowprep->coefs, SCIPvarComp, rowprep->nvars);
1054 	
1055 	   /* merge terms with same variable, drop 0 coefficients */
1056 	   i = 0;
1057 	   j = 1;
1058 	   while( j < rowprep->nvars )
1059 	   {
1060 	      if( rowprep->vars[i] == rowprep->vars[j] )
1061 	      {
1062 	         /* merge term j into term i */
1063 	         rowprep->coefs[i] += rowprep->coefs[j];
1064 	         ++j;
1065 	         continue;
1066 	      }
1067 	
1068 	      /* move term i into side if fixed */
1069 	      if( rowprep->local && SCIPisRelEQ(scip, SCIPvarGetLbLocal(rowprep->vars[i]), SCIPvarGetUbLocal(rowprep->vars[i])) )
1070 	      {
1071 	         if( (rowprep->coefs[i] > 0.0) == (rowprep->sidetype == SCIP_SIDETYPE_RIGHT) )
1072 	            rowprep->side -= rowprep->coefs[i] * SCIPvarGetLbLocal(rowprep->vars[i]);
1073 	         else
1074 	            rowprep->side -= rowprep->coefs[i] * SCIPvarGetUbLocal(rowprep->vars[i]);
1075 	         rowprep->coefs[i] = 0.0;  /* so will be cleaned out below */
1076 	      }
1077 	      else if( !rowprep->local && SCIPisRelEQ(scip, SCIPvarGetLbGlobal(rowprep->vars[i]), SCIPvarGetUbGlobal(rowprep->vars[i])) )
1078 	      {
1079 	         if( (rowprep->coefs[i] > 0.0) == (rowprep->sidetype == SCIP_SIDETYPE_RIGHT) )
1080 	            rowprep->side -= rowprep->coefs[i] * SCIPvarGetLbGlobal(rowprep->vars[i]);
1081 	         else
1082 	            rowprep->side -= rowprep->coefs[i] * SCIPvarGetUbGlobal(rowprep->vars[i]);
1083 	         rowprep->coefs[i] = 0.0;  /* so will be cleaned out below */
1084 	      }
1085 	
1086 	      if( rowprep->coefs[i] == 0.0 )
1087 	      {
1088 	         /* move term j to position i */
1089 	         rowprep->coefs[i] = rowprep->coefs[j];
1090 	         rowprep->vars[i] = rowprep->vars[j];
1091 	         ++j;
1092 	         continue;
1093 	      }
1094 	
1095 	      /* move term j to position i+1 and move on */
1096 	      if( j != i+1 )
1097 	      {
1098 	         rowprep->vars[i+1] = rowprep->vars[j];
1099 	         rowprep->coefs[i+1] = rowprep->coefs[j];
1100 	      }
1101 	      ++i;
1102 	      ++j;
1103 	   }
1104 	
1105 	   /* move term i into side if fixed */
1106 	   if( rowprep->local && SCIPisRelEQ(scip, SCIPvarGetLbLocal(rowprep->vars[i]), SCIPvarGetUbLocal(rowprep->vars[i])) )
1107 	   {
1108 	      if( (rowprep->coefs[i] > 0.0) == (rowprep->sidetype == SCIP_SIDETYPE_RIGHT) )
1109 	         rowprep->side -= rowprep->coefs[i] * SCIPvarGetLbLocal(rowprep->vars[i]);
1110 	      else
1111 	         rowprep->side -= rowprep->coefs[i] * SCIPvarGetUbLocal(rowprep->vars[i]);
1112 	      rowprep->coefs[i] = 0.0;  /* so will be cleaned out below */
1113 	   }
1114 	   else if( !rowprep->local && SCIPisRelEQ(scip, SCIPvarGetLbGlobal(rowprep->vars[i]), SCIPvarGetUbGlobal(rowprep->vars[i])) )
1115 	   {
1116 	      if( (rowprep->coefs[i] > 0.0) == (rowprep->sidetype == SCIP_SIDETYPE_RIGHT) )
1117 	         rowprep->side -= rowprep->coefs[i] * SCIPvarGetLbGlobal(rowprep->vars[i]);
1118 	      else
1119 	         rowprep->side -= rowprep->coefs[i] * SCIPvarGetUbGlobal(rowprep->vars[i]);
1120 	      rowprep->coefs[i] = 0.0;  /* so will be cleaned out below */
1121 	   }
1122 	
1123 	   /* remaining term can have coef zero -> forget about it */
1124 	   if( rowprep->coefs[i] == 0.0 )
1125 	      --i;
1126 	
1127 	   /* i points to last term */
1128 	   rowprep->nvars = i+1;
1129 	}
1130 	
1131 	/** Cleans up and attempts to improve rowprep
1132 	 *
1133 	 * Drops small or large coefficients if coefrange is too large, if this can be done by relaxing the row.
1134 	 * Scales coefficients up to reach minimal violation, if possible.
1135 	 * Scaling is omitted if violation is very small (\ref ROWPREP_SCALEUP_VIOLNONZERO) or
1136 	 * maximal coefficient would become huge (\ref ROWPREP_SCALEUP_MAXMAXCOEF).
1137 	 * Scales coefficients and side down if they are large and if the minimal violation is still reached.
1138 	 * Rounds coefficients close to integral values to integrals, if this can be done by relaxing the row.
1139 	 * Rounds side within epsilon of 0 to 0.0 or +/-1.1*epsilon, whichever relaxes the row least.
1140 	 *
1141 	 * After return, the terms in the rowprep will be sorted by absolute value of coefficient, in decreasing order.
1142 	 * Thus, the coefrange can be obtained via `REALABS(rowprep->coefs[0]) / REALABS(rowprep->coefs[rowprep->nvars-1])` (if nvars>0).
1143 	 *
1144 	 * `success` is set to TRUE if and only if the rowprep satisfies the following:
1145 	 * - the coefrange is below `maxcoefrange`
1146 	 * - the violation is at least `minviol`
1147 	 * - the violation is reliable or `minviol` = 0
1148 	 * - the absolute value of coefficients are below SCIPinfinity()
1149 	 * - the absolute value of the side is below SCIPinfinity()
1150 	 */
1151 	SCIP_RETCODE SCIPcleanupRowprep(
1152 	   SCIP*                 scip,               /**< SCIP data structure */
1153 	   SCIP_ROWPREP*         rowprep,            /**< rowprep to be cleaned */
1154 	   SCIP_SOL*             sol,                /**< solution that we try to cut off, or NULL for LP solution */
1155 	   SCIP_Real             minviol,            /**< minimal absolute violation the row should achieve (w.r.t. sol) */
1156 	   SCIP_Real*            viol,               /**< buffer to store absolute violation of cleaned up cut in sol, or NULL if not of interest */
1157 	   SCIP_Bool*            success             /**< buffer to store whether cut cleanup was successful, or NULL if not of interest */
1158 	   )
1159 	{
1160 	   SCIP_Real myviol;
1161 	   SCIP_Bool violreliable = TRUE;
1162 	   SCIP_Real maxcoefrange;
1163 	#ifdef SCIP_DEBUG
1164 	   SCIP_Real mincoef = 1.0;
1165 	   SCIP_Real maxcoef = 1.0;
1166 	#endif
1167 	
1168 	   maxcoefrange = SCIPsetGetSepaMaxCoefRatioRowprep(scip->set);
1169 	
1170 	   if( rowprep->recordmodifications )
1171 	   {
1172 	      /* forget about possible previous modifications */
1173 	      rowprep->nmodifiedvars = 0;
1174 	      rowprep->modifiedside = FALSE;
1175 	   }
1176 	
1177 	   /* sort term by absolute value of coef. */
1178 	   SCIP_CALL( rowprepCleanupSortTerms(scip, rowprep) );
1179 	
1180 	#ifdef SCIP_DEBUG
1181 	   if( rowprep->nvars > 0 )
1182 	   {
1183 	      maxcoef = REALABS(rowprep->coefs[0]);
1184 	      mincoef = REALABS(rowprep->coefs[rowprep->nvars-1]);
1185 	   }
1186 	
1187 	   SCIPinfoMessage(scip, NULL, "starting cleanup, coefrange %g: ", maxcoef/mincoef);
1188 	   SCIPprintRowprep(scip, rowprep, NULL);
1189 	#endif
1190 	
1191 	   /* improve coefficient range by aggregating out variables */
1192 	   SCIP_CALL( rowprepCleanupImproveCoefrange(scip, rowprep, sol, maxcoefrange) );
1193 	
1194 	   /* get current violation in sol (reliability info only needed if success is not NULL) */
1195 	   myviol = SCIPgetRowprepViolation(scip, rowprep, sol, success != NULL ? &violreliable : NULL);  /*lint !e826*/
1196 	   assert(myviol >= 0.0);
1197 	
1198 	#ifdef SCIP_DEBUG
1199 	   if( rowprep->nvars > 0 )
1200 	   {
1201 	      maxcoef = REALABS(rowprep->coefs[0]);
1202 	      mincoef = REALABS(rowprep->coefs[rowprep->nvars-1]);
1203 	   }
1204 	
1205 	   SCIPinfoMessage(scip, NULL, "improved coefrange to %g, viol %g: ", maxcoef / mincoef, myviol);
1206 	   SCIPprintRowprep(scip, rowprep, NULL);
1207 	#endif
1208 	
1209 	   /* if there is interest in achieving some minimal violation, then possibly scale up to increase violation
1210 	    * this updates myviol; since this is only scaling the cut, it doesn't change anything about the reliability of the violation value */
1211 	   if( minviol > 0.0 )
1212 	   {
1213 	      /* first, try to achieve scip's minefficacy (typically 1e-4) */
1214 	      if( SCIPgetSepaMinEfficacy(scip) > minviol )
1215 	         rowprepCleanupScaleup(scip, rowprep, &myviol, SCIPgetSepaMinEfficacy(scip));
1216 	      /* in case scip minefficacy could not be reached or was smaller than minviol, try with the given minviol */
1217 	      rowprepCleanupScaleup(scip, rowprep, &myviol, minviol);
1218 	   }
1219 	
1220 	   /* scale down to improve numerics, updates myviol (reliability doesn't change) */
1221 	   rowprepCleanupScaledown(scip, rowprep, &myviol, MAX(SCIPgetSepaMinEfficacy(scip), minviol)); /*lint !e666*/
1222 	
1223 	#ifdef SCIP_DEBUG
1224 	   SCIPinfoMessage(scip, NULL, "applied scaling, viol %g: ", myviol);
1225 	   SCIPprintRowprep(scip, rowprep, NULL);
1226 	#endif
1227 	
1228 	   /* turn almost-integral coefs to integral values, may set myviol to SCIP_INVALID */
1229 	   SCIP_CALL( rowprepCleanupIntegralCoefs(scip, rowprep, &myviol) );
1230 	
1231 	   /* relax almost-zero side, may set myviol to SCIP_INVALID */
1232 	   rowprepCleanupSide(scip, rowprep, &myviol);
1233 	
1234 	#ifdef SCIP_DEBUG
1235 	   SCIPinfoMessage(scip, NULL, "adjusted almost-integral coefs and sides, viol %g: ", myviol);
1236 	   SCIPprintRowprep(scip, rowprep, NULL);
1237 	#endif
1238 	
1239 	#if !1
1240 	   /* compute final coefrange, if requested by caller */
1241 	   if( coefrange != NULL )
1242 	   {
1243 	      if( rowprep->nvars > 0 )
1244 	         *coefrange = REALABS(rowprep->coefs[0]) / REALABS(rowprep->coefs[rowprep->nvars-1]);
1245 	      else
1246 	         *coefrange = 1.0;
1247 	   }
1248 	#endif
1249 	
1250 	   /* check whether rowprep could be turned into a reasonable row */
1251 	   if( success != NULL )
1252 	   {
1253 	      *success = TRUE;
1254 	
1255 	      /* check whether the coef.range is below maxcoefrange */
1256 	      if( rowprep->nvars > 0 && REALABS(rowprep->coefs[0]) / REALABS(rowprep->coefs[rowprep->nvars-1]) > maxcoefrange )
1257 	      {
1258 	         SCIPdebugMsg(scip, "rowprep coefrange %g is above the limit %g\n", REALABS(rowprep->coefs[0]) / REALABS(rowprep->coefs[rowprep->nvars-1]), maxcoefrange);
1259 	         *success = FALSE;
1260 	      }
1261 	
1262 	      /* check whether coefficients are below SCIPinfinity (terms are order by coef value) */
1263 	      if( *success && rowprep->nvars > 0 && SCIPisInfinity(scip, REALABS(rowprep->coefs[0])) )
1264 	      {
1265 	         SCIPdebugMsg(scip, "rowprep coefficient %g is beyond value for infinity\n", rowprep->coefs[0]);
1266 	         *success = FALSE;
1267 	      }
1268 	
1269 	      /* check whether the absolute value of the side is below SCIPinfinity */
1270 	      if( *success && SCIPisInfinity(scip, REALABS(rowprep->side)) )
1271 	      {
1272 	         SCIPdebugMsg(scip, "rowprep side %g is beyond value for infinity\n", rowprep->side);
1273 	         *success = FALSE;
1274 	      }
1275 	
1276 	      /* check if violation is at least minviol and reliable, if minviol > 0 */
1277 	      if( *success && minviol > 0.0 )
1278 	      {
1279 	         /* may need to recompute violation if coefs or side was modified above */
1280 	         if( myviol == SCIP_INVALID )  /*lint !e777 */
1281 	            myviol = SCIPgetRowprepViolation(scip, rowprep, sol, &violreliable);
1282 	
1283 	         if( !violreliable )
1284 	         {
1285 	            SCIPdebugMsg(scip, "rowprep violation %g is not reliable\n", myviol);
1286 	            *success = FALSE;
1287 	         }
1288 	         else if( myviol < minviol )
1289 	         {
1290 	            SCIPdebugMsg(scip, "rowprep violation %g is below minimal violation %g\n", myviol, minviol);
1291 	            *success = FALSE;
1292 	         }
1293 	      }
1294 	   }
1295 	
1296 	   /* If we updated myviol correctly, then it should coincide with freshly computed violation.
1297 	    * I leave this assert off for now, since getting the tolerance in the EQ correctly is not trivial. We recompute viol below anyway.
1298 	    */
1299 	   /* assert(myviol == SCIP_INVALID || SCIPisEQ(scip, myviol, SCIPgetRowprepViolation(scip, rowprep, sol, NULL))); */
1300 	
1301 	   /* compute final violation, if requested by caller */
1302 	   if( viol != NULL )  /*lint --e{777} */
1303 	      *viol = myviol == SCIP_INVALID ? SCIPgetRowprepViolation(scip, rowprep, sol, NULL) : myviol;
1304 	
1305 	   return SCIP_OKAY;
1306 	}
1307 	
1308 	/** Cleans up and attempts to improve rowprep without regard for violation
1309 	 *
1310 	 * Drops small or large coefficients if their ratio is beyond separating/maxcoefratiofacrowprep / numerics/feastol,
1311 	 * if this can be done by relaxing the row.
1312 	 * Scales coefficients and side to have maximal coefficient in `[1/maxcoefbound,maxcoefbound]`.
1313 	 * Rounds coefficients close to integral values to integrals, if this can be done by relaxing the row.
1314 	 * Rounds side within epsilon of 0 to 0.0 or +/-1.1*epsilon, whichever relaxes the row least.
1315 	 *
1316 	 * After return, the terms in the rowprep will be sorted by absolute value of coefficient, in decreasing order.
1317 	 * Thus, the coefratio can be obtained via `REALABS(rowprep->coefs[0]) / REALABS(rowprep->coefs[rowprep->nvars-1])` (if nvars>0).
1318 	 *
1319 	 * `success` is set to TRUE if and only if the rowprep satisfies the following:
1320 	 * - the coefratio is below separating/maxcoefratiofacrowprep / numerics/feastol
1321 	 * - the absolute value of coefficients are below SCIPinfinity()
1322 	 * - the absolute value of the side is below SCIPinfinity()
1323 	 *
1324 	 * In difference to SCIPcleanupRowprep(), this function does not scale up the row to increase the absolute violation.
1325 	 */
1326 	SCIP_RETCODE SCIPcleanupRowprep2(
1327 	   SCIP*                 scip,               /**< SCIP data structure */
1328 	   SCIP_ROWPREP*         rowprep,            /**< rowprep to be cleaned */
1329 	   SCIP_SOL*             sol,                /**< solution that we try to cut off, or NULL for LP solution */
1330 	   SCIP_Real             maxcoefbound,       /**< bound on absolute value of largest coefficient */
1331 	   SCIP_Bool*            success             /**< buffer to store whether cut cleanup was successful, or NULL if not of interest */
1332 	   )
1333 	{
1334 	   SCIP_Real maxcoefrange;
1335 	#ifdef SCIP_DEBUG
1336 	   SCIP_Real mincoef = 1.0;
1337 	   SCIP_Real maxcoef = 1.0;
1338 	#endif
1339 	
1340 	   assert(maxcoefbound >= 1.0);
1341 	
1342 	   maxcoefrange = SCIPsetGetSepaMaxCoefRatioRowprep(scip->set);
1343 	
(1) Event deref_parm: Directly dereferencing parameter "rowprep".
1344 	   if( rowprep->recordmodifications )
1345 	   {
1346 	      /* forget about possible previous modifications */
1347 	      rowprep->nmodifiedvars = 0;
1348 	      rowprep->modifiedside = FALSE;
1349 	   }
1350 	
1351 	   /* sort term by absolute value of coef. */
1352 	   SCIP_CALL( rowprepCleanupSortTerms(scip, rowprep) );
1353 	
1354 	#ifdef SCIP_DEBUG
1355 	   if( rowprep->nvars > 0 )
1356 	   {
1357 	      maxcoef = REALABS(rowprep->coefs[0]);
1358 	      mincoef = REALABS(rowprep->coefs[rowprep->nvars-1]);
1359 	   }
1360 	
1361 	   SCIPinfoMessage(scip, NULL, "starting cleanup, coefrange %g: ", maxcoef/mincoef);
1362 	   SCIPprintRowprep(scip, rowprep, NULL);
1363 	#endif
1364 	
1365 	   /* improve coefficient range by aggregating out variables */
1366 	   SCIP_CALL( rowprepCleanupImproveCoefrange(scip, rowprep, sol, maxcoefrange) );
1367 	
1368 	#ifdef SCIP_DEBUG
1369 	   if( rowprep->nvars > 0 )
1370 	   {
1371 	      maxcoef = REALABS(rowprep->coefs[0]);
1372 	      mincoef = REALABS(rowprep->coefs[rowprep->nvars-1]);
1373 	   }
1374 	
1375 	   SCIPinfoMessage(scip, NULL, "improved coefrange to %g: ", maxcoef / mincoef);
1376 	   SCIPprintRowprep(scip, rowprep, NULL);
1377 	#endif
1378 	
1379 	   /* scale up or down to improve numerics
1380 	    * if maximal coef is below 1.0/maxcoefbound, scale up to reach ~ 1.0/maxcoefbound
1381 	    * if maximal coef is above maxcoefbound, scale down to ~ maxcoefbound
1382 	    */
1383 	   if( rowprep->nvars > 0 && !SCIPisInfinity(scip, maxcoefbound) )
1384 	   {
1385 	      SCIP_Real expon = 0.0;
1386 	      if( REALABS(rowprep->coefs[0]) < 1.0/maxcoefbound )
1387 	         expon = SCIPscaleRowprep(rowprep, (1.0/maxcoefbound) / REALABS(rowprep->coefs[0]));
1388 	      else if( REALABS(rowprep->coefs[0]) > maxcoefbound )
1389 	         expon = SCIPscaleRowprep(rowprep, maxcoefbound / REALABS(rowprep->coefs[0]));
1390 	
1391 	#ifdef SCIP_DEBUG
1392 	      SCIPinfoMessage(scip, NULL, "applied scaling by %g: ", pow(2.0, expon));
1393 	      SCIPprintRowprep(scip, rowprep, NULL);
1394 	#else
1395 	      (void) expon;
1396 	#endif
1397 	   }
1398 	
1399 	   /* turn almost-integral coefs to integral values */
1400 	   SCIP_CALL( rowprepCleanupIntegralCoefs(scip, rowprep, NULL) );
1401 	
1402 	   /* relax almost-zero side */
1403 	   rowprepCleanupSide(scip, rowprep, NULL);
1404 	
1405 	#ifdef SCIP_DEBUG
1406 	   SCIPinfoMessage(scip, NULL, "adjusted almost-integral coefs and sides: ");
1407 	   SCIPprintRowprep(scip, rowprep, NULL);
1408 	#endif
1409 	
1410 	   /* check whether rowprep could be turned into a reasonable row */
1411 	   if( success != NULL )
1412 	   {
1413 	      *success = TRUE;
1414 	
1415 	      /* check whether the coef.range is below maxcoefrange */
1416 	      if( rowprep->nvars > 0 && REALABS(rowprep->coefs[0]) / REALABS(rowprep->coefs[rowprep->nvars-1]) > maxcoefrange )
1417 	      {
1418 	         SCIPdebugMsg(scip, "rowprep coefrange %g is above the limit %g\n", REALABS(rowprep->coefs[0]) / REALABS(rowprep->coefs[rowprep->nvars-1]), maxcoefrange);
1419 	         *success = FALSE;
1420 	      }
1421 	
1422 	      /* check whether coefficients are below SCIPinfinity (terms are order by coef value) */
1423 	      if( *success && rowprep->nvars > 0 && SCIPisInfinity(scip, REALABS(rowprep->coefs[0])) )
1424 	      {
1425 	         SCIPdebugMsg(scip, "rowprep coefficient %g is beyond value for infinity\n", rowprep->coefs[0]);
1426 	         *success = FALSE;
1427 	      }
1428 	
1429 	      /* check whether the absolute value of the side is below SCIPinfinity */
1430 	      if( *success && SCIPisInfinity(scip, REALABS(rowprep->side)) )
1431 	      {
1432 	         SCIPdebugMsg(scip, "rowprep side %g is beyond value for infinity\n", rowprep->side);
1433 	         *success = FALSE;
1434 	      }
1435 	   }
1436 	
1437 	   return SCIP_OKAY;
1438 	}
1439 	
1440 	/** Scales up a rowprep to increase coefficients/sides that are within epsilon to an integer value, if possible.
1441 	 *
1442 	 * Computes the minimal fractionality of all fractional coefficients and the side of the rowprep.
1443 	 * If this fractionality is below epsilon, the rowprep is scaled up such that the fractionality exceeds epsilon,
1444 	 * if this will not put any coefficient or side above SCIPhugeValue().
1445 	 *
1446 	 * This function does not relax the rowprep.
1447 	 *
1448 	 * `success` is set to TRUE if the resulting rowprep can be turned into a SCIP_ROW, that is,
1449 	 * all coefs and the side is below SCIPinfinity() and fractionalities are above epsilon.
1450 	 * If `success` is set to FALSE, then the rowprep will not have been modified.
1451 	 *
1452 	 * @return The applied scaling factor, if `success` is set to TRUE.
1453 	 */
1454 	SCIP_Real SCIPscaleupRowprep(
1455 	   SCIP*                 scip,               /**< SCIP data structure */
1456 	   SCIP_ROWPREP*         rowprep,            /**< rowprep to be cleaned */
1457 	   SCIP_Real             minscaleup,         /**< minimal factor by which to scale up row, or <= 1.0 if to be ignored */
1458 	   SCIP_Bool*            success             /**< buffer to store whether rowprep could be turned into SCIP_ROW without loss, or NULL if not of interest */
1459 	   )
1460 	{
1461 	   SCIP_Real minfrac = 0.5;
1462 	   SCIP_Real minfrac0 = 0.5;
1463 	   SCIP_Real frac;
1464 	   SCIP_Real maxval;
1465 	   SCIP_Real factor = 1.0;
1466 	   SCIP_Bool makeintegral = TRUE;
1467 	   int i;
1468 	
1469 	   /* find the smallest fractionality in rowprep sides and coefficients and the largest absolute coefficient/side */
1470 	   frac = REALABS(floor(rowprep->side + 0.5) - rowprep->side);
1471 	   if( frac != 0.0 )
1472 	   {
1473 	      if( REALABS(rowprep->side) > 0.5 )
1474 	      {
1475 	         if( frac < minfrac )
1476 	            minfrac = frac;
1477 	      }
1478 	      else if( frac < minfrac0 )
1479 	         minfrac0 = frac;
1480 	   }
1481 	   maxval = REALABS(rowprep->side);
1482 	
1483 	   for( i = 0; i < rowprep->nvars; ++i )
1484 	   {
1485 	      frac = REALABS(floor(rowprep->coefs[i] + 0.5) - rowprep->coefs[i]);
1486 	      if( frac != 0.0 )
1487 	      {
1488 	         if( REALABS(rowprep->coefs[i]) > 0.5 )
1489 	         {
1490 	            if( frac < minfrac )
1491 	               minfrac = frac;
1492 	         }
1493 	         else if( frac < minfrac0 )
1494 	            minfrac0 = frac;
1495 	      }
1496 	      if( REALABS(rowprep->coefs[i]) > maxval )
1497 	         maxval = REALABS(rowprep->coefs[i]);
1498 	   }
1499 	
1500 	   SCIPdebugMsg(scip, "minimal fractional of rowprep coefs and side is %g, max coef/side is %g\n", MIN(minfrac, minfrac0), maxval);
1501 	
1502 	   /* in order for SCIP_ROW to not modify the coefs and side, they need to be more than epsilon way from an integer value
1503 	    *
1504 	    * If the integer value is 0, then scaling up the rowprep by epsilon/minfrac will increase its minimal fractionality
1505 	    * above epsilon.
1506 	    * If the integer value is not zero, then scaling up the rowprep by a well-chosen fractional number alpha will increase
1507 	    * the minimal fractionality by about alpha*integer-value mod 1. To reduce the chance that alpha*integer-value is integral,
1508 	    * we use a "very fractional" value for alpha.
1509 	    *
1510 	    * If the scaling increases the maximal coef/value beyond SCIPinfinity, then the rowprep would be useless.
1511 	    * We even check that we don't increase beyond SCIPhugeValue here
1512 	    */
1513 	   if( minfrac0 <= SCIPepsilon(scip) )
1514 	   {
1515 	      factor = 1.1 * SCIPepsilon(scip) / minfrac0;
1516 	
1517 	      if( factor < minscaleup )
1518 	         factor = minscaleup;
1519 	   }
1520 	   else if( minfrac <= SCIPepsilon(scip) )
1521 	   {
1522 	      factor = MAX(M_SQRT2, minscaleup);
1523 	      makeintegral = FALSE;
1524 	   }
1525 	   else if( minscaleup > 1.0 )
1526 	   {
1527 	      factor = minscaleup;
1528 	   }
1529 	   else
1530 	   {
1531 	      /* do not scale up, only check whether maxval is already below infinity */
1532 	      if( success != NULL )
1533 	         *success = !SCIPisInfinity(scip, maxval);
1534 	
1535 	      return 1.0;
1536 	   }
1537 	
1538 	   if( !SCIPisHugeValue(scip, factor * maxval) )
1539 	   {
1540 	      if( makeintegral)
1541 	      {
1542 	         factor = SCIPscaleRowprep(rowprep, factor);
1543 	
1544 	#ifdef SCIP_DEBUG
1545 	         factor = pow(2.0, factor);  /* SCIPscaleRowprep() actually returned log2 of factor */
1546 	#endif
1547 	      }
1548 	      else
1549 	      {
1550 	         /* multiply each coefficient by factor */
1551 	         for( i = 0; i < rowprep->nvars; ++i )
1552 	            rowprep->coefs[i] *= factor;
1553 	
1554 	         /* multiply side by factor */
1555 	         rowprep->side *= factor;
1556 	      }
1557 	#ifdef SCIP_DEBUG
1558 	      maxval *= factor;
1559 	      SCIPinfoMessage(scip, NULL, "scaled up rowprep by %g (minfrac=%g, minscaleup=%g), maxval is now %g\n", factor, minfrac, minscaleup, maxval);
1560 	      SCIPprintRowprep(scip, rowprep, NULL);
1561 	#endif
1562 	
1563 	      if( success != NULL )
1564 	         *success = TRUE;
1565 	   }
1566 	   else if( success != NULL )
1567 	      *success = FALSE;
1568 	
1569 	   return factor;
1570 	}
1571 	
1572 	/** scales a rowprep by given factor (after some rounding)
1573 	 *
1574 	 * @return Exponent of actually applied scaling factor, if written as \f$2^x\f$.
1575 	 */
1576 	int SCIPscaleRowprep(
1577 	   SCIP_ROWPREP*         rowprep,            /**< rowprep to be scaled */
1578 	   SCIP_Real             factor              /**< suggested scale factor */
1579 	   )
1580 	{
1581 	   double v;
1582 	   int expon;
1583 	   int i;
1584 	
1585 	   assert(rowprep != NULL);
1586 	   assert(factor > 0.0);
1587 	
1588 	   /* write factor as v*2^expon with v in [0.5,1) */
1589 	   v = frexp(factor, &expon);
1590 	   /* adjust to v'*2^expon with v' in (0.5,1] by v'=v if v > 0.5, v'=1 if v=0.5 */
1591 	   if( v == 0.5 )
1592 	      --expon;
1593 	
1594 	   /* multiply each coefficient by 2^expon */
1595 	   for( i = 0; i < rowprep->nvars; ++i )
1596 	      rowprep->coefs[i] = ldexp(rowprep->coefs[i], expon);
1597 	
1598 	   /* multiply side by 2^expon */
1599 	   rowprep->side = ldexp(rowprep->side, expon);
1600 	
1601 	   return expon;
1602 	}
1603 	
1604 	/** generates a SCIP_ROW from a rowprep, setting its origin to given constraint handler */
1605 	SCIP_RETCODE SCIPgetRowprepRowConshdlr(
1606 	   SCIP*                 scip,               /**< SCIP data structure */
1607 	   SCIP_ROW**            row,                /**< buffer to store pointer to new row */
1608 	   SCIP_ROWPREP*         rowprep,            /**< rowprep to be turned into a row */
1609 	   SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
1610 	   )
1611 	{
1612 	   assert(scip != NULL);
1613 	   assert(row != NULL);
1614 	   assert(rowprep != NULL);
1615 	   assert(conshdlr != NULL);
1616 	
1617 	   SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, row, conshdlr, rowprep->name,
1618 	      rowprep->sidetype == SCIP_SIDETYPE_LEFT  ? rowprep->side : -SCIPinfinity(scip),
1619 	      rowprep->sidetype == SCIP_SIDETYPE_RIGHT ? rowprep->side :  SCIPinfinity(scip),
1620 	      rowprep->local && (SCIPgetDepth(scip) > 0), FALSE, TRUE) );
1621 	
1622 	   SCIP_CALL( SCIPaddVarsToRow(scip, *row, rowprep->nvars, rowprep->vars, rowprep->coefs) );
1623 	
1624 	   return SCIP_OKAY;
1625 	}
1626 	
1627 	/** generates a SCIP_ROW from a rowprep, setting its origin to given constraint */
1628 	SCIP_RETCODE SCIPgetRowprepRowCons(
1629 	   SCIP*                 scip,               /**< SCIP data structure */
1630 	   SCIP_ROW**            row,                /**< buffer to store pointer to new row */
1631 	   SCIP_ROWPREP*         rowprep,            /**< rowprep to be turned into a row */
1632 	   SCIP_CONS*            cons                /**< constraint */
1633 	   )
1634 	{
1635 	   assert(scip != NULL);
1636 	   assert(row != NULL);
1637 	   assert(rowprep != NULL);
1638 	   assert(cons != NULL);
1639 	
1640 	   SCIP_CALL( SCIPcreateEmptyRowCons(scip, row, cons, rowprep->name,
1641 	      rowprep->sidetype == SCIP_SIDETYPE_LEFT  ? rowprep->side : -SCIPinfinity(scip),
1642 	      rowprep->sidetype == SCIP_SIDETYPE_RIGHT ? rowprep->side :  SCIPinfinity(scip),
1643 	      rowprep->local && (SCIPgetDepth(scip) > 0), FALSE, TRUE) );
1644 	
1645 	   SCIP_CALL( SCIPaddVarsToRow(scip, *row, rowprep->nvars, rowprep->vars, rowprep->coefs) );
1646 	
1647 	   return SCIP_OKAY;
1648 	}
1649 	
1650 	/** generates a SCIP_ROW from a rowprep, setting its origin to given separator */
1651 	SCIP_RETCODE SCIPgetRowprepRowSepa(
1652 	   SCIP*                 scip,               /**< SCIP data structure */
1653 	   SCIP_ROW**            row,                /**< buffer to store pointer to new row */
1654 	   SCIP_ROWPREP*         rowprep,            /**< rowprep to be turned into a row */
1655 	   SCIP_SEPA*            sepa                /**< separator */
1656 	   )
1657 	{
1658 	   assert(scip != NULL);
1659 	   assert(row != NULL);
1660 	   assert(rowprep != NULL);
1661 	
1662 	   SCIP_CALL( SCIPcreateEmptyRowSepa(scip, row, sepa, rowprep->name,
1663 	      rowprep->sidetype == SCIP_SIDETYPE_LEFT  ? rowprep->side : -SCIPinfinity(scip),
1664 	      rowprep->sidetype == SCIP_SIDETYPE_RIGHT ? rowprep->side :  SCIPinfinity(scip),
1665 	      rowprep->local && (SCIPgetDepth(scip) > 0), FALSE, TRUE) );
1666 	
1667 	   SCIP_CALL( SCIPaddVarsToRow(scip, *row, rowprep->nvars, rowprep->vars, rowprep->coefs) );
1668 	
1669 	   return SCIP_OKAY;
1670 	}
1671