Scippy

SCIP

Solving Constraint Integer Programs

prop_obbt.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 (C) 2002-2016 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 email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file prop_obbt.c
17  * @ingroup PROPAGATORS
18  * @brief optimization-based bound tightening propagator
19  * @author Stefan Weltge
20  * @author Benjamin Mueller
21  */
22 
23 /**@todo if bound tightenings of other propagators are the reason for lpsolstat != SCIP_LPSOLSTAT_OPTIMAL, resolve LP */
24 /**@todo only run more than once in root node if primal bound improved or many cuts were added to the LP */
25 /**@todo filter bounds of a variable already if SCIPisLbBetter()/SCIPisUbBetter() would return FALSE */
26 /**@todo improve warmstarting of LP solving */
27 /**@todo include bound value (finite/infinite) into getScore() function */
28 /**@todo use unbounded ray in filtering */
29 /**@todo do we want to run if the LP is unbounded, maybe for infinite variable bounds? */
30 /**@todo add first filter round in direction of objective function */
31 /**@todo implement conflict resolving callback by calling public method of genvbounds propagator, since the reason are
32  * exactly the variable bounds with nonnegative reduced costs stored in the right-hand side of the generated
33  * generalized variable bound (however, this only makes sense if we run locally)
34  */
35 
36 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
37 
38 #include <assert.h>
39 #include <string.h>
40 
41 #include "scip/prop_obbt.h"
42 #include "scip/prop_genvbounds.h"
43 #include "scip/debug.h"
44 #include "scip/cons_quadratic.h"
45 #include "scip/cons_nonlinear.h"
46 #include "scip/cons_abspower.h"
47 #include "scip/cons_bivariate.h"
48 
49 #define PROP_NAME "obbt"
50 #define PROP_DESC "optimization-based bound tightening propagator"
51 #define PROP_TIMING SCIP_PROPTIMING_AFTERLPLOOP
52 #define PROP_PRIORITY -1000000 /**< propagator priority */
53 #define PROP_FREQ 0 /**< propagator frequency */
54 #define PROP_DELAY TRUE /**< should propagation method be delayed, if other propagators
55  * found reductions? */
56 
57 #define DEFAULT_CREATE_GENVBOUNDS TRUE /**< should obbt try to provide genvbounds if possible? */
58 #define DEFAULT_FILTERING_NORM TRUE /**< should coefficients in filtering be normalized w.r.t. the
59  * domains sizes? */
60 #define DEFAULT_APPLY_FILTERROUNDS FALSE /**< try to filter bounds in so-called filter rounds by solving
61  * auxiliary LPs? */
62 #define DEFAULT_APPLY_TRIVIALFITLERING TRUE /**< should obbt try to use the LP solution to filter some bounds? */
63 #define DEFAULT_GENVBDSDURINGFILTER TRUE /**< try to genrate genvbounds during trivial and aggressive filtering? */
64 #define DEFAULT_DUALFEASTOL 1e-9 /**< feasibility tolerance for reduced costs used in obbt; this value
65  * is used if SCIP's dual feastol is greater */
66 #define DEFAULT_CONDITIONLIMIT -1.0 /**< maximum condition limit used in LP solver (-1.0: no limit) */
67 #define DEFAULT_BOUNDSTREPS 0.001 /**< minimal relative improve for strengthening bounds */
68 #define DEFAULT_FILTERING_MIN 2 /**< minimal number of filtered bounds to apply another filter
69  * round */
70 #define DEFAULT_ITLIMITFACTOR 10.0 /**< multiple of root node LP iterations used as total LP iteration
71  * limit for obbt (<= 0: no limit ) */
72 #define DEFAULT_MINITLIMIT 5000L /**< minimum LP iteration limit */
73 #define DEFAULT_ONLYNONCONVEXVARS FALSE /**< only apply obbt on non-convex variables */
74 #define DEFAULT_TIGHTINTBOUNDSPROBING TRUE /**< should bounds of integral variables be tightened during
75  * the probing mode? */
76 #define DEFAULT_TIGHTCONTBOUNDSPROBING FALSE /**< should bounds of continuous variables be tightened during
77  * the probing mode? */
78 #define DEFAULT_ORDERINGALGO 1 /**< which type of ordering algorithm should we use?
79  * (0: no, 1: greedy, 2: greedy reverse) */
80 #define OBBT_SCOREBASE 5 /**< base that is used to calculate a bounds score value */
81 #define GENVBOUND_PROP_NAME "genvbounds"
82 #define INTERVALINFTY 1E+43 /**< value for infinity in interval operations */
83 
84 #define DEFAULT_SEPARATESOL FALSE /**< should the obbt LP solution be separated? note that that by
85  * separating solution OBBT will apply all bound tightenings
86  * immediatly */
87 #define DEFAULT_SEPAMINITER 0 /**< minimum number of iteration spend to separate an obbt LP solution */
88 #define DEFAULT_SEPAMAXITER 10 /**< maximum number of iteration spend to separate an obbt LP solution */
89 #define DEFAULT_GENVBDSDURINGSEPA TRUE /**< try to create genvbounds during separation process? */
90 #define DEFAULT_PROPAGATEFREQ 0 /**< trigger a propagation round after that many bound tightenings
91  * (0: no propagation) */
92 
93 /** translate from one value of infinity to another
94  *
95  * if val is >= infty1, then give infty2, else give val
96  */
97 #define infty2infty(infty1, infty2, val) ((val) >= (infty1) ? (infty2) : (val))
98 
99 /*
100  * Data structures
101  */
102 
103 /** bound data */
104 struct Bound
105 {
106  SCIP_VAR* var; /**< variable */
107  SCIP_Real newval; /**< stores a probably tighter value for this bound */
108  SCIP_BOUNDTYPE boundtype; /**< type of bound */
109  unsigned int score; /**< score value that is used to group bounds */
110  unsigned int filtered:1; /**< thrown out during pre-filtering step */
111  unsigned int found:1; /**< stores whether a probably tighter value for this bound was found */
112  unsigned int done:1; /**< has this bound been processed already? */
113  unsigned int nonconvex:1; /**< is this bound affecting a nonconvex term? */
114  int index; /**< unique index */
115 };
116 typedef struct Bound BOUND;
117 
119 /** propagator data */
120 struct SCIP_PropData
121 {
122  BOUND** bounds; /**< array of interesting bounds */
123  SCIP_ROW* cutoffrow; /**< pointer to current objective cutoff row */
124  SCIP_PROP* genvboundprop; /**< pointer to genvbound propagator */
125  SCIP_Longint lastnode; /**< number of last node where obbt was performed */
126  SCIP_Longint npropagatedomreds; /**< number of domain reductions found during propagation */
127  SCIP_Longint nprobingiterations; /**< number of LP iterations during the probing mode */
128  SCIP_Longint nfilterlpiters; /**< number of LP iterations spend for filtering */
129  SCIP_Longint minitlimit; /**< minimum LP iteration limit */
130  SCIP_Real dualfeastol; /**< feasibility tolerance for reduced costs used in obbt; this value is
131  * used if SCIP's dual feastol is greater */
132  SCIP_Real conditionlimit; /**< maximum condition limit used in LP solver (-1.0: no limit) */
133  SCIP_Real boundstreps; /**< minimal relative improve for strengthening bounds */
134  SCIP_Real itlimitfactor; /**< LP iteration limit for obbt will be this factor times total LP
135  * iterations in root node */
136  SCIP_Bool applyfilterrounds; /**< apply filter rounds? */
137  SCIP_Bool applytrivialfilter; /**< should obbt try to use the LP solution to filter some bounds? */
138  SCIP_Bool genvbdsduringfilter;/**< should we try to generate genvbounds during trivial and aggressive
139  * filtering? */
140  SCIP_Bool genvbdsduringsepa; /**< try to create genvbounds during separation process? */
141  SCIP_Bool creategenvbounds; /**< should obbt try to provide genvbounds if possible? */
142  SCIP_Bool normalize; /**< should coefficients in filtering be normalized w.r.t. the domains
143  * sizes? */
144  SCIP_Bool onlynonconvexvars; /**< only apply obbt on non-convex variables */
145  SCIP_Bool tightintboundsprobing; /**< should bounds of integral variables be tightened during
146  * the probing mode? */
147  SCIP_Bool tightcontboundsprobing;/**< should bounds of continuous variables be tightened during
148  * the probing mode? */
149  SCIP_Bool separatesol; /**< should the obbt LP solution be separated? note that that by
150  * separating solution OBBT will apply all bound tightenings
151  * immediatly */
152  int orderingalgo; /**< which type of ordering algorithm should we use?
153  * (0: no, 1: greedy, 2: greedy reverse) */
154  int nbounds; /**< length of interesting bounds array */
155  int nminfilter; /**< minimal number of filtered bounds to apply another filter round */
156  int nfiltered; /**< number of filtered bounds by solving auxiliary variables */
157  int ntrivialfiltered; /**< number of filtered bounds because the LP value was equal to the bound */
158  int nsolvedbounds; /**< number of solved bounds during the loop in applyObbt() */
159  int ngenvboundsprobing; /**< number of non-trivial genvbounds generated and added during obbt */
160  int ngenvboundsaggrfil; /**< number of non-trivial genvbounds found during aggressive filtering */
161  int ngenvboundstrivfil; /**< number of non-trivial genvbounds found during trivial filtering */
162  int lastidx; /**< index to store the last undone and unfiltered bound */
163  int sepaminiter; /**< minimum number of iteration spend to separate an obbt LP solution */
164  int sepamaxiter; /**< maximum number of iteration spend to separate an obbt LP solution */
165  int propagatefreq; /**< trigger a propagation round after that many bound tightenings
166  * (0: no propagation) */
167  int propagatecounter; /**< number of bound tightenings since the last propagation round */
168 };
169 
170 
171 /*
172  * Local methods
173  */
174 
175 /** solves the LP and handles errors */
176 static
178  SCIP* scip, /**< SCIP data structure */
179  int itlimit, /**< maximal number of LP iterations to perform, or -1 for no limit */
180  SCIP_Bool* error, /**< pointer to store whether an unresolved LP error occurred */
181  SCIP_Bool* optimal /**< was the LP solved to optimalilty? */
182  )
183 {
184  SCIP_LPSOLSTAT lpsolstat;
185  SCIP_RETCODE retcode;
186 
187  assert(scip != NULL);
188  assert(itlimit == -1 || itlimit >= 0);
189  assert(error != NULL);
190  assert(optimal != NULL);
191 
192  *optimal = FALSE;
193  *error = FALSE;
194 
195  retcode = SCIPsolveProbingLP(scip, itlimit, error, NULL);
196 
197  lpsolstat = SCIPgetLPSolstat(scip);
198 
199  /* an error should not kill the overall solving process */
200  if( retcode != SCIP_OKAY )
201  {
202  SCIPwarningMessage(scip, " error while solving LP in obbt propagator; LP solve terminated with code <%d>\n", retcode);
203  SCIPwarningMessage(scip, " this does not affect the remaining solution procedure --> continue\n");
204 
205  *error = TRUE;
206 
207  return SCIP_OKAY;
208  }
209 
210  if( lpsolstat == SCIP_LPSOLSTAT_OPTIMAL )
211  {
212  assert(!*error);
213  *optimal = TRUE;
214  }
215 #ifdef SCIP_DEBUG
216  else
217  {
218  switch( lpsolstat )
219  {
221  SCIPdebugMessage(" reached lp iteration limit\n");
222  break;
224  SCIPdebugMessage(" reached time limit while solving lp\n");
225  break;
227  SCIPdebugMessage(" lp was unbounded\n");
228  break;
230  SCIPdebugMessage(" lp was not solved\n");
231  break;
233  SCIPdebugMessage(" an error occured during solving lp\n");
234  break;
237  case SCIP_LPSOLSTAT_OPTIMAL: /* should not appear because it is handled earlier */
238  default:
239  SCIPdebugMessage(" received an unexpected solstat during solving lp: %d\n", lpsolstat);
240  }
241  }
242 #endif
243 
244  return SCIP_OKAY;
245 }
246 
247 /** adds the objective cutoff to the LP; must be in probing mode */
248 static
250  SCIP* scip, /**< SCIP data structure */
251  SCIP_PROPDATA* propdata /**< data of the obbt propagator */
252  )
253 {
254  SCIP_ROW* row;
255  SCIP_VAR** vars;
256  char rowname[SCIP_MAXSTRLEN];
257 
258  int nvars;
259  int i;
260 
261  assert(scip != NULL);
262  assert(SCIPinProbing(scip));
263  assert(propdata != NULL);
264  assert(propdata->cutoffrow == NULL);
265 
266  if( SCIPisInfinity(scip, SCIPgetCutoffbound(scip)) )
267  {
268  SCIPdebugMessage("no objective cutoff since there is no cutoff bound\n");
269  return SCIP_OKAY;
270  }
271 
272  SCIPdebugMessage("create objective cutoff and add it to the LP\n");
273 
274  /* get variables data */
275  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
276 
277  /* create objective cutoff row; set local flag to FALSE since primal cutoff is globally valid */
278  (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "obbt_objcutoff");
279  SCIP_CALL( SCIPcreateEmptyRowUnspec(scip, &row, rowname, -SCIPinfinity(scip), SCIPgetCutoffbound(scip), FALSE, FALSE, FALSE) );
280  SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
281 
282  for( i = 0; i < nvars; i++ )
283  {
284  SCIP_CALL( SCIPaddVarToRow(scip, row, vars[i], SCIPvarGetObj(vars[i])) );
285  }
286  SCIP_CALL( SCIPflushRowExtensions(scip, row) );
287 
288  /* add row to the LP */
289  SCIP_CALL( SCIPaddRowProbing(scip, row) );
290 
291  propdata->cutoffrow = row;
292  assert(SCIProwIsInLP(propdata->cutoffrow));
293 
294  return SCIP_OKAY;
295 }
296 
297 /** determines, whether a variable is already locally fixed */
298 static
300  SCIP* scip, /**< SCIP data structure */
301  SCIP_VAR* var /**< variable to check */
302  )
303 {
304  return SCIPisFeasEQ(scip, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var));
305 }
306 
307 /** sets objective to minimize or maximize a single variable */
308 static
310  SCIP* scip,
311  SCIP_PROPDATA* propdata,
312  BOUND* bound,
313  SCIP_Real coef
314  )
315 {
316 #ifdef SCIP_DEBUG
317  SCIP_VAR** vars;
318  int nvars;
319  int counter;
320  int i;
321 #endif
322 
323  assert( scip != NULL );
324  assert( propdata != NULL );
325  assert( bound != NULL );
326 
327  /* set the objective for bound->var */
328  if( bound->boundtype == SCIP_BOUNDTYPE_LOWER )
329  {
330  SCIP_CALL( SCIPchgVarObjProbing(scip, bound->var, coef) );
331  }
332  else
333  {
334  SCIP_CALL( SCIPchgVarObjProbing(scip, bound->var, -coef) );
335  }
336 
337 #ifdef SCIP_DEBUG
338  vars = SCIPgetVars(scip);
339  nvars = SCIPgetNVars(scip);
340  counter = 0;
341 
342  for( i = 0; i < nvars; ++i )
343  {
344  if( SCIPgetVarObjProbing(scip, vars[i]) != 0.0 )
345  ++counter;
346  }
347 
348  assert((counter == 0 && coef == 0.0) || (counter == 1 && coef != 0.0));
349 #endif
350 
351  return SCIP_OKAY;
352 }
353 
354 /** determines whether variable should be included in the right-hand side of the generalized variable bound */
355 static
357  SCIP* scip, /**< SCIP data structure */
358  SCIP_VAR* var /**< variable to check */
359  )
360 {
361  SCIP_Real redcost;
362 
363  assert(scip != NULL);
364  assert(var != NULL);
365 
367  return FALSE;
369  redcost = SCIPgetVarRedcost(scip, var);
370  assert(redcost != SCIP_INVALID); /*lint !e777 */
371 
372  if( redcost == SCIP_INVALID ) /*lint !e777 */
373  return FALSE;
374 
375  if( redcost < SCIPdualfeastol(scip) && redcost > -SCIPdualfeastol(scip) )
376  return FALSE;
377 
378  return TRUE;
379 }
380 
381 /** returns number of LP iterations left (-1: no limit ) */
382 static
384  SCIP* scip, /**< SCIP data structure */
385  SCIP_Longint nolditerations, /**< iterations count at the beginning of the corresponding function */
386  SCIP_Longint itlimit /**< LP iteration limit (-1: no limit) */
387  )
388 {
389  SCIP_Longint itsleft;
390 
391  assert(scip != NULL);
392  assert(nolditerations >= 0);
393  assert(itlimit == -1 || itlimit >= 0);
394 
395  if( itlimit == -1 )
396  {
397  SCIPdebugMessage("iterations left: unlimited\n");
398  return -1;
399  }
400  else
401  {
402  itsleft = itlimit - ( SCIPgetNLPIterations(scip) - nolditerations );
403  itsleft = MAX(itsleft, 0);
404  itsleft = MIN(itsleft, INT_MAX);
405 
406  SCIPdebugMessage("iterations left: %d\n", (int) itsleft);
407  return (int) itsleft;
408  }
409 }
410 
411 /** returns the objective coefficient for a variable's bound that will be chosen during filtering */
412 static
414  SCIP* scip, /**< SCIP data structure */
415  SCIP_PROPDATA* propdata, /**< data of the obbt propagator */
416  SCIP_VAR* var, /**< variable */
417  SCIP_BOUNDTYPE boundtype /**< boundtype to be filtered? */
418  )
419 {
420  SCIP_Real lb;
421  SCIP_Real ub;
422 
423  assert(scip != NULL);
424  assert(propdata != NULL);
425  assert(var != NULL);
426 
427  lb = SCIPvarGetLbLocal(var);
428  ub = SCIPvarGetUbLocal(var);
429 
430  /* this function should not be called for fixed variables */
431  assert(!varIsFixedLocal(scip, var));
432 
433  /* infinite bounds will not be reached */
434  if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPisInfinity(scip, -lb) )
435  return 0.0;
436  if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPisInfinity(scip, ub) )
437  return 0.0;
438 
439  if( propdata->normalize )
440  {
441  /* if the length of the domain is too large then the coefficient should be set to +/- 1.0 */
442  if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPisInfinity(scip, ub) )
443  return 1.0;
444  if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPisInfinity(scip, -lb) )
445  return -1.0;
446 
447  /* otherwise the coefficient is +/- 1.0 / ( ub - lb ) */
448  return boundtype == SCIP_BOUNDTYPE_LOWER ? 1.0 / (ub - lb) : -1.0 / (ub - lb);
449  }
450  else
451  {
452  return boundtype == SCIP_BOUNDTYPE_LOWER ? 1.0 : -1.0;
453  }
454 }
455 
456 /** creates a genvbound if the dual LP solution provides such information
457  *
458  * Consider the problem
459  *
460  * min { +/- x_i : obj * x <= z, lb <= Ax <= ub, l <= x <= u },
461  *
462  * where z is the current cutoff bound. Let (mu, nu, gamma, alpha, beta) >= 0 be the optimal solution of the dual of
463  * problem (P), where the variables correspond to the primal inequalities in the following way:
464  *
465  * Ax >= lb <-> mu
466  * -Ax >= -ub <-> nu
467  * -obj * x >= -z <-> gamma
468  * x >= l <-> alpha
469  * -x >= -u <-> beta
470  *
471  * Fixing these multipliers, by weak duality, we obtain the inequality
472  *
473  * +/- x_i >= lb*mu - ub*nu - z*gamma + l*alpha - u*beta
474  *
475  * that holds for all primal feasible points x with objective value at least z. Setting
476  *
477  * c = lb*mu - ub*nu, redcost_k = alpha_k - beta_k
478  *
479  * we obtain the inequality
480  *
481  * +/- x_i >= sum ( redcost_k * x_k ) + (-gamma) * cutoff_bound + c,
482  *
483  * that holds for all primal feasible points with objective value at least cutoff_bound. Therefore, the latter
484  * inequality can be added as a generalized variable bound.
485  */
486 static
488  SCIP* scip, /**< SCIP data structure */
489  SCIP_PROPDATA* propdata, /**< data of the obbt propagator */
490  BOUND* bound, /**< bound of x_i */
491  SCIP_Bool* found /**< pointer to store if we have found a non-trivial genvbound */
492  )
493 {
494  assert(scip != NULL);
495  assert(bound != NULL);
496  assert(propdata != NULL);
497  assert(propdata->genvboundprop != NULL);
498  assert(found != NULL);
500  *found = FALSE;
501 
502  /* make sure we are in probing mode having an optimal LP solution */
503  assert(SCIPinProbing(scip));
504 
505  assert(SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL);
506 
507  /* only genvbounds created in the root node are globally valid
508  *
509  * note: depth changes to one if we use the probing mode to solve the obbt LPs
510  */
511  assert(SCIPgetDepth(scip) == 0 || (SCIPinProbing(scip) && SCIPgetDepth(scip) == 1));
512 
513  SCIPdebugMessage(" try to create a genvbound for <%s>...\n", SCIPvarGetName(bound->var));
514 
515  /* a genvbound with a multiplier for x_i would not help us */
516  if( SCIPisZero(scip, SCIPgetVarRedcost(scip, bound->var)) )
517  {
518  SCIP_VAR** vars; /* global variables array */
519  SCIP_VAR** genvboundvars; /* genvbound variables array */
520 
521  SCIP_VAR* xi; /* variable x_i */
522 
523  SCIP_Real* genvboundcoefs; /* genvbound coefficients array */
524 
525  SCIP_Real gamma_dual; /* dual multiplier of objective cutoff */
526 
527  int k; /* variable for indexing global variables array */
528  int ncoefs; /* number of nonzero coefficients in genvbound */
529  int nvars; /* number of global variables */
530 
531  /* set x_i */
532  xi = bound->var;
533 
534  /* get variable data */
535  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
536 
537  /* count nonzero coefficients in genvbound */
538  ncoefs = 0;
539  for( k = 0; k < nvars; k++ )
540  {
541  if( includeVarGenVBound(scip, vars[k]) )
542  {
543  assert(vars[k] != xi);
544  ncoefs++;
545  }
546  }
547 
548  /* get dual multiplier for the objective cutoff (set to zero if there is no) */
549  if( propdata->cutoffrow == NULL )
550  {
551  gamma_dual = 0.0;
552  }
553  else
554  {
555  assert(!SCIPisInfinity(scip, SCIPgetCutoffbound(scip)));
556 
557  /* note that the objective cutoff is of the form
558  * -inf <= obj * x <= cutoff_bound
559  * but we want the positive dual multiplier!
560  */
561  gamma_dual = -SCIProwGetDualsol(propdata->cutoffrow);
562  }
563 
564  /* we need at least one nonzero coefficient or a nonzero dual multiplier for the objective cutoff */
565  if( ncoefs > 0 || !SCIPisZero(scip, gamma_dual) )
566  {
567  SCIP_Bool addgenvbound; /* if everything is fine with the redcosts and the bounds, add the genvbound */
568  SCIP_Real c; /* helper variable to calculate constant term in genvbound */
569  int idx; /* variable for indexing genvbound's coefficients array */
570 
571  /* add the bound if the bool is still TRUE after the loop */
572  addgenvbound = TRUE;
573 
574  /* there should be no coefficient for x_i */
575  assert(SCIPisZero(scip, SCIPgetVarRedcost(scip, xi)));
576 
577  /* allocate memory for storing the genvbounds right-hand side variables and coefficients */
578  SCIP_CALL( SCIPallocBufferArray(scip, &(genvboundvars), ncoefs) );
579  SCIP_CALL( SCIPallocBufferArray(scip, &(genvboundcoefs), ncoefs) );
580 
581  /* set c = lb*mu - ub*nu - z*gamma + l*alpha - u*beta */
582  c = SCIPgetLPObjval(scip);
583 
584  /* subtract ( - z * gamma ) from c */
585  c += SCIPgetCutoffbound(scip) * gamma_dual;
586 
587  /* subtract ( l*alpha - u*beta ) from c and set the coefficients of the variables */
588  idx = 0;
589  for( k = 0; k < nvars; k++ )
590  {
591  SCIP_VAR* xk;
592 
593  xk = vars[k];
594 
595  if( includeVarGenVBound(scip, xk) )
596  {
597  SCIP_Real redcost;
598 
599  redcost = SCIPgetVarRedcost(scip, xk);
600 
601  assert(redcost != SCIP_INVALID); /*lint !e777 */
602  assert(xk != xi);
603 
604  /* in this case dont add a genvbound */
605  if( ( (redcost > SCIPdualfeastol(scip)) && SCIPisInfinity(scip, -SCIPvarGetLbLocal(xk)) ) ||
606  ( (redcost < -SCIPdualfeastol(scip)) && SCIPisInfinity(scip, SCIPvarGetUbLocal(xk)) ) )
607  {
608  addgenvbound = FALSE;
609  break;
610  }
611 
612  /* store coefficients */
613  assert(idx < ncoefs);
614  genvboundvars[idx] = xk;
615  genvboundcoefs[idx] = redcost;
616  idx++;
617 
618  /* if redcost > 0, then redcost = alpha_k, otherwise redcost = - beta_k */
619  assert(redcost <= 0 || !SCIPisInfinity(scip, -SCIPvarGetLbLocal(xk)));
620  assert(redcost >= 0 || !SCIPisInfinity(scip, SCIPvarGetUbLocal(xk)));
621  c -= redcost > 0 ? redcost * SCIPvarGetLbLocal(xk) : redcost * SCIPvarGetUbLocal(xk);
622  }
623  }
624 
625  assert(!addgenvbound || idx == ncoefs);
626 
627  /* add genvbound */
628  if( addgenvbound && !SCIPisInfinity(scip, -c) )
629  {
630  SCIPdebugMessage(" adding genvbound\n");
631  SCIP_CALL( SCIPgenVBoundAdd(scip, propdata->genvboundprop, genvboundvars, xi, genvboundcoefs, ncoefs,
632  !SCIPisPositive(scip, gamma_dual) ? 0.0 : -gamma_dual, c, bound->boundtype) );
633 
634  *found = TRUE;
635  }
636 
637  /* free arrays */
638  SCIPfreeBufferArray(scip, &genvboundcoefs);
639  SCIPfreeBufferArray(scip, &genvboundvars);
640  }
641  else
642  {
643  SCIPdebugMessage(" trivial genvbound, skipping\n");
644  }
645  }
646  else
647  {
648  SCIPdebugMessage(" found multiplier for <%s>: %g, skipping\n",
649  SCIPvarGetName(bound->var), SCIPgetVarRedcost(scip, bound->var));
650  }
651 
652  return SCIP_OKAY;
653 }
654 
655 /** exchange a bound which has been processed and updates the last undone and unfiltered bound index
656  * NOTE: this method has to be called after filtering or processing a bound
657  */
658 static
659 void exchangeBounds(
660  SCIP_PROPDATA* propdata, /**< propagator data */
661  int i /**< bound that was filtered or processed */
662  )
663 {
664  assert(i >= 0 && i < propdata->nbounds);
665  assert(propdata->lastidx >= 0 && propdata->lastidx < propdata->nbounds);
666 
667  /* exchange the bounds */
668  if( propdata->lastidx != i )
669  {
670  BOUND* tmp;
672  tmp = propdata->bounds[i];
673  propdata->bounds[i] = propdata->bounds[propdata->lastidx];
674  propdata->bounds[propdata->lastidx] = tmp;
675  }
676 
677  propdata->lastidx -= 1;
678 }
679 
680 /** trying to filter some bounds using the existing LP solution */
681 static
683  SCIP* scip, /**< original SCIP data structure */
684  SCIP_PROPDATA* propdata, /**< data of the obbt propagator */
685  int* nfiltered, /**< how many bounds were filtered this round? */
686  BOUND* currbound /**< bound for which OBBT LP was solved (Note: might be NULL) */
687  )
688 {
689  int i;
690 
691  assert(scip != NULL);
692  assert(propdata != NULL);
693  assert(nfiltered != NULL);
695  *nfiltered = 0;
696 
697  /* only apply filtering if an LP solution is at hand */
699  {
700  SCIPdebugMessage("can't filter using existing lp solution since it was not solved to optimality\n");
701  return SCIP_OKAY;
702  }
703 
704  /* check if a bound is tight */
705  for( i = propdata->nbounds - 1; i >= 0; --i )
706  {
707  BOUND* bound; /* shortcut for current bound */
708 
709  SCIP_Real solval; /* the variables value in the current solution */
710  SCIP_Real boundval; /* current local bound for the variable */
711 
712  bound = propdata->bounds[i];
713  if( bound->filtered || bound->done )
714  continue;
715 
716  boundval = bound->boundtype == SCIP_BOUNDTYPE_UPPER ?
717  SCIPvarGetUbLocal(bound->var) : SCIPvarGetLbLocal(bound->var);
718  solval = SCIPvarGetLPSol(bound->var);
719 
720  /* bound is tight; since this holds for all fixed variables, those are filtered here automatically */
721  if( (bound->boundtype == SCIP_BOUNDTYPE_UPPER && SCIPisFeasGE(scip, solval, boundval))
722  || (bound->boundtype == SCIP_BOUNDTYPE_LOWER && SCIPisFeasLE(scip, solval, boundval)) )
723  {
724  SCIP_BASESTAT basestat;
725 
726  /* mark bound as filtered */
727  bound->filtered = TRUE;
728  SCIPdebugMessage("trivial filtered var: %s boundval=%e solval=%e\n", SCIPvarGetName(bound->var), boundval, solval);
729 
730  /* get the basis status of the variable */
731  basestat = SCIPcolGetBasisStatus(SCIPvarGetCol(bound->var));
732 
733  /* solve corresponding OBBT LP and try to generate a nontrivial genvbound */
734  if( propdata->genvbdsduringfilter && currbound != NULL && basestat == SCIP_BASESTAT_BASIC )
735  {
736 #ifndef NDEBUG
737  int j;
738 #endif
739  SCIP_Bool optimal;
740  SCIP_Bool error;
741 
742  /* set objective coefficient of the bound */
743  SCIP_CALL( SCIPchgVarObjProbing(scip, currbound->var, 0.0) );
744  SCIP_CALL( setObjProbing(scip, propdata, bound, 1.0) );
745 
746 #ifndef NDEBUG
747  for( j = 0; j < SCIPgetNVars(scip); ++j )
748  {
749  SCIP_VAR* var;
750 
751  var = SCIPgetVars(scip)[j];
752  assert(var != NULL);
753  assert(SCIPisZero(scip, SCIPgetVarObjProbing(scip, var)) || var == bound->var);
754  }
755 #endif
756 
757  /* solve the OBBT LP */
758  propdata->nprobingiterations -= SCIPgetNLPIterations(scip);
759  SCIP_CALL( solveLP(scip, -1, &error, &optimal) );
760  propdata->nprobingiterations += SCIPgetNLPIterations(scip);
761  assert(propdata->nprobingiterations >= 0);
762 
763  /* try to generate a genvbound if we have solved the OBBT LP */
764  if( optimal && propdata->genvboundprop != NULL
765  && (SCIPgetDepth(scip) == 0 || (SCIPinProbing(scip) && SCIPgetDepth(scip) == 1)) )
766  {
768 
769  assert(!error);
770  SCIP_CALL( createGenVBound(scip, propdata, bound, &found) );
771 
772  if( found )
773  {
774  propdata->ngenvboundstrivfil += 1;
775  SCIPdebugMessage("found genvbound during trivial filtering\n");
776  }
777  }
778 
779  /* restore objective function */
780  SCIP_CALL( setObjProbing(scip, propdata, bound, 0.0) );
781  SCIP_CALL( setObjProbing(scip, propdata, currbound, 1.0) );
782  }
783 
784  /* exchange bound i with propdata->bounds[propdata->lastidx] */
785  if( propdata->lastidx >= 0 )
786  exchangeBounds(propdata, i);
787 
788  /* increase number of filtered variables */
789  (*nfiltered)++;
790  }
791  }
792 
793  return SCIP_OKAY;
794 }
795 
796 /** enforces one round of filtering */
797 static
799  SCIP* scip, /**< SCIP data structure */
800  SCIP_PROPDATA* propdata, /**< data of the obbt propagator */
801  int itlimit, /**< LP iteration limit (-1: no limit) */
802  int* nfiltered, /**< how many bounds were filtered this round */
803  SCIP_Real* objcoefs, /**< array to store the nontrivial objective coefficients */
804  int* objcoefsinds, /**< array to store bound indices for which their corresponding variables
805  * has a nontrivial objective coefficient */
806  int nobjcoefs /**< number of nontrivial objective coefficients */
807  )
808 {
809  SCIP_VAR** vars; /* array of the problems variables */
810  SCIP_Bool error;
811  SCIP_Bool optimal;
812 
813  int nvars; /* number of the problems variables */
814  int i;
815 
816  assert(scip != NULL);
817  assert(SCIPinProbing(scip));
818  assert(propdata != NULL);
819  assert(itlimit == -1 || itlimit >= 0);
820  assert(nfiltered != NULL);
821  assert(objcoefs != NULL);
822  assert(objcoefsinds != NULL);
823  assert(nobjcoefs >= 0);
824 
825  *nfiltered = 0;
826 
827  /* get variable data */
828  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
829 
830  /* solve LP */
831  propdata->nfilterlpiters -= (int) SCIPgetNLPIterations(scip);
832  SCIP_CALL( solveLP(scip, itlimit, &error, &optimal) );
833  propdata->nfilterlpiters += (int) SCIPgetNLPIterations(scip);
834  assert(propdata->nfilterlpiters >= 0);
835 
836  if( !optimal )
837  {
838  SCIPdebugMessage("skipping filter round since the LP was not solved to optimality\n");
839  return SCIP_OKAY;
840  }
841 
842  assert(!error);
843 
844  /* check if a bound is tight */
845  for( i = 0; i < propdata->nbounds; i++ )
846  {
847  BOUND* bound; /* shortcut for current bound */
848 
849  SCIP_Real solval; /* the variables value in the current solution */
850  SCIP_Real boundval; /* current local bound for the variable */
851 
852  bound = propdata->bounds[i];
853 
854  /* if bound is filtered it was handled already before */
855  if( bound->filtered )
856  continue;
857 
858  boundval = bound->boundtype == SCIP_BOUNDTYPE_UPPER ?
859  SCIPvarGetUbLocal(bound->var) : SCIPvarGetLbLocal(bound->var);
860  solval = SCIPvarGetLPSol(bound->var);
861 
862  /* bound is tight */
863  if( (bound->boundtype == SCIP_BOUNDTYPE_UPPER && SCIPisFeasGE(scip, solval, boundval))
864  || (bound->boundtype == SCIP_BOUNDTYPE_LOWER && SCIPisFeasLE(scip, solval, boundval)) )
865  {
866  SCIP_Real objcoef;
867  SCIP_BASESTAT basestat;
868 
869  /* mark bound as filtered */
870  bound->filtered = TRUE;
871 
872  /* get the basis status of the variable */
873  basestat = SCIPcolGetBasisStatus(SCIPvarGetCol(bound->var));
874 
875  /* increase number of filtered variables */
876  (*nfiltered)++;
877 
878  /* solve corresponding OBBT LP and try to generate a nontrivial genvbound */
879  if( propdata->genvbdsduringfilter && basestat == SCIP_BASESTAT_BASIC )
880  {
881  int j;
882 
883  /* set all objective coefficients to zero */
884  for( j = 0; j < nobjcoefs; ++j )
885  {
886  BOUND* filterbound;
887 
888  filterbound = propdata->bounds[ objcoefsinds[j] ];
889  assert(filterbound != NULL);
890 
891  SCIP_CALL( SCIPchgVarObjProbing(scip, filterbound->var, 0.0) );
892  }
893 
894 #ifndef NDEBUG
895  for( j = 0; j < nvars; ++j )
896  assert(SCIPisZero(scip, SCIPgetVarObjProbing(scip, vars[j])));
897 #endif
898 
899  /* set objective coefficient of the bound */
900  SCIP_CALL( setObjProbing(scip, propdata, bound, 1.0) );
901 
902  /* solve the OBBT LP */
903  propdata->nfilterlpiters -= (int) SCIPgetNLPIterations(scip);
904  SCIP_CALL( solveLP(scip, -1, &error, &optimal) );
905  propdata->nfilterlpiters += (int) SCIPgetNLPIterations(scip);
906  assert(propdata->nfilterlpiters >= 0);
907 
908  /* try to generate a genvbound if we have solved the OBBT LP */
909  if( optimal && propdata->genvboundprop != NULL
910  && (SCIPgetDepth(scip) == 0 || (SCIPinProbing(scip) && SCIPgetDepth(scip) == 1)) )
911  {
913 
914  assert(!error);
915  SCIP_CALL( createGenVBound(scip, propdata, bound, &found) );
916 
917  if( found )
918  {
919  propdata->ngenvboundsaggrfil += 1;
920  SCIPdebugMessage("found genvbound during aggressive filtering\n");
921  }
922 
923  }
924 
925  /* restore objective function */
926  for( j = 0; j < nobjcoefs; ++j )
927  {
928  BOUND* filterbound;
929 
930  filterbound = propdata->bounds[ objcoefsinds[j] ];
931  assert(filterbound != NULL);
932 
933  /* NOTE: only restore coefficients of nonfiltered bounds */
934  if( !filterbound->filtered )
935  {
936  assert(!SCIPisZero(scip, objcoefs[j]));
937  SCIP_CALL( SCIPchgVarObjProbing(scip, propdata->bounds[ objcoefsinds[j] ]->var, objcoefs[j]) );
938  }
939  }
940  }
941 
942  /* get the corresponding variable's objective coefficient */
943  objcoef = SCIPgetVarObjProbing(scip, bound->var);
944 
945  /* change objective coefficient if it was set up for this bound */
946  if( (bound->boundtype == SCIP_BOUNDTYPE_UPPER && SCIPisNegative(scip, objcoef))
947  || (bound->boundtype == SCIP_BOUNDTYPE_LOWER && SCIPisPositive(scip, objcoef)) )
948  {
949  SCIP_CALL( SCIPchgVarObjProbing(scip, bound->var, 0.0) );
950  }
951  }
952  }
953 
954  return SCIP_OKAY;
955 }
956 
957 /** filter some bounds that are not improvable by solving auxiliary LPs */
958 static
960  SCIP* scip, /**< SCIP data structure */
961  SCIP_PROPDATA* propdata, /**< data of the obbt propagator */
962  SCIP_Longint itlimit /**< LP iteration limit (-1: no limit) */
963  )
964 {
965  SCIP_VAR** vars;
966  SCIP_Longint nolditerations;
967  SCIP_Real* objcoefs; /* array to store the nontrivial objective coefficients */
968  int* objcoefsinds; /* array to store bound indices for which the corresponding variable
969  * has a nontrivial objective coefficient */
970  int nobjcoefs; /* number of nontrivial objective coefficients */
971  int nleftiterations;
972  int i;
973  int nfiltered;
974  int ntotalfiltered;
975  int nvars;
976 
977  assert(scip != NULL);
978  assert(SCIPinProbing(scip));
979  assert(propdata != NULL);
980  assert(itlimit == -1 || itlimit >= 0);
981 
982  ntotalfiltered = 0;
983  nolditerations = SCIPgetNLPIterations(scip);
984  nleftiterations = getIterationsLeft(scip, nolditerations, itlimit);
985 
986  /* get variable data */
987  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
988 
989  SCIPdebugMessage("start filter rounds\n");
990 
991  SCIP_CALL( SCIPallocBufferArray(scip, &objcoefs, propdata->nbounds) );
992  SCIP_CALL( SCIPallocBufferArray(scip, &objcoefsinds, propdata->nbounds) );
993  nobjcoefs = 0;
994 
995  /*
996  * 1.) Try first to filter lower bounds of interesting variables, whose bounds are not already filtered
997  */
998 
999  for( i = 0; i < nvars; i++ )
1000  {
1001  SCIP_CALL( SCIPchgVarObjProbing(scip, vars[i], 0.0) );
1002  }
1003 
1004  for( i = 0; i < propdata->nbounds; i++ )
1005  {
1006  if( propdata->bounds[i]->boundtype == SCIP_BOUNDTYPE_LOWER && !propdata->bounds[i]->filtered
1007  && !propdata->bounds[i]->done )
1008  {
1009  SCIP_Real objcoef;
1010 
1011  objcoef = getFilterCoef(scip, propdata, propdata->bounds[i]->var, SCIP_BOUNDTYPE_LOWER);
1012 
1013  if( !SCIPisZero(scip, objcoef) )
1014  {
1015  SCIP_CALL( SCIPchgVarObjProbing(scip, propdata->bounds[i]->var, objcoef) );
1016 
1017  /* store nontrivial objective coefficients */
1018  objcoefs[nobjcoefs] = objcoef;
1019  objcoefsinds[nobjcoefs] = i;
1020  ++nobjcoefs;
1021  }
1022  }
1023  }
1024 
1025  do
1026  {
1027  SCIPdebugMessage("doing a lower bounds round\n");
1028  SCIP_CALL( filterRound(scip, propdata, nleftiterations, &nfiltered, objcoefs, objcoefsinds, nobjcoefs) );
1029  ntotalfiltered += nfiltered;
1030  SCIPdebugMessage("filtered %d more bounds in lower bounds round\n", nfiltered);
1031 
1032  /* update iterations left */
1033  nleftiterations = getIterationsLeft(scip, nolditerations, itlimit);
1034  }
1035  while( nfiltered >= propdata->nminfilter && ( nleftiterations == -1 || nleftiterations > 0 ) );
1036 
1037  /*
1038  * 2.) Now try to filter the remaining upper bounds of interesting variables, whose bounds are not already filtered
1039  */
1040 
1041  /* set all objective coefficients to zero */
1042  for( i = 0; i < nobjcoefs; i++ )
1043  {
1044  BOUND* bound;
1045 
1046  assert(objcoefsinds[i] >= 0 && objcoefsinds[i] < propdata->nbounds);
1047  bound = propdata->bounds[ objcoefsinds[i] ];
1048  assert(bound != NULL);
1049  SCIP_CALL( SCIPchgVarObjProbing(scip, bound->var, 0.0) );
1050  }
1051 
1052  /* reset number of nontrivial objective coefficients */
1053  nobjcoefs = 0;
1054 
1055 #ifndef NDEBUG
1056  for( i = 0; i < nvars; ++i )
1057  assert(SCIPisZero(scip, SCIPgetVarObjProbing(scip, vars[i])));
1058 #endif
1059 
1060  for( i = 0; i < propdata->nbounds; i++ )
1061  {
1062  if( propdata->bounds[i]->boundtype == SCIP_BOUNDTYPE_UPPER && !propdata->bounds[i]->filtered )
1063  {
1064  SCIP_Real objcoef;
1065 
1066  objcoef = getFilterCoef(scip, propdata, propdata->bounds[i]->var, SCIP_BOUNDTYPE_UPPER);
1067 
1068  if( !SCIPisZero(scip, objcoef) )
1069  {
1070  SCIP_CALL( SCIPchgVarObjProbing(scip, propdata->bounds[i]->var, objcoef) );
1071 
1072  /* store nontrivial objective coefficients */
1073  objcoefs[nobjcoefs] = objcoef;
1074  objcoefsinds[nobjcoefs] = i;
1075  ++nobjcoefs;
1076  }
1077  }
1078  }
1079 
1080  do
1081  {
1082  SCIPdebugMessage("doing an upper bounds round\n");
1083  SCIP_CALL( filterRound(scip, propdata, nleftiterations, &nfiltered, objcoefs, objcoefsinds, nobjcoefs) );
1084  SCIPdebugMessage("filtered %d more bounds in upper bounds round\n", nfiltered);
1085  ntotalfiltered += nfiltered;
1086  /* update iterations left */
1087  nleftiterations = getIterationsLeft(scip, nolditerations, itlimit);
1088  }
1089  while( nfiltered >= propdata->nminfilter && ( nleftiterations == -1 || nleftiterations > 0 ) );
1090 
1091  SCIPdebugMessage("filtered %d this round\n", ntotalfiltered);
1092  propdata->nfiltered += ntotalfiltered;
1093 
1094  /* free array */
1095  SCIPfreeBufferArray(scip, &objcoefsinds);
1096  SCIPfreeBufferArray(scip, &objcoefs);
1097 
1098  return SCIP_OKAY;
1099 }
1100 
1101 /** applies possible bound changes that were found */
1102 static
1104  SCIP* scip, /**< SCIP data structure */
1105  SCIP_PROPDATA* propdata, /**< data of the obbt propagator */
1106  SCIP_RESULT* result /**< result pointer */
1107  )
1108 {
1109 #ifdef SCIP_DEBUG
1110  int ntightened; /* stores the number of successful bound changes */
1111 #endif
1112  int i;
1113 
1114  assert(scip != NULL);
1115  assert(!SCIPinProbing(scip));
1116  assert(propdata != NULL);
1117  assert(result != NULL);
1118  assert(*result == SCIP_DIDNOTFIND);
1119 
1120  SCIPdebug( ntightened = 0 );
1121 
1122  for( i = 0; i < propdata->nbounds; i++ )
1123  {
1124  BOUND* bound; /* shortcut to the current bound */
1125  SCIP_Bool infeas; /* stores wether a tightening approach forced an infeasibilty */
1126  SCIP_Bool tightened; /* stores wether a tightening approach was successful */
1127 
1128  bound = propdata->bounds[i];
1129 
1130  if( bound->found )
1131  {
1132  SCIPdebug( double oldbound = (bound->boundtype == SCIP_BOUNDTYPE_LOWER)
1133  ? SCIPvarGetLbLocal(bound->var)
1134  : SCIPvarGetUbLocal(bound->var) );
1135 
1136  if( bound->boundtype == SCIP_BOUNDTYPE_LOWER )
1137  {
1138  SCIP_CALL( SCIPtightenVarLb(scip, bound->var, bound->newval, FALSE, &infeas, &tightened) );
1139  }
1140  else
1141  {
1142  SCIP_CALL( SCIPtightenVarUb(scip, bound->var, bound->newval, FALSE, &infeas, &tightened) );
1143  }
1144 
1145  /* handle information about the success */
1146  if( infeas )
1147  {
1148  *result = SCIP_CUTOFF;
1149  SCIPdebugMessage("cut off\n");
1150  break;
1151  }
1152 
1153  if( tightened )
1154  {
1155  SCIPdebug( SCIPdebugMessage("tightended: %s old: %e new: %e\n" , SCIPvarGetName(bound->var), oldbound,
1156  bound->newval) );
1157  *result = SCIP_REDUCEDDOM;
1158  SCIPdebug( ntightened++ );
1159  }
1160  }
1161  }
1162 
1163  SCIPdebug( SCIPdebugMessage("tightened bounds: %d\n", ntightened) );
1164 
1165  return SCIP_OKAY;
1166 }
1167 
1168 /** tries to tighten a bound in probing mode */
1169 static
1171  SCIP* scip, /**< SCIP data structure */
1172  BOUND* bound, /**< bound that could be tightened */
1173  SCIP_Real newval, /**< new bound value */
1174  SCIP_Bool* tightened /**< was tightening successful? */
1175  )
1176 {
1177  SCIP_Real lb;
1178  SCIP_Real ub;
1179 
1180  assert(scip != NULL);
1181  assert(SCIPinProbing(scip));
1182  assert(bound != NULL);
1183  assert(tightened != NULL);
1184 
1185  *tightened = FALSE;
1186 
1187  /* get old bounds */
1188  lb = SCIPvarGetLbLocal(bound->var);
1189  ub = SCIPvarGetUbLocal(bound->var);
1190 
1191  if( bound->boundtype == SCIP_BOUNDTYPE_LOWER )
1192  {
1193  /* round bounds new value if variable is integral */
1194  if( SCIPvarIsIntegral(bound->var) )
1195  newval = SCIPceil(scip, newval);
1196 
1197  /* ensure that we give consistent bounds to the LP solver */
1198  if( newval > ub )
1199  newval = ub;
1200 
1201  /* tighten if really better */
1202  if( SCIPisLbBetter(scip, newval, lb, ub) )
1203  {
1204  SCIP_CALL( SCIPchgVarLbProbing(scip, bound->var, newval) );
1205  *tightened = TRUE;
1206  }
1207  }
1208  else
1209  {
1210  /* round bounds new value if variable is integral */
1211  if( SCIPvarIsIntegral(bound->var) )
1212  newval = SCIPfloor(scip, newval);
1213 
1214  /* ensure that we give consistent bounds to the LP solver */
1215  if( newval < lb )
1216  newval = lb;
1217 
1218  /* tighten if really better */
1219  if( SCIPisUbBetter(scip, newval, lb, ub) )
1220  {
1221  SCIP_CALL( SCIPchgVarUbProbing(scip, bound->var, newval) );
1222  *tightened = TRUE;
1223  }
1224  }
1225 
1226  return SCIP_OKAY;
1227 }
1228 
1229 /** comparison method for two bounds w.r.t. their scores */
1230 static
1231 SCIP_DECL_SORTPTRCOMP(compBoundsScore)
1232 {
1233  BOUND* bound1 = (BOUND*) elem1;
1234  BOUND* bound2 = (BOUND*) elem2;
1235 
1236  return bound1->score == bound2->score ? 0 : ( bound1->score > bound2->score ? 1 : -1 );
1237 }
1238 
1239 /** comparison method for two bounds w.r.t. their boundtype */
1240 static
1241 SCIP_DECL_SORTPTRCOMP(compBoundsBoundtype)
1242 {
1243  int diff;
1244  BOUND* bound1 = (BOUND*) elem1;
1245  BOUND* bound2 = (BOUND*) elem2;
1246 
1247  /* prioritize undone bounds */
1248  diff = (!bound1->done ? 1 : 0) - (!bound2->done ? 1 : 0);
1249  if( diff != 0 )
1250  return diff;
1251 
1252  /* prioritize unfiltered bounds */
1253  diff = (!bound1->filtered ? 1 : 0) - (!bound2->filtered ? 1 : 0);
1254  if( diff != 0 )
1255  return diff;
1256 
1257  diff = (bound1->boundtype == SCIP_BOUNDTYPE_LOWER ? 1 : 0) - (bound2->boundtype == SCIP_BOUNDTYPE_LOWER ? 1 : 0);
1258 
1259  if( diff == 0 )
1260  return (bound1->score == bound2->score) ? 0 : (bound1->score > bound2->score ? 1 : -1);
1261  else
1262  return diff;
1263 }
1264 
1265 /** sort the propdata->bounds array with their distance or their boundtype key */
1266 static
1268  SCIP* scip, /**< SCIP data structure */
1269  SCIP_PROPDATA* propdata /**< propagator data */
1270  )
1271 {
1272  assert(scip != NULL);
1273  assert(propdata != NULL);
1274 
1275  SCIPdebugMessage("sort bounds\n");
1276  SCIPsortDownPtr((void**) propdata->bounds, compBoundsBoundtype, propdata->nbounds);
1277 
1278  return SCIP_OKAY;
1280 
1281 /** evaluates a bound for the current LP solution */
1282 static
1284  SCIP* scip,
1285  BOUND* bound
1286  )
1287 {
1288  assert(scip != NULL);
1289  assert(bound != NULL);
1290 
1291  if( bound->boundtype == SCIP_BOUNDTYPE_LOWER )
1292  return REALABS( SCIPvarGetLPSol(bound->var) - SCIPvarGetLbLocal(bound->var) );
1293  else
1294  return REALABS( SCIPvarGetUbLocal(bound->var) - SCIPvarGetLPSol(bound->var) );
1296 
1297 /** returns the index of the next undone and unfiltered bound with the smallest distance */
1298 static
1299 int nextBound(
1300  SCIP* scip, /**< SCIP data structure */
1301  SCIP_PROPDATA* propdata, /**< data of the obbt propagator */
1302  SCIP_Bool convexphase /**< consider only convex variables? */
1303  )
1304 {
1305  SCIP_Real bestval;
1306  int bestidx;
1307  int k;
1308 
1309  assert(scip != NULL);
1310  assert(propdata != NULL);
1312  bestidx = -1;
1313  bestval = SCIPinfinity(scip);
1314 
1315  for( k = 0; k <= propdata->lastidx; ++k )
1316  {
1317  BOUND* tmpbound;
1318  tmpbound = propdata->bounds[k];
1319 
1320  assert(tmpbound != NULL);
1321 
1322  if( !tmpbound->filtered && !tmpbound->done && (tmpbound->nonconvex == !convexphase) )
1323  {
1324  SCIP_Real boundval;
1325 
1326  /* return the next bound which is not done or unfiltered yet */
1327  if( propdata->orderingalgo == 0 )
1328  return k;
1329 
1330  boundval = evalBound(scip, tmpbound);
1331 
1332  /* negate boundval if we use the reverse greedy algorithm */
1333  boundval = (propdata->orderingalgo == 2) ? -1.0 * boundval : boundval;
1334 
1335  if( bestidx == -1 || boundval < bestval )
1336  {
1337  bestidx = k;
1338  bestval = boundval;
1339  }
1340  }
1341  }
1342 
1343  return bestidx;
1344 }
1345 
1346 /** try to separate the solution of the last OBBT LP in order to learn better variable bounds; we apply additional
1347  * separation rounds as long as the routine finds better bounds; because of dual degeneracy we apply a minimum number of
1348  * separation rounds
1349  */
1350 static
1352  SCIP* scip, /**< SCIP data structure */
1353  SCIP_PROPDATA* propdata, /**< data of the obbt propagator */
1354  BOUND* currbound, /**< current bound */
1355  SCIP_Longint* nleftiterations, /**< number of left iterations (-1 for no limit) */
1356  SCIP_Bool* success /**< pointer to store if we have found a better bound */
1357  )
1358 {
1359  SCIP_Bool inroot;
1360  int i;
1361 
1362  assert(nleftiterations != NULL);
1363  assert(success != NULL);
1364  assert(SCIPinProbing(scip));
1365 
1366  *success = FALSE;
1367 
1368  /* check if we are originally in the root node */
1369  inroot = SCIPgetDepth(scip) == 1;
1370 
1371  for( i = 0; i <= propdata->sepamaxiter; ++i )
1372  {
1373  SCIP_Longint nlpiter;
1374  SCIP_Real oldval;
1375  SCIP_Bool cutoff;
1376  SCIP_Bool delayed;
1377  SCIP_Bool error;
1378  SCIP_Bool optimal;
1379  SCIP_Bool tightened;
1380 
1381  oldval = SCIPvarGetLPSol(currbound->var);
1382 
1383  /* find and store cuts to separate the current LP solution */
1384  SCIP_CALL( SCIPseparateSol(scip, NULL, inroot, FALSE, &delayed, &cutoff) );
1385  SCIPdebugMessage("applySeparation() - ncuts = %d\n", SCIPgetNCuts(scip));
1386 
1387  /* leave if we did not found any cut */
1388  if( SCIPgetNCuts(scip) == 0 )
1389  break;
1390 
1391  /* apply cuts and resolve LP */
1392  SCIP_CALL( SCIPapplyCutsProbing(scip, &cutoff) );
1393  assert(SCIPgetNCuts(scip) == 0);
1394  nlpiter = SCIPgetNLPIterations(scip);
1395  SCIP_CALL( solveLP(scip, (int) *nleftiterations, &error, &optimal) );
1396  nlpiter = SCIPgetNLPIterations(scip) - nlpiter;
1397  SCIPdebugMessage("applySeparation() - optimal=%u error=%u lpiter=%" SCIP_LONGINT_FORMAT "\n", optimal, error, nlpiter);
1398  SCIPdebugMessage("oldval = %e newval = %e\n", oldval, SCIPvarGetLPSol(currbound->var));
1399 
1400  /* leave if we did not solve the LP to optimality or an error occured */
1401  if( error || !optimal )
1402  break;
1403 
1404  /* try to generate a genvbound */
1405  if( inroot && propdata->genvboundprop != NULL && propdata->genvbdsduringsepa )
1406  {
1407  SCIP_Bool found;
1408  SCIP_CALL( createGenVBound(scip, propdata, currbound, &found) );
1409  propdata->ngenvboundsprobing += found ? 1 : 0;
1410  }
1411 
1412  /* try to tight the variable bound */
1413  tightened = FALSE;
1414  if( !SCIPisEQ(scip, oldval, SCIPvarGetLPSol(currbound->var)) )
1415  {
1416  SCIP_CALL( tightenBoundProbing(scip, currbound, SCIPvarGetLPSol(currbound->var), &tightened) );
1417  SCIPdebugMessage("apply separation - tightened=%u oldval=%e newval=%e\n", tightened, oldval,
1418  SCIPvarGetLPSol(currbound->var));
1419 
1420  *success |= tightened;
1421  }
1422 
1423  /* leave the separation if we did not tighten the bound and proceed at least propdata->sepaminiter iterations */
1424  if( !tightened && i >= propdata->sepaminiter )
1425  break;
1426  }
1427 
1428  return SCIP_OKAY;
1429 }
1430 
1431 /** finds new variable bounds until no iterations left or all bounds have been checked */
1432 static
1434  SCIP* scip, /**< SCIP data structure */
1435  SCIP_PROPDATA* propdata, /**< data of the obbt propagator */
1436  SCIP_Longint* nleftiterations, /**< pointer to store the number of left iterations */
1437  SCIP_Bool convexphase /**< consider only convex variables? */
1438  )
1439 {
1440  SCIP_Longint nolditerations;
1441  SCIP_Bool iterationsleft;
1442  BOUND* currbound;
1443  SCIP_Longint itlimit;
1444  int nextboundidx;
1446  assert(scip != NULL);
1447  assert(propdata != NULL);
1448  assert(nleftiterations != NULL);
1449 
1450  /* update the number of left iterations */
1451  nolditerations = SCIPgetNLPIterations(scip);
1452  itlimit = *nleftiterations;
1453  assert(*nleftiterations == getIterationsLeft(scip, nolditerations, itlimit));
1454  iterationsleft = (*nleftiterations == -1) || (*nleftiterations > 0);
1455 
1456  /* To improve the performance we sort the bound in such a way that the undone and
1457  * unfiltered bounds are at the end of propdata->bounds. We calculate and update
1458  * the position of the last unfiltered and undone bound in propdata->lastidx
1459  */
1460  if( !convexphase )
1461  {
1462  /* sort bounds */
1463  SCIP_CALL( sortBounds(scip, propdata) );
1464 
1465  /* if the first bound is filtered or done then there is no bound left */
1466  if( propdata->bounds[0]->done || propdata->bounds[0]->filtered )
1467  {
1468  SCIPdebugMessage("no unprocessed/unfiltered bound left\n");
1469  return SCIP_OKAY;
1470  }
1471 
1472  /* compute the last undone and unfiltered node */
1473  propdata->lastidx = 0;
1474  while( propdata->lastidx < propdata->nbounds - 1 && !propdata->bounds[propdata->lastidx]->done &&
1475  !propdata->bounds[propdata->lastidx]->filtered )
1476  ++propdata->lastidx;
1477 
1478  SCIPdebugMessage("lastidx = %d\n", propdata->lastidx);
1479  }
1480 
1481  /* find the first unprocessed bound */
1482  nextboundidx = nextBound(scip, propdata, convexphase);
1483 
1484  /* skip if there is no bound left */
1485  if( nextboundidx == -1 )
1486  {
1487  SCIPdebugMessage("no unprocessed/unfiltered bound left\n");
1488  return SCIP_OKAY;
1489  }
1490 
1491  currbound = propdata->bounds[nextboundidx];
1492  assert(!currbound->done && !currbound->filtered);
1493 
1494  /* main loop */
1495  while( iterationsleft && !SCIPisStopped(scip) )
1496  {
1497  SCIP_Bool optimal;
1498  SCIP_Bool error;
1499  int nfiltered;
1500 
1501  assert(currbound != NULL);
1502  assert(currbound->done == FALSE);
1503  assert(currbound->filtered == FALSE);
1504 
1505  /* do not visit currbound more than once */
1506  currbound->done = TRUE;
1507  exchangeBounds(propdata, nextboundidx);
1508 
1509  /* set objective for curr */
1510  SCIP_CALL( setObjProbing(scip, propdata, currbound, 1.0) );
1511 
1512  SCIPdebugMessage("before solving Boundtype: %d , LB: %e , UB: %e\n",
1513  currbound->boundtype == SCIP_BOUNDTYPE_LOWER, SCIPvarGetLbLocal(currbound->var),
1514  SCIPvarGetUbLocal(currbound->var) );
1515  SCIPdebugMessage("before solving var <%s>, LP value: %f\n",
1516  SCIPvarGetName(currbound->var), SCIPvarGetLPSol(currbound->var));
1517 
1518  SCIPdebugMessage("probing iterations before solve: %lld \n", SCIPgetNLPIterations(scip));
1519 
1520  propdata->nprobingiterations -= SCIPgetNLPIterations(scip);
1521 
1522  /* now solve the LP */
1523  SCIP_CALL( solveLP(scip, (int) *nleftiterations, &error, &optimal) );
1524 
1525  propdata->nprobingiterations += SCIPgetNLPIterations(scip);
1526  propdata->nsolvedbounds++;
1527 
1528  SCIPdebugMessage("probing iterations after solve: %lld \n", SCIPgetNLPIterations(scip));
1529  SCIPdebugMessage("OPT: %u ERROR: %u\n" , optimal, error);
1530  SCIPdebugMessage("after solving Boundtype: %d , LB: %e , UB: %e\n",
1531  currbound->boundtype == SCIP_BOUNDTYPE_LOWER, SCIPvarGetLbLocal(currbound->var),
1532  SCIPvarGetUbLocal(currbound->var) );
1533  SCIPdebugMessage("after solving var <%s>, LP value: %f\n",
1534  SCIPvarGetName(currbound->var), SCIPvarGetLPSol(currbound->var));
1535 
1536  /* update nleftiterations */
1537  *nleftiterations = getIterationsLeft(scip, nolditerations, itlimit);
1538  iterationsleft = (*nleftiterations == -1) || (*nleftiterations > 0);
1539 
1540  if( error )
1541  {
1542  SCIPdebugMessage("ERROR during LP solving\n");
1543 
1544  /* set the objective of currbound to zero to null the whole objective; otherwise the objective is wrong when
1545  * we call findNewBounds() for the convex phase
1546  */
1547  SCIP_CALL( SCIPchgVarObjProbing(scip, currbound->var, 0.0) );
1548 
1549  return SCIP_OKAY;
1550  }
1551 
1552  if( optimal )
1553  {
1554  SCIP_Bool success;
1555 
1556  currbound->newval = SCIPvarGetLPSol(currbound->var);
1557  currbound->found = TRUE;
1558 
1559  /* in root node we may want to create a genvbound (independent of tightening success) */
1560  if( (SCIPgetDepth(scip) == 0 || (SCIPinProbing(scip) && SCIPgetDepth(scip) == 1))
1561  && propdata->genvboundprop != NULL )
1562  {
1563  SCIP_Bool found;
1564 
1565  SCIP_CALL( createGenVBound(scip, propdata, currbound, &found) );
1566 
1567  if( found )
1568  propdata->ngenvboundsprobing += 1;
1569  }
1570 
1571  /* try to tighten bound in probing mode */
1572  success = FALSE;
1573  if( propdata->tightintboundsprobing && SCIPvarIsIntegral(currbound->var) )
1574  {
1575  SCIPdebugMessage("tightening bound %s = %e bounds: [%e, %e]\n", SCIPvarGetName(currbound->var),
1576  currbound->newval, SCIPvarGetLbLocal(currbound->var), SCIPvarGetUbLocal(currbound->var) );
1577  SCIP_CALL( tightenBoundProbing(scip, currbound, currbound->newval, &success) );
1578  SCIPdebugMessage("tightening bound %s\n", success ? "successful" : "not successful");
1579  }
1580  else if( propdata->tightcontboundsprobing && !SCIPvarIsIntegral(currbound->var) )
1581  {
1582  SCIPdebugMessage("tightening bound %s = %e bounds: [%e, %e]\n", SCIPvarGetName(currbound->var),
1583  currbound->newval, SCIPvarGetLbLocal(currbound->var), SCIPvarGetUbLocal(currbound->var) );
1584  SCIP_CALL( tightenBoundProbing(scip, currbound, currbound->newval, &success) );
1585  SCIPdebugMessage("tightening bound %s\n", success ? "successful" : "not successful");
1586  }
1587 
1588  /* separate current OBBT LP solution */
1589  if( iterationsleft && propdata->separatesol )
1590  {
1591  propdata->nprobingiterations -= SCIPgetNLPIterations(scip);
1592  SCIP_CALL( applySeparation(scip, propdata, currbound, nleftiterations, &success) );
1593  propdata->nprobingiterations += SCIPgetNLPIterations(scip);
1594 
1595  /* remember best solution value after solving additional separations LPs */
1596  if( success )
1597  {
1598 #ifndef NDEBUG
1599  SCIP_Real newval = SCIPvarGetLPSol(currbound->var);
1600 
1601  /* round new bound if the variable is integral */
1602  if( SCIPvarIsIntegral(currbound->var) )
1603  newval = currbound->boundtype == SCIP_BOUNDTYPE_LOWER ?
1604  SCIPceil(scip, newval) : SCIPfloor(scip, newval);
1605 
1606  assert((currbound->boundtype == SCIP_BOUNDTYPE_LOWER &&
1607  SCIPisGT(scip, newval, currbound->newval))
1608  || (currbound->boundtype == SCIP_BOUNDTYPE_UPPER &&
1609  SCIPisLT(scip, newval, currbound->newval)));
1610 #endif
1611 
1612  currbound->newval = SCIPvarGetLPSol(currbound->var);
1613  }
1614  }
1615 
1616  /* filter bound candidates by using the current LP solution */
1617  if( propdata->applytrivialfilter )
1618  {
1619  SCIP_CALL( filterExistingLP(scip, propdata, &nfiltered, currbound) );
1620  SCIPdebugMessage("filtered %d bounds via inspecting present LP solution\n", nfiltered);
1621  propdata->ntrivialfiltered += nfiltered;
1622  }
1623 
1624  propdata->propagatecounter += success ? 1 : 0;
1625 
1626  /* propagate if we have found enough bound tightenings */
1627  if( propdata->propagatefreq != 0 && propdata->propagatecounter >= propdata->propagatefreq )
1628  {
1629  SCIP_Longint ndomredsfound;
1630  SCIP_Bool cutoff;
1631 
1632  SCIP_CALL( SCIPpropagateProbing(scip, 0, &cutoff, &ndomredsfound) );
1633  SCIPdebugMessage("propagation - cutoff %u ndomreds %" SCIP_LONGINT_FORMAT "\n", cutoff, ndomredsfound);
1634 
1635  propdata->npropagatedomreds += ndomredsfound;
1636  propdata->propagatecounter = 0;
1637  }
1638  }
1639 
1640  /* set objective to zero */
1641  SCIP_CALL( setObjProbing(scip, propdata, currbound, 0.0) );
1642 
1643  /* find the first unprocessed bound */
1644  nextboundidx = nextBound(scip, propdata, convexphase);
1645 
1646  /* check if there is no unprocessed and unfiltered node left */
1647  if( nextboundidx == -1 )
1648  {
1649  SCIPdebugMessage("NO unvisited/unfiltered bound left!\n");
1650  break;
1651  }
1652 
1653  currbound = propdata->bounds[nextboundidx];
1654  assert(!currbound->done && !currbound->filtered);
1655  }
1656 
1657  if( iterationsleft )
1658  {
1659  SCIPdebugMessage("still iterations left: %" SCIP_LONGINT_FORMAT "\n", *nleftiterations);
1660  }
1661  else
1662  {
1663  SCIPdebugMessage("no iterations left\n");
1664  }
1665 
1666  return SCIP_OKAY;
1667 }
1668 
1669 
1670 /** main function of obbt */
1671 static
1673  SCIP* scip, /**< SCIP data structure */
1674  SCIP_PROPDATA* propdata, /**< data of the obbt propagator */
1675  SCIP_Longint itlimit, /**< LP iteration limit (-1: no limit) */
1676  SCIP_RESULT* result /**< result pointer */
1677  )
1678 {
1679  SCIP_VAR** vars;
1680  SCIP_Real* oldlbs;
1681  SCIP_Real* oldubs;
1682  SCIP_Longint lastnpropagatedomreds;
1683  SCIP_Longint nleftiterations;
1684  SCIP_Real oldconditionlimit;
1685  SCIP_Real oldboundstreps;
1686  SCIP_Real olddualfeastol;
1687  SCIP_Bool hasconditionlimit;
1688  SCIP_Bool continuenode;
1689  SCIP_Bool boundleft;
1690  int nfiltered;
1691  int nvars;
1692  int i;
1693 
1694  assert(scip != NULL);
1695  assert(propdata != NULL);
1696  assert(itlimit == -1 || itlimit >= 0);
1697 
1698  SCIPdebugMessage("apply obbt\n");
1699 
1700  oldlbs = NULL;
1701  oldubs = NULL;
1702  lastnpropagatedomreds = propdata->npropagatedomreds;
1703  nleftiterations = itlimit;
1704  continuenode = SCIPnodeGetNumber(SCIPgetCurrentNode(scip)) == propdata->lastnode;
1705  propdata->lastidx = -1;
1706  boundleft = FALSE;
1707  *result = SCIP_DIDNOTFIND;
1708 
1709  /* store old variable bounds if we use propagation during obbt */
1710  if( propdata->propagatefreq > 0 )
1711  {
1712  SCIP_CALL( SCIPallocBufferArray(scip, &oldlbs, propdata->nbounds) );
1713  SCIP_CALL( SCIPallocBufferArray(scip, &oldubs, propdata->nbounds) );
1714  }
1715 
1716  /* reset bound data structure flags; fixed variables are marked as filtered */
1717  for( i = 0; i < propdata->nbounds; i++ )
1718  {
1719  BOUND* bound = propdata->bounds[i];
1720  bound->found = FALSE;
1721 
1722  /* store old variable bounds */
1723  if( oldlbs != NULL && oldubs != NULL )
1724  {
1725  oldlbs[bound->index] = SCIPvarGetLbLocal(bound->var);
1726  oldubs[bound->index] = SCIPvarGetUbLocal(bound->var);
1727  }
1728 
1729  /* reset 'done' and 'filtered' flag in a new B&B node */
1730  if( !continuenode )
1731  {
1732  bound->done = FALSE;
1733  bound->filtered = FALSE;
1734  }
1735 
1736  /* mark fixed variables as filtered */
1737  bound->filtered |= varIsFixedLocal(scip, bound->var);
1738 
1739  /* check for an unprocessed bound */
1740  if( !bound->filtered && !bound->done )
1741  boundleft = TRUE;
1742  }
1743 
1744  /* no bound left to check */
1745  if( !boundleft )
1746  goto TERMINATE;
1747 
1748  /* filter variables via inspecting present LP solution */
1749  if( propdata->applytrivialfilter && !continuenode )
1750  {
1751  SCIP_CALL( filterExistingLP(scip, propdata, &nfiltered, NULL) );
1752  SCIPdebugMessage("filtered %d bounds via inspecting present LP solution\n", nfiltered);
1753  propdata->ntrivialfiltered += nfiltered;
1754  }
1755 
1756  /* store old dualfeasibletol */
1757  olddualfeastol = SCIPdualfeastol(scip);
1758 
1759  /* start probing */
1760  SCIP_CALL( SCIPstartProbing(scip) );
1761  SCIPdebugMessage("start probing\n");
1762 
1763  /* tighten dual feastol */
1764  if( propdata->dualfeastol < olddualfeastol )
1765  {
1766  SCIP_CALL( SCIPchgDualfeastol(scip, propdata->dualfeastol) );
1767  }
1768 
1769  /* tighten condition limit */
1770  hasconditionlimit = (SCIPgetRealParam(scip, "lp/conditionlimit", &oldconditionlimit) == SCIP_OKAY);
1771  if( !hasconditionlimit )
1772  {
1773  SCIPwarningMessage(scip, "obbt propagator could not set condition limit in LP solver - running without\n");
1774  }
1775  else if( propdata->conditionlimit > 0.0 && (oldconditionlimit < 0.0 || propdata->conditionlimit < oldconditionlimit) )
1776  {
1777  SCIP_CALL( SCIPsetRealParam(scip, "lp/conditionlimit", propdata->conditionlimit) );
1778  }
1779 
1780  /* tighten relative bound improvement limit */
1781  SCIP_CALL( SCIPgetRealParam(scip, "numerics/boundstreps", &oldboundstreps) );
1782  if( !SCIPisEQ(scip, oldboundstreps, propdata->boundstreps) )
1783  {
1784  SCIP_CALL( SCIPsetRealParam(scip, "numerics/boundstreps", propdata->boundstreps) );
1785  }
1786 
1787  /* add objective cutoff */
1788  SCIP_CALL( addObjCutoff(scip, propdata) );
1789 
1790  /* apply filtering */
1791  if( propdata->applyfilterrounds )
1792  {
1793  SCIP_CALL( filterBounds(scip, propdata, nleftiterations) );
1794  }
1795 
1796  /* set objective coefficients to zero */
1797  vars = SCIPgetVars(scip);
1798  nvars = SCIPgetNVars(scip);
1799  for( i = 0; i < nvars; ++i )
1800  {
1801  /* note that it is not possible to change the objective of non-column variables during probing; we have to take
1802  * care of the objective contribution of loose variables in createGenVBound()
1803  */
1804  if( SCIPvarGetObj(vars[i]) != 0.0 && SCIPvarGetStatus(vars[i]) == SCIP_VARSTATUS_COLUMN )
1805  {
1806  SCIP_CALL( SCIPchgVarObjProbing(scip, vars[i], 0.0) );
1807  }
1808  }
1809 
1810  /* find new bounds for the variables */
1811  SCIP_CALL( findNewBounds(scip, propdata, &nleftiterations, FALSE) );
1812 
1813  if( nleftiterations > 0 || itlimit < 0 )
1814  {
1815  SCIP_CALL( findNewBounds(scip, propdata, &nleftiterations, TRUE) );
1816  }
1817 
1818  /* reset dual feastol and condition limit */
1819  SCIP_CALL( SCIPchgDualfeastol(scip, olddualfeastol) );
1820  if( hasconditionlimit )
1821  {
1822  SCIP_CALL( SCIPsetRealParam(scip, "lp/conditionlimit", oldconditionlimit) );
1823  }
1824 
1825  /* update bound->newval if we have learned additional bound tightenings during SCIPpropagateProbing() */
1826  if( oldlbs != NULL && oldubs != NULL && propdata->npropagatedomreds - lastnpropagatedomreds > 0 )
1827  {
1828  assert(propdata->propagatefreq > 0);
1829  for( i = 0; i < propdata->nbounds; ++i )
1830  {
1831  BOUND* bound = propdata->bounds[i];
1832 
1833  /* it might be the case that a bound found by the additional propagation is better than the bound found after solving an OBBT
1834  * LP
1835  */
1836  if( bound->found )
1837  {
1838  if( bound->boundtype == SCIP_BOUNDTYPE_LOWER )
1839  bound->newval = MAX(bound->newval, SCIPvarGetLbLocal(bound->var)); /*lint !e666*/
1840  else
1841  bound->newval = MIN(bound->newval, SCIPvarGetUbLocal(bound->var)); /*lint !e666*/
1842  }
1843  else
1844  {
1845  SCIP_Real oldlb;
1846  SCIP_Real oldub;
1847 
1848  oldlb = oldlbs[bound->index];
1849  oldub = oldubs[bound->index];
1850 
1851  if( bound->boundtype == SCIP_BOUNDTYPE_LOWER && SCIPisLbBetter(scip, SCIPvarGetLbLocal(bound->var), oldlb, oldub) )
1852  {
1853  SCIPdebugMessage("tighter lower bound due to propagation: %d - %e -> %e\n", i, oldlb, SCIPvarGetLbLocal(bound->var));
1854  bound->newval = SCIPvarGetLbLocal(bound->var);
1855  bound->found = TRUE;
1856  }
1857 
1858  if( bound->boundtype == SCIP_BOUNDTYPE_UPPER && SCIPisUbBetter(scip, SCIPvarGetUbLocal(bound->var), oldlb, oldub) )
1859  {
1860  SCIPdebugMessage("tighter upper bound due to propagation: %d - %e -> %e\n", i, oldub, SCIPvarGetUbLocal(bound->var));
1861  bound->newval = SCIPvarGetUbLocal(bound->var);
1862  bound->found = TRUE;
1863  }
1864  }
1865  }
1866  }
1867 
1868  /* reset relative bound improvement limit */
1869  SCIP_CALL( SCIPsetRealParam(scip, "numerics/boundstreps", oldboundstreps) );
1870 
1871  /* end probing */
1872  SCIP_CALL( SCIPendProbing(scip) );
1873  SCIPdebugMessage("end probing!\n");
1874 
1875  /* release cutoff row if there is one */
1876  if( propdata->cutoffrow != NULL )
1877  {
1878  assert(!SCIProwIsInLP(propdata->cutoffrow));
1879  SCIP_CALL( SCIPreleaseRow(scip, &(propdata->cutoffrow)) );
1880  }
1881 
1882  /* apply buffered bound changes */
1883  SCIP_CALL( applyBoundChgs(scip, propdata, result) );
1884 
1885 TERMINATE:
1886  SCIPfreeBufferArrayNull(scip, &oldubs);
1887  SCIPfreeBufferArrayNull(scip, &oldlbs);
1888 
1889  return SCIP_OKAY;
1890 }
1891 
1892 /** computes the score of a bound */
1893 static
1894 unsigned int getScore(
1895  SCIP* scip, /**< SCIP data structure */
1896  BOUND* bound, /**< pointer of bound */
1897  int nlcount, /**< number of nonlinear constraints containing the bounds variable */
1898  int maxnlcount /**< maximal number of nonlinear constraints a variable appears in */
1899  )
1900 {
1901  unsigned int score; /* score to be computed */
1902 
1903  assert(scip != NULL);
1904  assert(bound != NULL);
1905  assert(nlcount >= 0);
1906  assert(maxnlcount >= nlcount);
1907 
1908  /* score = ( nlcount * ( BASE - 1 ) / maxnlcount ) * BASE^2 + vartype * BASE + boundtype */
1909  score = (unsigned int) ( nlcount > 0 ? (OBBT_SCOREBASE * nlcount * ( OBBT_SCOREBASE - 1 )) / maxnlcount : 0 );
1910  switch( SCIPvarGetType(bound->var) )
1911  {
1912  case SCIP_VARTYPE_INTEGER:
1913  score += 1;
1914  break;
1915  case SCIP_VARTYPE_IMPLINT:
1916  score += 2;
1917  break;
1919  score += 3;
1920  break;
1921  case SCIP_VARTYPE_BINARY:
1922  score += 4;
1923  break;
1924  default:
1925  break;
1926  }
1927 
1928  score *= OBBT_SCOREBASE;
1929  if( bound->boundtype == SCIP_BOUNDTYPE_UPPER )
1930  score += 1;
1931 
1932  return score;
1933 }
1934 
1935 /** count the variables which appear in non-convex term of nlrow */
1936 static
1938  SCIP* scip, /**< SCIP data structure */
1939  int* nlcounts, /**< store the number each variable appears in a
1940  * non-convex term */
1941  SCIP_NLROW* nlrow /**< nonlinear row */
1942  )
1943 {
1944  int t;
1945  int nexprtreevars;
1946  SCIP_VAR** exprtreevars;
1947  SCIP_EXPRTREE* exprtree;
1948 
1949  assert(scip != NULL);
1950  assert(nlcounts != NULL);
1951  assert(nlrow != NULL);
1952 
1953  /* go through all quadratic terms */
1954  for( t = SCIPnlrowGetNQuadElems(nlrow) - 1; t >= 0; --t )
1955  {
1956  SCIP_QUADELEM* quadelem;
1957  SCIP_VAR* bilinvar1;
1958  SCIP_VAR* bilinvar2;
1959 
1960  /* get quadratic term */
1961  quadelem = &SCIPnlrowGetQuadElems(nlrow)[t];
1962 
1963  /* get involved variables */
1964  bilinvar1 = SCIPnlrowGetQuadVars(nlrow)[quadelem->idx1];
1965  bilinvar2 = SCIPnlrowGetQuadVars(nlrow)[quadelem->idx2];
1966 
1967  assert(bilinvar1 != NULL);
1968  assert(bilinvar2 != NULL);
1969 
1970  /* we have a non-convex square term */
1971  if( bilinvar1 == bilinvar2 && !(quadelem->coef >= 0 ? SCIPisInfinity(scip, -SCIPnlrowGetLhs(nlrow)) : SCIPisInfinity(scip, SCIPnlrowGetRhs(nlrow))) )
1972  {
1973  ++nlcounts[SCIPvarGetProbindex(bilinvar1)];
1974  ++nlcounts[SCIPvarGetProbindex(bilinvar2)];
1975  }
1976 
1977  /* bilinear terms are in general non-convex */
1978  if( bilinvar1 != bilinvar2 )
1979  {
1980  ++nlcounts[SCIPvarGetProbindex(bilinvar1)];
1981  ++nlcounts[SCIPvarGetProbindex(bilinvar2)];
1982  }
1983  }
1984 
1985  exprtree = SCIPnlrowGetExprtree(nlrow);
1986  if( exprtree != NULL )
1987  {
1988  nexprtreevars = SCIPexprtreeGetNVars(exprtree);
1989  exprtreevars = SCIPexprtreeGetVars(exprtree);
1990 
1991  /* assume that the expression tree represents a non-convex constraint */
1992  for( t = 0; t < nexprtreevars; ++t)
1993  {
1994  SCIP_VAR* var;
1995  var = exprtreevars[t];
1996  assert(var != NULL);
1997 
1998  ++nlcounts[SCIPvarGetProbindex(var)];
1999  }
2000  }
2001 
2002  return SCIP_OKAY;
2003 }
2004 
2005 /** count how often each variable appears in a non-convex term */
2006 static
2008  SCIP* scip, /**< SCIP data structure */
2009  int* nlcounts /**< store the number each variable appears in a
2010  * non-convex term */
2011  )
2012 {
2013  SCIP_CONSHDLR* conshdlr;
2014  SCIP_CONS** conss;
2015  int nvars;
2016  int nconss;
2017  int i;
2018 
2019  assert(scip != NULL);
2020  assert(nlcounts != NULL);
2021 
2022  nvars = SCIPgetNVars(scip);
2023  BMSclearMemoryArray(nlcounts, nvars);
2024 
2025  /* quadratic constraint handler */
2026  conshdlr = SCIPfindConshdlr(scip, "quadratic");
2027  if( conshdlr != NULL )
2028  {
2029 
2030  /*SCIPdebugMessage("cons_quadratic is there!\n");*/
2031  nconss = SCIPconshdlrGetNActiveConss(conshdlr);
2032  conss = SCIPconshdlrGetConss(conshdlr);
2033 
2034  SCIPdebugMessage("nconss(quadratic) = %d\n", nconss);
2035 
2036  for( i = 0; i < nconss; ++i )
2037  {
2038  /* only check the nlrow if the constraint is not convex */
2039  if( SCIPisConvexQuadratic(scip, conss[i]) == FALSE )
2040  {
2041  SCIP_NLROW* nlrow;
2042  SCIP_CALL( SCIPgetNlRowQuadratic(scip, conss[i], &nlrow) );
2043  assert(nlrow != NULL);
2044 
2045  SCIP_CALL( countNLRowVarsNonConvexity(scip, nlcounts, nlrow) );
2046  }
2047  }
2048  }
2049 
2050  /* nonlinear constraint handler */
2051  conshdlr = SCIPfindConshdlr(scip, "nonlinear");
2052  if( conshdlr != NULL )
2053  {
2054  nconss = SCIPconshdlrGetNActiveConss(conshdlr);
2055  conss = SCIPconshdlrGetConss(conshdlr);
2056 
2057  SCIPdebugMessage("nconss(nonlinear) = %d\n", nconss);
2058 
2059  for( i = 0; i < nconss; ++i )
2060  {
2061  SCIP_EXPRCURV curvature;
2062  SCIP_CALL( SCIPgetCurvatureNonlinear(scip, conss[i], TRUE, &curvature) );
2063 
2064  /* only check the nlrow if the constraint is not convex */
2065  if( curvature != SCIP_EXPRCURV_CONVEX )
2066  {
2067  SCIP_NLROW* nlrow;
2068  SCIP_CALL( SCIPgetNlRowNonlinear(scip, conss[i], &nlrow) );
2069  assert(nlrow != NULL);
2070 
2071  SCIP_CALL( countNLRowVarsNonConvexity(scip, nlcounts, nlrow) );
2072  }
2073  }
2074  }
2075 
2076  /* bivariate constraint handler */
2077  conshdlr = SCIPfindConshdlr(scip, "bivariate");
2078  if( conshdlr != NULL )
2079  {
2080  nconss = SCIPconshdlrGetNActiveConss(conshdlr);
2081  conss = SCIPconshdlrGetConss(conshdlr);
2082 
2083  SCIPdebugMessage("nconss(bivariate) = %d\n", nconss);
2084 
2085  for( i = 0; i < nconss; ++i )
2086  {
2087  SCIP_EXPRCURV curvature;
2088  SCIP_INTERVAL* varbounds;
2089  SCIP_EXPRTREE* exprtree;
2090  int j;
2091 
2092  exprtree = SCIPgetExprtreeBivariate(scip, conss[i]);
2093  if( exprtree != NULL )
2094  {
2095  SCIP_CALL( SCIPallocBufferArray(scip, &varbounds, SCIPexprtreeGetNVars(exprtree)) );
2096  for( j = 0; j < SCIPexprtreeGetNVars(exprtree); ++j )
2097  {
2098  SCIP_VAR* var;
2099  var = SCIPexprtreeGetVars(exprtree)[j];
2100 
2101  SCIPintervalSetBounds(&varbounds[j],
2102  -infty2infty(SCIPinfinity(scip), INTERVALINFTY, -MIN(SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var))), /*lint !e666*/
2103  +infty2infty(SCIPinfinity(scip), INTERVALINFTY, MAX(SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var))) ); /*lint !e666*/
2104  }
2105 
2106  SCIP_CALL( SCIPexprtreeCheckCurvature(exprtree, SCIPinfinity(scip), varbounds, &curvature, NULL) );
2107 
2108  /* increase counter for all variables in the expression tree if the constraint is non-convex */
2109  if( curvature != SCIP_EXPRCURV_CONVEX )
2110  {
2111  for( j = 0; j < SCIPexprtreeGetNVars(exprtree); ++j )
2112  {
2113  SCIP_VAR* var;
2114  var = SCIPexprtreeGetVars(exprtree)[j];
2115 
2116  ++nlcounts[SCIPvarGetProbindex(var)];
2117  }
2118  }
2119  }
2120  }
2121  }
2122 
2123  /* abspower constraint handler */
2124  conshdlr = SCIPfindConshdlr(scip, "abspower");
2125  if( conshdlr != NULL )
2126  {
2127  nconss = SCIPconshdlrGetNActiveConss(conshdlr);
2128  conss = SCIPconshdlrGetConss(conshdlr);
2129 
2130  SCIPdebugMessage("nconss(abspower) = %d\n", nconss);
2131 
2132  for( i = 0; i < nconss; ++i )
2133  {
2134  /* constraint is non-convex in general */
2135  SCIP_NLROW* nlrow;
2136  SCIP_CALL( SCIPgetNlRowAbspower(scip, conss[i], &nlrow) );
2137  assert(nlrow != NULL);
2138 
2139  SCIP_CALL( countNLRowVarsNonConvexity(scip, nlcounts, nlrow) );
2140  }
2141  }
2142 
2143  return SCIP_OKAY;
2144 }
2145 
2146 
2147 /** determines whether a variable is interesting */
2148 static
2150  SCIP* scip, /**< SCIP data structure */
2151  SCIP_VAR* var, /**< variable to check */
2152  int nlcount /**< number of nonlinear constraints containing the variable
2153  * or number of non-convex terms containing the variable
2154  * (depends on propdata->onlynonconvexvars) */
2155  )
2156 {
2157  assert(SCIPgetDepth(scip) == 0);
2158 
2159  return !SCIPvarIsBinary(var) && SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN && nlcount > 0
2160  && !varIsFixedLocal(scip, var);
2162 
2163 /** initializes interesting bounds */
2164 static
2166  SCIP* scip, /**< SCIP data structure */
2167  SCIP_PROPDATA* propdata /**< data of the obbt propagator */
2168  )
2169 {
2170  SCIP_VAR** vars; /* array of the problems variables */
2171  int* nlcount; /* array that stores in how many nonlinearities each variable appears */
2172  int* nccount; /* array that stores in how many nonconvexities each variable appears */
2173 
2174  int bdidx; /* bound index inside propdata->bounds */
2175  int maxnlcount; /* maximal number of nonlinear constraints a variable appears in */
2176  int nvars; /* number of the problems variables */
2177  int i;
2178 
2179  assert(scip != NULL);
2180  assert(propdata != NULL);
2181  assert(SCIPisNLPConstructed(scip));
2182 
2183  SCIPdebugMessage("initialize bounds\n");
2184 
2185  /* get variable data */
2186  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
2187 
2188  /* count nonlinearities */
2189  assert(SCIPgetNNLPVars(scip) == nvars);
2190 
2191  SCIP_CALL( SCIPallocBufferArray(scip, &nlcount, nvars) );
2192  SCIP_CALL( SCIPallocBufferArray(scip, &nccount, nvars) );
2193 
2194  SCIP_CALL( SCIPgetNLPVarsNonlinearity(scip, nlcount) );
2195  SCIP_CALL( getNLPVarsNonConvexity(scip, nccount) );
2196 
2197  maxnlcount = 0;
2198  for( i = 0; i < nvars; i++ )
2199  {
2200  if( maxnlcount < nlcount[i] )
2201  maxnlcount = nlcount[i];
2202  }
2203 
2204  /* allocate interesting bounds array */
2205  SCIP_CALL( SCIPallocMemoryArray(scip, &(propdata->bounds), 2 * nvars) );
2206 
2207  /* get all interesting variables and their bounds */
2208  bdidx = 0;
2209  for( i = 0; i < nvars; i++ )
2210  {
2211  if( varIsInteresting(scip, vars[i], (propdata->onlynonconvexvars ? nccount[i] : nlcount[i])) )
2212  {
2213  BOUND** bdaddress;
2214 
2215  /* create lower bound */
2216  bdaddress = &(propdata->bounds[bdidx]);
2217  SCIP_CALL( SCIPallocMemory(scip, bdaddress) );
2218  propdata->bounds[bdidx]->boundtype = SCIP_BOUNDTYPE_LOWER;
2219  propdata->bounds[bdidx]->var = vars[i];
2220  propdata->bounds[bdidx]->found = FALSE;
2221  propdata->bounds[bdidx]->filtered = FALSE;
2222  propdata->bounds[bdidx]->newval = 0.0;
2223  propdata->bounds[bdidx]->score = getScore(scip, propdata->bounds[bdidx], nlcount[i], maxnlcount);
2224  propdata->bounds[bdidx]->done = FALSE;
2225  propdata->bounds[bdidx]->nonconvex = (nccount[i] > 0);
2226  propdata->bounds[bdidx]->index = bdidx;
2227  bdidx++;
2228 
2229  /* create upper bound */
2230  bdaddress = &(propdata->bounds[bdidx]);
2231  SCIP_CALL( SCIPallocMemory(scip, bdaddress) );
2232  propdata->bounds[bdidx]->boundtype = SCIP_BOUNDTYPE_UPPER;
2233  propdata->bounds[bdidx]->var = vars[i];
2234  propdata->bounds[bdidx]->found = FALSE;
2235  propdata->bounds[bdidx]->filtered = FALSE;
2236  propdata->bounds[bdidx]->newval = 0.0;
2237  propdata->bounds[bdidx]->score = getScore(scip, propdata->bounds[bdidx], nlcount[i], maxnlcount);
2238  propdata->bounds[bdidx]->done = FALSE;
2239  propdata->bounds[bdidx]->nonconvex = (nccount[i] > 0);
2240  propdata->bounds[bdidx]->index = bdidx;
2241  bdidx++;
2242  }
2243  }
2244 
2245  /* free memory for buffering nonlinearities */
2246  assert(nlcount != NULL);
2247  assert(nccount != NULL);
2248  SCIPfreeBufferArray(scip, &nlcount);
2249  SCIPfreeBufferArray(scip, &nccount);
2250 
2251  /* set number of interesting bounds */
2252  propdata->nbounds = bdidx;
2253 
2254  /* propdata->bounds array if empty */
2255  if( propdata->nbounds <= 0 )
2256  {
2257  assert(propdata->nbounds == 0);
2258  SCIPfreeMemoryArray(scip, &(propdata->bounds));
2259  }
2260 
2261  SCIPdebugMessage("problem has %d/%d interesting bounds\n", propdata->nbounds, 2 * nvars);
2262 
2263  if( propdata->nbounds > 0 )
2264  {
2265  /* sort bounds according to decreasing score; although this initial order will be overruled by the distance
2266  * criterion later, gives a more well-defined starting situation for OBBT and might help to reduce solver
2267  * variability
2268  */
2269  SCIPsortDownPtr((void**) propdata->bounds, compBoundsScore, propdata->nbounds);
2270  }
2271 
2272  return SCIP_OKAY;
2273 }
2274 
2275 
2276 /*
2277  * Callback methods of propagator
2278  */
2279 
2280 /** solving process initialization method of propagator (called when branch and bound process is about to begin) */
2281 static
2282 SCIP_DECL_PROPINITSOL(propInitsolObbt)
2283 { /*lint --e{715}*/
2284  SCIP_PROPDATA* propdata;
2285 
2286  assert(scip != NULL);
2287  assert(prop != NULL);
2288  assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
2289 
2290  /* get propagator data */
2291  propdata = SCIPpropGetData(prop);
2292  assert(propdata != NULL);
2293 
2294  propdata->bounds = NULL;
2295  propdata->nbounds = -1;
2296  propdata->cutoffrow = NULL;
2297  propdata->lastnode = -1;
2298 
2299 
2300  /* if genvbounds propagator is not available, we cannot create genvbounds */
2301  propdata->genvboundprop = propdata->creategenvbounds ? SCIPfindProp(scip, GENVBOUND_PROP_NAME) : NULL;
2302 
2303  SCIPdebugMessage("creating genvbounds: %s\n", propdata->genvboundprop != NULL ? "true" : "false");
2304 
2305  return SCIP_OKAY;
2306 }
2307 
2308 /** execution method of propagator */
2309 static
2310 SCIP_DECL_PROPEXEC(propExecObbt)
2311 { /*lint --e{715}*/
2312  SCIP_PROPDATA* propdata;
2313  SCIP_Longint itlimit;
2314 
2315  assert(scip != NULL);
2316  assert(prop != NULL);
2317  assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
2318 
2319  *result = SCIP_DIDNOTRUN;
2320 
2321  /* do not run in: presolving, repropagation, probing mode, if no objective propagation is allowed */
2323  return SCIP_OKAY;
2324 
2325  /* only run for nonlinear problems, i.e., if NLP is constructed */
2326  if( !SCIPisNLPConstructed(scip) )
2327  {
2328  SCIPdebugMessage("NLP not constructed, skipping obbt\n");
2329  return SCIP_OKAY;
2330  }
2331 
2332  /* only run if LP all columns are in the LP, i.e., the LP is a relaxation; e.g., do not run if pricers are active
2333  * since pricing is not performed in probing mode
2334  */
2335  if( !SCIPallColsInLP(scip) )
2336  {
2337  SCIPdebugMessage("not all columns in LP, skipping obbt\n");
2338  return SCIP_OKAY;
2339  }
2340 
2341  if( !SCIPallowObjProp(scip) )
2342  return SCIP_OKAY;
2343 
2344  /* get propagator data */
2345  propdata = SCIPpropGetData(prop);
2346  assert(propdata != NULL);
2347 
2348  /* ensure that bounds are initialized */
2349  if( propdata->nbounds == -1 )
2350  {
2351  /* bounds must be initialized at root node */
2352  if( SCIPgetDepth(scip) == 0 )
2353  {
2354  SCIP_CALL( initBounds(scip, propdata) );
2355  }
2356  else
2357  {
2358  assert(!SCIPinProbing(scip));
2359  return SCIP_OKAY;
2360  }
2361  }
2362  assert(propdata->nbounds >= 0);
2363 
2364  /* do not run if there are no interesting bounds */
2365  /**@todo disable */
2366  if( propdata->nbounds <= 0 )
2367  {
2368  SCIPdebugMessage("there are no interesting bounds\n");
2369  return SCIP_OKAY;
2370  }
2371 
2372  /* only run once in a node != root */
2373  if( SCIPgetDepth(scip) > 0 && SCIPnodeGetNumber(SCIPgetCurrentNode(scip)) == propdata->lastnode )
2374  {
2375  return SCIP_OKAY;
2376  }
2377 
2378  SCIPdebugMessage("applying obbt for problem <%s> at depth %d\n", SCIPgetProbName(scip), SCIPgetDepth(scip));
2379 
2380  /* without an optimal LP solution we don't want to run; this may be because propagators with higher priority have
2381  * already found reductions or numerical troubles occured during LP solving
2382  */
2384  {
2385  SCIPdebugMessage("aborting since no optimal LP solution is at hand\n");
2386  return SCIP_OKAY;
2387  }
2388 
2389  /* compute iteration limit */
2390  if( propdata->itlimitfactor > 0.0 )
2391  itlimit = (SCIP_Longint) MAX(propdata->itlimitfactor * SCIPgetNRootLPIterations(scip),
2392  propdata->minitlimit); /*lint !e666*/
2393  else
2394  itlimit = -1;
2395 
2396  /* apply obbt */
2397  SCIP_CALL( applyObbt(scip, propdata, itlimit, result) );
2398  assert(*result != SCIP_DIDNOTRUN);
2399 
2400  /* set current node as last node */
2401  propdata->lastnode = SCIPnodeGetNumber(SCIPgetCurrentNode(scip));
2402 
2403  return SCIP_OKAY;
2404 }
2405 
2406 /** propagation conflict resolving method of propagator */
2407 static
2408 SCIP_DECL_PROPRESPROP(propRespropObbt)
2409 { /*lint --e{715}*/
2410  *result = SCIP_DIDNOTFIND;
2411 
2412  return SCIP_OKAY;
2413 }
2414 
2415 /** solving process deinitialization method of propagator (called before branch and bound process data is freed) */
2416 static
2417 SCIP_DECL_PROPEXITSOL(propExitsolObbt)
2418 { /*lint --e{715}*/
2419  SCIP_PROPDATA* propdata;
2420  int i;
2421 
2422  assert(scip != NULL);
2423  assert(prop != NULL);
2424  assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
2425 
2426  /* get propagator data */
2427  propdata = SCIPpropGetData(prop);
2428  assert(propdata != NULL);
2430  /* note that because we reset filtered flags to false at each call to obbt, the same bound may be filtered multiple
2431  * times
2432  */
2433  SCIPstatisticMessage("DIVE-LP: %" SCIP_LONGINT_FORMAT " NFILTERED: %d NTRIVIALFILTERED: %d NSOLVED: %d "
2434  "FILTER-LP: %" SCIP_LONGINT_FORMAT " NGENVB(dive): %d NGENVB(aggr.): %d NGENVB(triv.) %d\n",
2435  propdata->nprobingiterations, propdata->nfiltered, propdata->ntrivialfiltered, propdata->nsolvedbounds,
2436  propdata->nfilterlpiters, propdata->ngenvboundsprobing, propdata->ngenvboundsaggrfil, propdata->ngenvboundstrivfil);
2437 
2438  /* free memory allocated for the bounds */
2439  if( propdata->nbounds > 0 )
2440  {
2441  /* free bounds */
2442  for( i = propdata->nbounds - 1; i >= 0; i-- )
2443  {
2444  SCIPfreeMemory(scip, &(propdata->bounds[i]));
2445  }
2446  SCIPfreeMemoryArray(scip, &(propdata->bounds));
2447  }
2448 
2449  propdata->nbounds = -1;
2450 
2451  return SCIP_OKAY;
2452 }
2453 
2454 /** destructor of propagator to free user data (called when SCIP is exiting) */
2455 static
2456 SCIP_DECL_PROPFREE(propFreeObbt)
2457 { /*lint --e{715}*/
2458  SCIP_PROPDATA* propdata;
2459 
2460  assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
2461 
2462  /* free propagator data */
2463  propdata = SCIPpropGetData(prop);
2464  assert(propdata != NULL);
2465 
2466  SCIPfreeMemory(scip, &propdata);
2467 
2469 
2470  return SCIP_OKAY;
2471 }
2472 
2473 
2474 /*
2475  * propagator specific interface methods
2476  */
2477 
2478 /** creates the obbt propagator and includes it in SCIP */
2480  SCIP* scip /**< SCIP data structure */
2481  )
2482 {
2483  SCIP_PROPDATA* propdata;
2484  SCIP_PROP* prop;
2485 
2486  /* create obbt propagator data */
2487  SCIP_CALL( SCIPallocMemory(scip, &propdata) );
2488 
2489  /* initialize statistic variables */
2490  propdata->nprobingiterations = 0;
2491  propdata->nfiltered = 0;
2492  propdata->ntrivialfiltered = 0;
2493  propdata->nsolvedbounds = 0;
2494  propdata->ngenvboundsprobing = 0;
2495  propdata->ngenvboundsaggrfil = 0;
2496  propdata->ngenvboundstrivfil = 0;
2497  propdata->nfilterlpiters = 0;
2498  propdata->lastidx = -1;
2499  propdata->propagatecounter = 0;
2500  propdata->npropagatedomreds = 0;
2501 
2502  /* include propagator */
2504  propExecObbt, propdata) );
2505 
2506  SCIP_CALL( SCIPsetPropFree(scip, prop, propFreeObbt) );
2507  SCIP_CALL( SCIPsetPropExitsol(scip, prop, propExitsolObbt) );
2508  SCIP_CALL( SCIPsetPropInitsol(scip, prop, propInitsolObbt) );
2509  SCIP_CALL( SCIPsetPropResprop(scip, prop, propRespropObbt) );
2510 
2511  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/creategenvbounds",
2512  "should obbt try to provide genvbounds if possible?",
2513  &propdata->creategenvbounds, TRUE, DEFAULT_CREATE_GENVBOUNDS, NULL, NULL) );
2514 
2515  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/normalize",
2516  "should coefficients in filtering be normalized w.r.t. the domains sizes?",
2517  &propdata->normalize, TRUE, DEFAULT_FILTERING_NORM, NULL, NULL) );
2518 
2519  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/applyfilterrounds",
2520  "try to filter bounds in so-called filter rounds by solving auxiliary LPs?",
2521  &propdata->applyfilterrounds, TRUE, DEFAULT_APPLY_FILTERROUNDS, NULL, NULL) );
2522 
2523  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/applytrivialfilter",
2524  "try to filter bounds with the LP solution after each solve?",
2525  &propdata->applytrivialfilter, TRUE, DEFAULT_APPLY_TRIVIALFITLERING, NULL, NULL) );
2526 
2527  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/genvbdsduringfilter",
2528  "should we try to generate genvbounds during trivial and aggressive filtering?",
2529  &propdata->genvbdsduringfilter, TRUE, DEFAULT_GENVBDSDURINGFILTER, NULL, NULL) );
2530 
2531  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/genvbdsduringsepa",
2532  "try to create genvbounds during separation process?",
2533  &propdata->genvbdsduringsepa, TRUE, DEFAULT_GENVBDSDURINGSEPA, NULL, NULL) );
2534 
2535  SCIP_CALL( SCIPaddIntParam(scip, "propagating/" PROP_NAME "/minfilter",
2536  "minimal number of filtered bounds to apply another filter round",
2537  &propdata->nminfilter, TRUE, DEFAULT_FILTERING_MIN, 1, INT_MAX, NULL, NULL) );
2538 
2539  SCIP_CALL( SCIPaddRealParam(scip, "propagating/" PROP_NAME "/itlimitfactor",
2540  "multiple of root node LP iterations used as total LP iteration limit for obbt (<= 0: no limit )",
2541  &propdata->itlimitfactor, FALSE, DEFAULT_ITLIMITFACTOR, SCIP_REAL_MIN, SCIP_REAL_MAX, NULL, NULL) );
2542 
2543  SCIP_CALL( SCIPaddLongintParam(scip, "propagating/" PROP_NAME "/minitlimit",
2544  "minimum LP iteration limit",
2545  &propdata->minitlimit, FALSE, DEFAULT_MINITLIMIT, 0L, SCIP_LONGINT_MAX, NULL, NULL) );
2546 
2547  SCIP_CALL( SCIPaddRealParam(scip, "propagating/" PROP_NAME "/dualfeastol",
2548  "feasibility tolerance for reduced costs used in obbt; this value is used if SCIP's dual feastol is greater",
2549  &propdata->dualfeastol, FALSE, DEFAULT_DUALFEASTOL, 0.0, SCIP_REAL_MAX, NULL, NULL) );
2550 
2551  SCIP_CALL( SCIPaddRealParam(scip, "propagating/" PROP_NAME "/conditionlimit",
2552  "maximum condition limit used in LP solver (-1.0: no limit)",
2553  &propdata->conditionlimit, FALSE, DEFAULT_CONDITIONLIMIT, -1.0, SCIP_REAL_MAX, NULL, NULL) );
2554 
2555  SCIP_CALL( SCIPaddRealParam(scip, "propagating/" PROP_NAME "/boundstreps",
2556  "minimal relative improve for strengthening bounds",
2557  &propdata->boundstreps, FALSE, DEFAULT_BOUNDSTREPS, 0.0, 1.0, NULL, NULL) );
2558 
2559  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/onlynonconvexvars",
2560  "only apply obbt on non-convex variables",
2561  &propdata->onlynonconvexvars, TRUE, DEFAULT_ONLYNONCONVEXVARS, NULL, NULL) );
2562 
2563  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/tightintboundsprobing",
2564  "should integral bounds be tightened during the probing mode?",
2565  &propdata->tightintboundsprobing, TRUE, DEFAULT_TIGHTINTBOUNDSPROBING, NULL, NULL) );
2566 
2567  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/tightcontboundsprobing",
2568  "should continuous bounds be tightened during the probing mode?",
2569  &propdata->tightcontboundsprobing, TRUE, DEFAULT_TIGHTCONTBOUNDSPROBING, NULL, NULL) );
2570 
2571  SCIP_CALL( SCIPaddIntParam(scip, "propagating/" PROP_NAME "/orderingalgo",
2572  "select the type of ordering algorithm which should be used (0: no special ordering, 1: greedy, 2: greedy reverse)",
2573  &propdata->orderingalgo, TRUE, DEFAULT_ORDERINGALGO, 0, 2, NULL, NULL) );
2574 
2575  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/separatesol",
2576  "should the obbt LP solution be separated?",
2577  &propdata->separatesol, TRUE, DEFAULT_SEPARATESOL, NULL, NULL) );
2578 
2579  SCIP_CALL( SCIPaddIntParam(scip, "propagating/" PROP_NAME "/sepaminiter",
2580  "minimum number of iteration spend to separate an obbt LP solution",
2581  &propdata->sepaminiter, TRUE, DEFAULT_SEPAMINITER, 0, INT_MAX, NULL, NULL) );
2582 
2583  SCIP_CALL( SCIPaddIntParam(scip, "propagating/" PROP_NAME "/sepamaxiter",
2584  "maximum number of iteration spend to separate an obbt LP solution",
2585  &propdata->sepamaxiter, TRUE, DEFAULT_SEPAMAXITER, 0, INT_MAX, NULL, NULL) );
2586 
2587  SCIP_CALL( SCIPaddIntParam(scip, "propagating/" PROP_NAME "/propagatefreq",
2588  "trigger a propagation round after that many bound tightenings (0: no propagation)",
2589  &propdata->propagatefreq, TRUE, DEFAULT_PROPAGATEFREQ, 0, INT_MAX, NULL, NULL) );
2590 
2591  return SCIP_OKAY;
2592 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:51
static SCIP_RETCODE countNLRowVarsNonConvexity(SCIP *scip, int *nlcounts, SCIP_NLROW *nlrow)
Definition: prop_obbt.c:1949
SCIP_RETCODE SCIPsetPropExitsol(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPEXITSOL((*propexitsol)))
Definition: scip.c:7025
#define DEFAULT_APPLY_FILTERROUNDS
Definition: prop_obbt.c:62
#define DEFAULT_GENVBDSDURINGFILTER
Definition: prop_obbt.c:66
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41572
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
SCIP_RETCODE SCIPsolveProbingLP(SCIP *scip, int itlim, SCIP_Bool *lperror, SCIP_Bool *cutoff)
Definition: scip.c:32788
#define PROP_NAME
Definition: prop_obbt.c:49
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:41685
#define PROP_FREQ
Definition: prop_obbt.c:53
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:10698
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:5878
#define SCIPallocMemory(scip, ptr)
Definition: scip.h:20526
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16443
unsigned int done
Definition: prop_obbt.c:124
static SCIP_DECL_SORTPTRCOMP(compBoundsScore)
Definition: prop_obbt.c:1243
SCIP_RETCODE SCIPgenVBoundAdd(SCIP *scip, SCIP_PROP *genvboundprop, SCIP_VAR **vars, SCIP_VAR *var, SCIP_Real *coefs, int ncoefs, SCIP_Real coefcutoffbound, SCIP_Real constant, SCIP_BOUNDTYPE boundtype)
static SCIP_RETCODE filterExistingLP(SCIP *scip, SCIP_PROPDATA *propdata, int *nfiltered, BOUND *currbound)
Definition: prop_obbt.c:694
#define DEFAULT_MINITLIMIT
Definition: prop_obbt.c:78
static SCIP_RETCODE sortBounds(SCIP *scip, SCIP_PROPDATA *propdata)
Definition: prop_obbt.c:1279
SCIP_RETCODE SCIPgetCurvatureNonlinear(SCIP *scip, SCIP_CONS *cons, SCIP_Bool checkcurv, SCIP_EXPRCURV *curvature)
static void exchangeBounds(SCIP_PROPDATA *propdata, int i)
Definition: prop_obbt.c:671
int SCIPnlrowGetNQuadElems(SCIP_NLROW *nlrow)
Definition: nlp.c:3312
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:41648
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16623
enum SCIP_BaseStat SCIP_BASESTAT
Definition: type_lpi.h:84
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1248
#define DEFAULT_BOUNDSTREPS
Definition: prop_obbt.c:71
SCIP_Longint SCIPgetNRootLPIterations(SCIP *scip)
Definition: scip.c:37472
#define infty2infty(infty1, infty2, val)
Definition: prop_obbt.c:109
SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
Definition: scip.c:37454
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:10653
#define SCIP_MAXSTRLEN
Definition: def.h:201
#define DEFAULT_SEPAMAXITER
Definition: prop_obbt.c:99
#define NULL
Definition: lpi_spx.cpp:130
static SCIP_DECL_PROPEXITSOL(propExitsolObbt)
Definition: prop_obbt.c:2429
#define DEFAULT_ITLIMITFACTOR
Definition: prop_obbt.c:75
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17113
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4258
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1125
SCIP_RETCODE SCIPapplyCutsProbing(SCIP *scip, SCIP_Bool *cutoff)
Definition: scip.c:32880
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17067
static SCIP_RETCODE filterRound(SCIP *scip, SCIP_PROPDATA *propdata, int itlimit, int *nfiltered, SCIP_Real *objcoefs, int *objcoefsinds, int nobjcoefs)
Definition: prop_obbt.c:810
#define SCIPfreeMemoryArray(scip, ptr)
Definition: scip.h:20544
int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4322
static int nextBound(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_Bool convexphase)
Definition: prop_obbt.c:1311
#define SCIPallocMemoryArray(scip, ptr, num)
Definition: scip.h:20528
SCIP_RETCODE SCIPpropagateProbing(SCIP *scip, int maxproprounds, SCIP_Bool *cutoff, SCIP_Longint *ndomredsfound)
Definition: scip.c:32552
#define FALSE
Definition: def.h:56
#define DEFAULT_SEPAMINITER
Definition: prop_obbt.c:98
SCIP_Real SCIPdualfeastol(SCIP *scip)
Definition: scip.c:41174
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:8174
#define DEFAULT_APPLY_TRIVIALFITLERING
Definition: prop_obbt.c:65
#define TRUE
Definition: def.h:55
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
#define SCIPstatisticMessage
Definition: pub_message.h:104
#define SCIP_CALL(x)
Definition: def.h:266
static SCIP_Real getFilterCoef(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype)
Definition: prop_obbt.c:425
SCIP_RETCODE SCIPsetRealParam(SCIP *scip, const char *name, SCIP_Real value)
Definition: scip.c:4109
int index
Definition: prop_obbt.c:126
void SCIPintervalSetBounds(SCIP_INTERVAL *resultant, SCIP_Real inf, SCIP_Real sup)
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
Definition: scip.c:38561
SCIP_PROP * SCIPfindProp(SCIP *scip, const char *name)
Definition: scip.c:7123
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:26439
SCIP_EXPRTREE * SCIPgetExprtreeBivariate(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPaddLongintParam(SCIP *scip, const char *name, const char *desc, SCIP_Longint *valueptr, SCIP_Bool isadvanced, SCIP_Longint defaultvalue, SCIP_Longint minvalue, SCIP_Longint maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3601
#define SCIPdebugMessage
Definition: pub_message.h:77
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:16905
#define GENVBOUND_PROP_NAME
Definition: prop_obbt.c:90
#define SCIP_LONGINT_MAX
Definition: def.h:113
enum SCIP_LPSolStat SCIP_LPSOLSTAT
Definition: type_lp.h:42
SCIP_Real SCIPgetLPObjval(SCIP *scip)
Definition: scip.c:26482
SCIP_Bool SCIPallColsInLP(SCIP *scip)
Definition: scip.c:26829
SCIP_Bool SCIPisLbBetter(SCIP *scip, SCIP_Real newlb, SCIP_Real oldlb, SCIP_Real oldub)
Definition: scip.c:42255
static SCIP_RETCODE tightenBoundProbing(SCIP *scip, BOUND *bound, SCIP_Real newval, SCIP_Bool *tightened)
Definition: prop_obbt.c:1182
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:7016
#define DEFAULT_ORDERINGALGO
Definition: prop_obbt.c:86
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3547
SCIP_RETCODE SCIPcreateEmptyRowUnspec(SCIP *scip, SCIP_ROW **row, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip.c:27658
static unsigned int getScore(SCIP *scip, BOUND *bound, int nlcount, int maxnlcount)
Definition: prop_obbt.c:1906
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16562
SCIP_RETCODE SCIPchgDualfeastol(SCIP *scip, SCIP_Real dualfeastol)
Definition: scip.c:41261
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3573
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16634
SCIP_RETCODE SCIPexprtreeCheckCurvature(SCIP_EXPRTREE *tree, SCIP_Real infinity, SCIP_INTERVAL *varbounds, SCIP_EXPRCURV *curv, SCIP_INTERVAL *bounds)
Definition: expr.c:8840
static SCIP_RETCODE createGenVBound(SCIP *scip, SCIP_PROPDATA *propdata, BOUND *bound, SCIP_Bool *found)
Definition: prop_obbt.c:499
#define DEFAULT_DUALFEASTOL
Definition: prop_obbt.c:67
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition: lp.c:18674
SCIP_Real coef
Definition: type_expr.h:102
#define SCIPfreeMemory(scip, ptr)
Definition: scip.h:20542
#define DEFAULT_FILTERING_NORM
Definition: prop_obbt.c:59
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41585
static SCIP_RETCODE applyBoundChgs(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_RESULT *result)
Definition: prop_obbt.c:1115
SCIP_RETCODE SCIPincludePropObbt(SCIP *scip)
Definition: prop_obbt.c:2491
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:41709
SCIP_PROPDATA * SCIPpropGetData(SCIP_PROP *prop)
Definition: prop.c:735
static SCIP_Bool includeVarGenVBound(SCIP *scip, SCIP_VAR *var)
Definition: prop_obbt.c:368
static SCIP_DECL_PROPRESPROP(propRespropObbt)
Definition: prop_obbt.c:2420
void SCIPsortDownPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
#define PROP_DESC
Definition: prop_obbt.c:50
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition: scip.c:28407
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41907
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:19126
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:41758
constraint handler for quadratic constraints
#define DEFAULT_GENVBDSDURINGSEPA
Definition: prop_obbt.c:100
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:16771
int SCIPexprtreeGetNVars(SCIP_EXPRTREE *tree)
Definition: expr.c:8452
static SCIP_Bool varIsInteresting(SCIP *scip, SCIP_VAR *var, int nlcount)
Definition: prop_obbt.c:2161
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:41637
#define DEFAULT_PROPAGATEFREQ
Definition: prop_obbt.c:101
#define OBBT_SCOREBASE
Definition: prop_obbt.c:89
static SCIP_RETCODE getNLPVarsNonConvexity(SCIP *scip, int *nlcounts)
Definition: prop_obbt.c:2019
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip.c:32131
unsigned int score
Definition: prop_obbt.c:121
static int getIterationsLeft(SCIP *scip, SCIP_Longint nolditerations, SCIP_Longint itlimit)
Definition: prop_obbt.c:395
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip.h:20598
void SCIPpropSetData(SCIP_PROP *prop, SCIP_PROPDATA *propdata)
Definition: prop.c:745
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41611
#define INTERVALINFTY
Definition: prop_obbt.c:91
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:20193
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17123
SCIP_Real SCIPnlrowGetRhs(SCIP_NLROW *nlrow)
Definition: nlp.c:3373
SCIP_RETCODE SCIPsetPropResprop(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPRESPROP((*propresprop)))
Definition: scip.c:7106
#define SCIP_Bool
Definition: def.h:53
SCIP_RETCODE SCIPsetPropFree(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPFREE((*propfree)))
Definition: scip.c:6961
SCIP_Real newval
Definition: prop_obbt.c:119
SCIP_RETCODE SCIPincludePropBasic(SCIP *scip, SCIP_PROP **propptr, const char *name, const char *desc, int priority, int freq, SCIP_Bool delay, SCIP_PROPTIMING timingmask, SCIP_DECL_PROPEXEC((*propexec)), SCIP_PROPDATA *propdata)
Definition: scip.c:6908
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip.c:801
constraint handler for nonlinear constraints
SCIP_RETCODE SCIPaddRowProbing(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:32840
optimization-based bound tightening propagator
SCIP_RETCODE SCIPcacheRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:27811
#define MAX(x, y)
Definition: tclique_def.h:75
methods for debugging
SCIP_Bool SCIPallowObjProp(SCIP *scip)
Definition: scip.c:23093
#define DEFAULT_CREATE_GENVBOUNDS
Definition: prop_obbt.c:58
static SCIP_DECL_PROPFREE(propFreeObbt)
Definition: prop_obbt.c:2468
SCIP_RETCODE SCIPgetNlRowQuadratic(SCIP *scip, SCIP_CONS *cons, SCIP_NLROW **nlrow)
SCIP_RETCODE SCIPstartProbing(SCIP *scip)
Definition: scip.c:32153
SCIP_BOUNDTYPE boundtype
Definition: prop_obbt.c:120
SCIP_Real SCIPnlrowGetLhs(SCIP_NLROW *nlrow)
Definition: nlp.c:3363
SCIP_RETCODE SCIPendProbing(SCIP *scip)
Definition: scip.c:32285
SCIP_RETCODE SCIPseparateSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool pretendroot, SCIP_Bool onlydelayed, SCIP_Bool *delayed, SCIP_Bool *cutoff)
Definition: scip.c:31435
constraint handler for bivariate nonlinear constraints
static SCIP_RETCODE applySeparation(SCIP *scip, SCIP_PROPDATA *propdata, BOUND *currbound, SCIP_Longint *nleftiterations, SCIP_Bool *success)
Definition: prop_obbt.c:1363
Constraint handler for absolute power constraints .
SCIP_Real SCIPgetVarRedcost(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:17497
SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
Definition: scip.c:36779
static SCIP_RETCODE setObjProbing(SCIP *scip, SCIP_PROPDATA *propdata, BOUND *bound, SCIP_Real coef)
Definition: prop_obbt.c:321
SCIP_RETCODE SCIPsetPropInitsol(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPINITSOL((*propinitsol)))
Definition: scip.c:7009
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:38140
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:17431
#define SCIP_REAL_MAX
Definition: def.h:128
unsigned int found
Definition: prop_obbt.c:123
SCIP_RETCODE SCIPchgVarObjProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip.c:32471
#define SCIP_REAL_MIN
Definition: def.h:129
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16608
static SCIP_RETCODE solveLP(SCIP *scip, int itlimit, SCIP_Bool *error, SCIP_Bool *optimal)
Definition: prop_obbt.c:189
enum SCIP_ExprCurv SCIP_EXPRCURV
Definition: type_expr.h:93
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
Definition: scip.c:41770
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20585
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17057
#define PROP_TIMING
Definition: prop_obbt.c:51
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition: lp.c:18935
SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:27834
SCIP_VAR ** SCIPnlrowGetQuadVars(SCIP_NLROW *nlrow)
Definition: nlp.c:3275
#define REALABS(x)
Definition: def.h:151
SCIP_EXPRTREE * SCIPnlrowGetExprtree(SCIP_NLROW *nlrow)
Definition: nlp.c:3353
#define DEFAULT_SEPARATESOL
Definition: prop_obbt.c:93
SCIP_RETCODE SCIPchgVarUbProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:32352
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41933
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16750
static SCIP_RETCODE findNewBounds(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_Longint *nleftiterations, SCIP_Bool convexphase)
Definition: prop_obbt.c:1445
#define DEFAULT_ONLYNONCONVEXVARS
Definition: prop_obbt.c:79
#define SCIP_Real
Definition: def.h:127
SCIP_RETCODE SCIPgetNLPVarsNonlinearity(SCIP *scip, int *nlcount)
Definition: scip.c:28518
int SCIPgetNCuts(SCIP *scip)
Definition: scip.c:31485
SCIP_RETCODE SCIPchgVarLbProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:32318
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:20299
struct SCIP_PropData SCIP_PROPDATA
Definition: type_prop.h:38
#define MIN(x, y)
Definition: memory.c:67
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41959
SCIP_RETCODE SCIPgetNlRowNonlinear(SCIP *scip, SCIP_CONS *cons, SCIP_NLROW **nlrow)
#define SCIP_INVALID
Definition: def.h:147
static SCIP_Real evalBound(SCIP *scip, BOUND *bound)
Definition: prop_obbt.c:1295
SCIP_VAR * var
Definition: prop_obbt.c:118
const char * SCIPgetProbName(SCIP *scip)
Definition: scip.c:9941
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip.c:27738
static SCIP_RETCODE filterBounds(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_Longint itlimit)
Definition: prop_obbt.c:971
#define SCIP_Longint
Definition: def.h:112
#define DEFAULT_TIGHTCONTBOUNDSPROBING
Definition: prop_obbt.c:83
static SCIP_RETCODE addObjCutoff(SCIP *scip, SCIP_PROPDATA *propdata)
Definition: prop_obbt.c:261
static SCIP_Bool varIsFixedLocal(SCIP *scip, SCIP_VAR *var)
Definition: prop_obbt.c:311
static SCIP_DECL_PROPINITSOL(propInitsolObbt)
Definition: prop_obbt.c:2294
unsigned int filtered
Definition: prop_obbt.c:122
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip.c:10572
#define PROP_DELAY
Definition: prop_obbt.c:54
#define PROP_PRIORITY
Definition: prop_obbt.c:52
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:20597
#define DEFAULT_CONDITIONLIMIT
Definition: prop_obbt.c:70
SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
Definition: scip.c:3797
#define SCIPdebug(x)
Definition: pub_message.h:74
unsigned int nonconvex
Definition: prop_obbt.c:125
#define DEFAULT_TIGHTINTBOUNDSPROBING
Definition: prop_obbt.c:80
int SCIPgetNNLPVars(SCIP *scip)
Definition: scip.c:28496
SCIP_Real SCIPgetVarObjProbing(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:32385
static SCIP_RETCODE initBounds(SCIP *scip, SCIP_PROPDATA *propdata)
Definition: prop_obbt.c:2177
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:41697
static SCIP_DECL_PROPEXEC(propExecObbt)
Definition: prop_obbt.c:2322
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3629
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:27864
static SCIP_RETCODE applyObbt(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_Longint itlimit, SCIP_RESULT *result)
Definition: prop_obbt.c:1684
#define DEFAULT_FILTERING_MIN
Definition: prop_obbt.c:72
SCIP_VAR ** SCIPexprtreeGetVars(SCIP_EXPRTREE *tree)
Definition: nlp.c:101
const char * SCIPpropGetName(SCIP_PROP *prop)
Definition: prop.c:887
SCIP_Bool SCIPinRepropagation(SCIP *scip)
Definition: scip.c:36834
SCIP_Bool SCIPisUbBetter(SCIP *scip, SCIP_Real newub, SCIP_Real oldlb, SCIP_Real oldub)
Definition: scip.c:42270
SCIP_Bool SCIPisConvexQuadratic(SCIP *scip, SCIP_CONS *cons)
SCIP_QUADELEM * SCIPnlrowGetQuadElems(SCIP_NLROW *nlrow)
Definition: nlp.c:3322
generalized variable bounds propagator
SCIP_RETCODE SCIPgetNlRowAbspower(SCIP *scip, SCIP_CONS *cons, SCIP_NLROW **nlrow)