Scippy

SCIP

Solving Constraint Integer Programs

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