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-2015 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  {
767  SCIP_Bool found;
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  {
912  SCIP_Bool found;
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  SCIP_CALL( SCIPchgVarObjProbing(scip, vars[i], 0.0) );
1802  }
1803 
1804  /* find new bounds for the variables */
1805  SCIP_CALL( findNewBounds(scip, propdata, &nleftiterations, FALSE) );
1806 
1807  if( nleftiterations > 0 || itlimit < 0 )
1808  {
1809  SCIP_CALL( findNewBounds(scip, propdata, &nleftiterations, TRUE) );
1810  }
1811 
1812  /* reset dual feastol and condition limit */
1813  SCIP_CALL( SCIPchgDualfeastol(scip, olddualfeastol) );
1814  if( hasconditionlimit )
1815  {
1816  SCIP_CALL( SCIPsetRealParam(scip, "lp/conditionlimit", oldconditionlimit) );
1817  }
1818 
1819  /* update bound->newval if we have learned additional bound tightenings during SCIPpropagateProbing() */
1820  if( oldlbs != NULL && oldubs != NULL && propdata->npropagatedomreds - lastnpropagatedomreds > 0 )
1821  {
1822  assert(propdata->propagatefreq > 0);
1823  for( i = 0; i < propdata->nbounds; ++i )
1824  {
1825  BOUND* bound = propdata->bounds[i];
1826 
1827  /* it might be the case that a bound found by the additional propagation is better than the bound found after solving an OBBT
1828  * LP
1829  */
1830  if( bound->found )
1831  {
1832  if( bound->boundtype == SCIP_BOUNDTYPE_LOWER )
1833  bound->newval = MAX(bound->newval, SCIPvarGetLbLocal(bound->var)); /*lint !e666*/
1834  else
1835  bound->newval = MIN(bound->newval, SCIPvarGetUbLocal(bound->var)); /*lint !e666*/
1836  }
1837  else
1838  {
1839  SCIP_Real oldlb;
1840  SCIP_Real oldub;
1841 
1842  oldlb = oldlbs[bound->index];
1843  oldub = oldubs[bound->index];
1844 
1845  if( bound->boundtype == SCIP_BOUNDTYPE_LOWER && SCIPisLbBetter(scip, SCIPvarGetLbLocal(bound->var), oldlb, oldub) )
1846  {
1847  SCIPdebugMessage("tighter lower bound due to propagation: %d - %e -> %e\n", i, oldlb, SCIPvarGetLbLocal(bound->var));
1848  bound->newval = SCIPvarGetLbLocal(bound->var);
1849  bound->found = TRUE;
1850  }
1851 
1852  if( bound->boundtype == SCIP_BOUNDTYPE_UPPER && SCIPisUbBetter(scip, SCIPvarGetUbLocal(bound->var), oldlb, oldub) )
1853  {
1854  SCIPdebugMessage("tighter upper bound due to propagation: %d - %e -> %e\n", i, oldub, SCIPvarGetUbLocal(bound->var));
1855  bound->newval = SCIPvarGetUbLocal(bound->var);
1856  bound->found = TRUE;
1857  }
1858  }
1859  }
1860  }
1861 
1862  /* reset relative bound improvement limit */
1863  SCIP_CALL( SCIPsetRealParam(scip, "numerics/boundstreps", oldboundstreps) );
1864 
1865  /* end probing */
1866  SCIP_CALL( SCIPendProbing(scip) );
1867  SCIPdebugMessage("end probing!\n");
1868 
1869  /* release cutoff row if there is one */
1870  if( propdata->cutoffrow != NULL )
1871  {
1872  assert(!SCIProwIsInLP(propdata->cutoffrow));
1873  SCIP_CALL( SCIPreleaseRow(scip, &(propdata->cutoffrow)) );
1874  }
1875 
1876  /* apply buffered bound changes */
1877  SCIP_CALL( applyBoundChgs(scip, propdata, result) );
1878 
1879 TERMINATE:
1880  SCIPfreeBufferArrayNull(scip, &oldubs);
1881  SCIPfreeBufferArrayNull(scip, &oldlbs);
1882 
1883  return SCIP_OKAY;
1884 }
1885 
1886 /** computes the score of a bound */
1887 static
1888 unsigned int getScore(
1889  SCIP* scip, /**< SCIP data structure */
1890  BOUND* bound, /**< pointer of bound */
1891  int nlcount, /**< number of nonlinear constraints containing the bounds variable */
1892  int maxnlcount /**< maximal number of nonlinear constraints a variable appears in */
1893  )
1894 {
1895  unsigned int score; /* score to be computed */
1896 
1897  assert(scip != NULL);
1898  assert(bound != NULL);
1899  assert(nlcount >= 0);
1900  assert(maxnlcount >= nlcount);
1901 
1902  /* score = ( nlcount * ( BASE - 1 ) / maxnlcount ) * BASE^2 + vartype * BASE + boundtype */
1903  score = (unsigned int) ( nlcount > 0 ? (OBBT_SCOREBASE * nlcount * ( OBBT_SCOREBASE - 1 )) / maxnlcount : 0 );
1904  switch( SCIPvarGetType(bound->var) )
1905  {
1906  case SCIP_VARTYPE_INTEGER:
1907  score += 1;
1908  break;
1909  case SCIP_VARTYPE_IMPLINT:
1910  score += 2;
1911  break;
1913  score += 3;
1914  break;
1915  case SCIP_VARTYPE_BINARY:
1916  score += 4;
1917  break;
1918  default:
1919  break;
1920  }
1921 
1922  score *= OBBT_SCOREBASE;
1923  if( bound->boundtype == SCIP_BOUNDTYPE_UPPER )
1924  score += 1;
1925 
1926  return score;
1927 }
1928 
1929 /** count the variables which appear in non-convex term of nlrow */
1930 static
1932  SCIP* scip, /**< SCIP data structure */
1933  int* nlcounts, /**< store the number each variable appears in a
1934  * non-convex term */
1935  SCIP_NLROW* nlrow /**< nonlinear row */
1936  )
1937 {
1938  int t;
1939  int nexprtreevars;
1940  SCIP_VAR** exprtreevars;
1941  SCIP_EXPRTREE* exprtree;
1942 
1943  assert(scip != NULL);
1944  assert(nlcounts != NULL);
1945  assert(nlrow != NULL);
1946 
1947  /* go through all quadratic terms */
1948  for( t = SCIPnlrowGetNQuadElems(nlrow) - 1; t >= 0; --t )
1949  {
1950  SCIP_QUADELEM* quadelem;
1951  SCIP_VAR* bilinvar1;
1952  SCIP_VAR* bilinvar2;
1953 
1954  /* get quadratic term */
1955  quadelem = &SCIPnlrowGetQuadElems(nlrow)[t];
1956 
1957  /* get involved variables */
1958  bilinvar1 = SCIPnlrowGetQuadVars(nlrow)[quadelem->idx1];
1959  bilinvar2 = SCIPnlrowGetQuadVars(nlrow)[quadelem->idx2];
1960 
1961  assert(bilinvar1 != NULL);
1962  assert(bilinvar2 != NULL);
1963 
1964  /* we have a non-convex square term */
1965  if( bilinvar1 == bilinvar2 && !(quadelem->coef >= 0 ? SCIPisInfinity(scip, -SCIPnlrowGetLhs(nlrow)) : SCIPisInfinity(scip, SCIPnlrowGetRhs(nlrow))) )
1966  {
1967  ++nlcounts[SCIPvarGetProbindex(bilinvar1)];
1968  ++nlcounts[SCIPvarGetProbindex(bilinvar2)];
1969  }
1970 
1971  /* bilinear terms are in general non-convex */
1972  if( bilinvar1 != bilinvar2 )
1973  {
1974  ++nlcounts[SCIPvarGetProbindex(bilinvar1)];
1975  ++nlcounts[SCIPvarGetProbindex(bilinvar2)];
1976  }
1977  }
1978 
1979  exprtree = SCIPnlrowGetExprtree(nlrow);
1980  if( exprtree != NULL )
1981  {
1982  nexprtreevars = SCIPexprtreeGetNVars(exprtree);
1983  exprtreevars = SCIPexprtreeGetVars(exprtree);
1984 
1985  /* assume that the expression tree represents a non-convex constraint */
1986  for( t = 0; t < nexprtreevars; ++t)
1987  {
1988  SCIP_VAR* var;
1989  var = exprtreevars[t];
1990  assert(var != NULL);
1991 
1992  ++nlcounts[SCIPvarGetProbindex(var)];
1993  }
1994  }
1995 
1996  return SCIP_OKAY;
1997 }
1998 
1999 /** count how often each variable appears in a non-convex term */
2000 static
2002  SCIP* scip, /**< SCIP data structure */
2003  int* nlcounts /**< store the number each variable appears in a
2004  * non-convex term */
2005  )
2006 {
2007  SCIP_CONSHDLR* conshdlr;
2008  SCIP_CONS** conss;
2009  int nvars;
2010  int nconss;
2011  int i;
2012 
2013  assert(scip != NULL);
2014  assert(nlcounts != NULL);
2015 
2016  nvars = SCIPgetNVars(scip);
2017  BMSclearMemoryArray(nlcounts, nvars);
2018 
2019  /* quadratic constraint handler */
2020  conshdlr = SCIPfindConshdlr(scip, "quadratic");
2021  if( conshdlr != NULL )
2022  {
2023 
2024  /*SCIPdebugMessage("cons_quadratic is there!\n");*/
2025  nconss = SCIPconshdlrGetNActiveConss(conshdlr);
2026  conss = SCIPconshdlrGetConss(conshdlr);
2027 
2028  SCIPdebugMessage("nconss(quadratic) = %d\n", nconss);
2029 
2030  for( i = 0; i < nconss; ++i )
2031  {
2032  /* only check the nlrow if the constraint is not convex */
2033  if( SCIPisConvexQuadratic(scip, conss[i]) == FALSE )
2034  {
2035  SCIP_NLROW* nlrow;
2036  SCIP_CALL( SCIPgetNlRowQuadratic(scip, conss[i], &nlrow) );
2037  assert(nlrow != NULL);
2038 
2039  SCIP_CALL( countNLRowVarsNonConvexity(scip, nlcounts, nlrow) );
2040  }
2041  }
2042  }
2043 
2044  /* nonlinear constraint handler */
2045  conshdlr = SCIPfindConshdlr(scip, "nonlinear");
2046  if( conshdlr != NULL )
2047  {
2048  nconss = SCIPconshdlrGetNActiveConss(conshdlr);
2049  conss = SCIPconshdlrGetConss(conshdlr);
2050 
2051  SCIPdebugMessage("nconss(nonlinear) = %d\n", nconss);
2052 
2053  for( i = 0; i < nconss; ++i )
2054  {
2055  SCIP_EXPRCURV curvature;
2056  SCIP_CALL( SCIPgetCurvatureNonlinear(scip, conss[i], TRUE, &curvature) );
2057 
2058  /* only check the nlrow if the constraint is not convex */
2059  if( curvature != SCIP_EXPRCURV_CONVEX )
2060  {
2061  SCIP_NLROW* nlrow;
2062  SCIP_CALL( SCIPgetNlRowNonlinear(scip, conss[i], &nlrow) );
2063  assert(nlrow != NULL);
2064 
2065  SCIP_CALL( countNLRowVarsNonConvexity(scip, nlcounts, nlrow) );
2066  }
2067  }
2068  }
2069 
2070  /* bivariate constraint handler */
2071  conshdlr = SCIPfindConshdlr(scip, "bivariate");
2072  if( conshdlr != NULL )
2073  {
2074  nconss = SCIPconshdlrGetNActiveConss(conshdlr);
2075  conss = SCIPconshdlrGetConss(conshdlr);
2076 
2077  SCIPdebugMessage("nconss(bivariate) = %d\n", nconss);
2078 
2079  for( i = 0; i < nconss; ++i )
2080  {
2081  SCIP_EXPRCURV curvature;
2082  SCIP_INTERVAL* varbounds;
2083  SCIP_EXPRTREE* exprtree;
2084  int j;
2085 
2086  exprtree = SCIPgetExprtreeBivariate(scip, conss[i]);
2087  if( exprtree != NULL )
2088  {
2089  SCIP_CALL( SCIPallocBufferArray(scip, &varbounds, SCIPexprtreeGetNVars(exprtree)) );
2090  for( j = 0; j < SCIPexprtreeGetNVars(exprtree); ++j )
2091  {
2092  SCIP_VAR* var;
2093  var = SCIPexprtreeGetVars(exprtree)[j];
2094 
2095  SCIPintervalSetBounds(&varbounds[j],
2096  -infty2infty(SCIPinfinity(scip), INTERVALINFTY, -MIN(SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var))), /*lint !e666*/
2097  +infty2infty(SCIPinfinity(scip), INTERVALINFTY, MAX(SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var))) ); /*lint !e666*/
2098  }
2099 
2100  SCIP_CALL( SCIPexprtreeCheckCurvature(exprtree, SCIPinfinity(scip), varbounds, &curvature, NULL) );
2101 
2102  /* increase counter for all variables in the expression tree if the constraint is non-convex */
2103  if( curvature != SCIP_EXPRCURV_CONVEX )
2104  {
2105  for( j = 0; j < SCIPexprtreeGetNVars(exprtree); ++j )
2106  {
2107  SCIP_VAR* var;
2108  var = SCIPexprtreeGetVars(exprtree)[j];
2109 
2110  ++nlcounts[SCIPvarGetProbindex(var)];
2111  }
2112  }
2113  }
2114  }
2115  }
2116 
2117  /* abspower constraint handler */
2118  conshdlr = SCIPfindConshdlr(scip, "abspower");
2119  if( conshdlr != NULL )
2120  {
2121  nconss = SCIPconshdlrGetNActiveConss(conshdlr);
2122  conss = SCIPconshdlrGetConss(conshdlr);
2123 
2124  SCIPdebugMessage("nconss(abspower) = %d\n", nconss);
2125 
2126  for( i = 0; i < nconss; ++i )
2127  {
2128  /* constraint is non-convex in general */
2129  SCIP_NLROW* nlrow;
2130  SCIP_CALL( SCIPgetNlRowAbspower(scip, conss[i], &nlrow) );
2131  assert(nlrow != NULL);
2132 
2133  SCIP_CALL( countNLRowVarsNonConvexity(scip, nlcounts, nlrow) );
2134  }
2135  }
2136 
2137  return SCIP_OKAY;
2138 }
2139 
2140 
2141 /** determines whether a variable is interesting */
2142 static
2144  SCIP* scip, /**< SCIP data structure */
2145  SCIP_VAR* var, /**< variable to check */
2146  int nlcount /**< number of nonlinear constraints containing the variable
2147  * or number of non-convex terms containing the variable
2148  * (depends on propdata->onlynonconvexvars) */
2149  )
2150 {
2151  assert(SCIPgetDepth(scip) == 0);
2152 
2153  return !SCIPvarIsBinary(var) && SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN && nlcount > 0
2154  && !varIsFixedLocal(scip, var);
2156 
2157 /** initializes interesting bounds */
2158 static
2160  SCIP* scip, /**< SCIP data structure */
2161  SCIP_PROPDATA* propdata /**< data of the obbt propagator */
2162  )
2163 {
2164  SCIP_VAR** vars; /* array of the problems variables */
2165  int* nlcount; /* array that stores in how many nonlinearities each variable appears */
2166  int* nccount; /* array that stores in how many nonconvexities each variable appears */
2167 
2168  int bdidx; /* bound index inside propdata->bounds */
2169  int maxnlcount; /* maximal number of nonlinear constraints a variable appears in */
2170  int nvars; /* number of the problems variables */
2171  int i;
2172 
2173  assert(scip != NULL);
2174  assert(propdata != NULL);
2175  assert(SCIPisNLPConstructed(scip));
2176 
2177  SCIPdebugMessage("initialize bounds\n");
2178 
2179  /* get variable data */
2180  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
2181 
2182  /* count nonlinearities */
2183  assert(SCIPgetNNLPVars(scip) == nvars);
2184 
2185  SCIP_CALL( SCIPallocBufferArray(scip, &nlcount, nvars) );
2186  SCIP_CALL( SCIPallocBufferArray(scip, &nccount, nvars) );
2187 
2188  SCIP_CALL( SCIPgetNLPVarsNonlinearity(scip, nlcount) );
2189  SCIP_CALL( getNLPVarsNonConvexity(scip, nccount) );
2190 
2191  maxnlcount = 0;
2192  for( i = 0; i < nvars; i++ )
2193  {
2194  if( maxnlcount < nlcount[i] )
2195  maxnlcount = nlcount[i];
2196  }
2197 
2198  /* allocate interesting bounds array */
2199  SCIP_CALL( SCIPallocMemoryArray(scip, &(propdata->bounds), 2 * nvars) );
2200 
2201  /* get all interesting variables and their bounds */
2202  bdidx = 0;
2203  for( i = 0; i < nvars; i++ )
2204  {
2205  if( varIsInteresting(scip, vars[i], (propdata->onlynonconvexvars ? nccount[i] : nlcount[i])) )
2206  {
2207  BOUND** bdaddress;
2208 
2209  /* create lower bound */
2210  bdaddress = &(propdata->bounds[bdidx]);
2211  SCIP_CALL( SCIPallocMemory(scip, bdaddress) );
2212  propdata->bounds[bdidx]->boundtype = SCIP_BOUNDTYPE_LOWER;
2213  propdata->bounds[bdidx]->var = vars[i];
2214  propdata->bounds[bdidx]->found = FALSE;
2215  propdata->bounds[bdidx]->filtered = FALSE;
2216  propdata->bounds[bdidx]->newval = 0.0;
2217  propdata->bounds[bdidx]->score = getScore(scip, propdata->bounds[bdidx], nlcount[i], maxnlcount);
2218  propdata->bounds[bdidx]->done = FALSE;
2219  propdata->bounds[bdidx]->nonconvex = (nccount[i] > 0);
2220  propdata->bounds[bdidx]->index = bdidx;
2221  bdidx++;
2222 
2223  /* create upper bound */
2224  bdaddress = &(propdata->bounds[bdidx]);
2225  SCIP_CALL( SCIPallocMemory(scip, bdaddress) );
2226  propdata->bounds[bdidx]->boundtype = SCIP_BOUNDTYPE_UPPER;
2227  propdata->bounds[bdidx]->var = vars[i];
2228  propdata->bounds[bdidx]->found = FALSE;
2229  propdata->bounds[bdidx]->filtered = FALSE;
2230  propdata->bounds[bdidx]->newval = 0.0;
2231  propdata->bounds[bdidx]->score = getScore(scip, propdata->bounds[bdidx], nlcount[i], maxnlcount);
2232  propdata->bounds[bdidx]->done = FALSE;
2233  propdata->bounds[bdidx]->nonconvex = (nccount[i] > 0);
2234  propdata->bounds[bdidx]->index = bdidx;
2235  bdidx++;
2236  }
2237  }
2238 
2239  /* free memory for buffering nonlinearities */
2240  assert(nlcount != NULL);
2241  assert(nccount != NULL);
2242  SCIPfreeBufferArray(scip, &nlcount);
2243  SCIPfreeBufferArray(scip, &nccount);
2244 
2245  /* set number of interesting bounds */
2246  propdata->nbounds = bdidx;
2247 
2248  /* propdata->bounds array if empty */
2249  if( propdata->nbounds <= 0 )
2250  {
2251  assert(propdata->nbounds == 0);
2252  SCIPfreeMemoryArray(scip, &(propdata->bounds));
2253  }
2254 
2255  SCIPdebugMessage("problem has %d/%d interesting bounds\n", propdata->nbounds, 2 * nvars);
2256 
2257  if( propdata->nbounds > 0 )
2258  {
2259  /* sort bounds according to decreasing score; although this initial order will be overruled by the distance
2260  * criterion later, gives a more well-defined starting situation for OBBT and might help to reduce solver
2261  * variability
2262  */
2263  SCIPsortDownPtr((void**) propdata->bounds, compBoundsScore, propdata->nbounds);
2264  }
2265 
2266  return SCIP_OKAY;
2267 }
2268 
2269 
2270 /*
2271  * Callback methods of propagator
2272  */
2273 
2274 /** solving process initialization method of propagator (called when branch and bound process is about to begin) */
2275 static
2276 SCIP_DECL_PROPINITSOL(propInitsolObbt)
2277 { /*lint --e{715}*/
2278  SCIP_PROPDATA* propdata;
2279 
2280  assert(scip != NULL);
2281  assert(prop != NULL);
2282  assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
2283 
2284  /* get propagator data */
2285  propdata = SCIPpropGetData(prop);
2286  assert(propdata != NULL);
2287 
2288  propdata->bounds = NULL;
2289  propdata->nbounds = -1;
2290  propdata->cutoffrow = NULL;
2291  propdata->lastnode = -1;
2292 
2293 
2294  /* if genvbounds propagator is not available, we cannot create genvbounds */
2295  propdata->genvboundprop = propdata->creategenvbounds ? SCIPfindProp(scip, GENVBOUND_PROP_NAME) : NULL;
2296 
2297  SCIPdebugMessage("creating genvbounds: %s\n", propdata->genvboundprop != NULL ? "true" : "false");
2298 
2299  return SCIP_OKAY;
2300 }
2301 
2302 /** execution method of propagator */
2303 static
2304 SCIP_DECL_PROPEXEC(propExecObbt)
2305 { /*lint --e{715}*/
2306  SCIP_PROPDATA* propdata;
2307  SCIP_Longint itlimit;
2308 
2309  assert(scip != NULL);
2310  assert(prop != NULL);
2311  assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
2312 
2313  *result = SCIP_DIDNOTRUN;
2314 
2315  /* do not run in: presolving, repropagation, probing mode, if no objective propagation is allowed */
2317  return SCIP_OKAY;
2318 
2319  /* only run for nonlinear problems, i.e., if NLP is constructed */
2320  if( !SCIPisNLPConstructed(scip) )
2321  {
2322  SCIPdebugMessage("NLP not constructed, skipping obbt\n");
2323  return SCIP_OKAY;
2324  }
2325 
2326  /* 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
2327  * since pricing is not performed in probing mode
2328  */
2329  if( !SCIPallColsInLP(scip) )
2330  {
2331  SCIPdebugMessage("not all columns in LP, skipping obbt\n");
2332  return SCIP_OKAY;
2333  }
2334 
2335  if( !SCIPallowObjProp(scip) )
2336  return SCIP_OKAY;
2337 
2338  /* get propagator data */
2339  propdata = SCIPpropGetData(prop);
2340  assert(propdata != NULL);
2341 
2342  /* ensure that bounds are initialized */
2343  if( propdata->nbounds == -1 )
2344  {
2345  /* bounds must be initialized at root node */
2346  if( SCIPgetDepth(scip) == 0 )
2347  {
2348  SCIP_CALL( initBounds(scip, propdata) );
2349  }
2350  else
2351  {
2352  assert(!SCIPinProbing(scip));
2353  return SCIP_OKAY;
2354  }
2355  }
2356  assert(propdata->nbounds >= 0);
2357 
2358  /* do not run if there are no interesting bounds */
2359  /**@todo disable */
2360  if( propdata->nbounds <= 0 )
2361  {
2362  SCIPdebugMessage("there are no interesting bounds\n");
2363  return SCIP_OKAY;
2364  }
2365 
2366  /* only run once in a node != root */
2367  if( SCIPgetDepth(scip) > 0 && SCIPnodeGetNumber(SCIPgetCurrentNode(scip)) == propdata->lastnode )
2368  {
2369  return SCIP_OKAY;
2370  }
2371 
2372  SCIPdebugMessage("applying obbt for problem <%s> at depth %d\n", SCIPgetProbName(scip), SCIPgetDepth(scip));
2373 
2374  /* without an optimal LP solution we don't want to run; this may be because propagators with higher priority have
2375  * already found reductions or numerical troubles occured during LP solving
2376  */
2378  {
2379  SCIPdebugMessage("aborting since no optimal LP solution is at hand\n");
2380  return SCIP_OKAY;
2381  }
2382 
2383  /* compute iteration limit */
2384  if( propdata->itlimitfactor > 0.0 )
2385  itlimit = (SCIP_Longint) MAX(propdata->itlimitfactor * SCIPgetNRootLPIterations(scip),
2386  propdata->minitlimit); /*lint !e666*/
2387  else
2388  itlimit = -1;
2389 
2390  /* apply obbt */
2391  SCIP_CALL( applyObbt(scip, propdata, itlimit, result) );
2392  assert(*result != SCIP_DIDNOTRUN);
2393 
2394  /* set current node as last node */
2395  propdata->lastnode = SCIPnodeGetNumber(SCIPgetCurrentNode(scip));
2396 
2397  return SCIP_OKAY;
2398 }
2399 
2400 /** propagation conflict resolving method of propagator */
2401 static
2402 SCIP_DECL_PROPRESPROP(propRespropObbt)
2403 { /*lint --e{715}*/
2404  *result = SCIP_DIDNOTFIND;
2405 
2406  return SCIP_OKAY;
2407 }
2408 
2409 /** solving process deinitialization method of propagator (called before branch and bound process data is freed) */
2410 static
2411 SCIP_DECL_PROPEXITSOL(propExitsolObbt)
2412 { /*lint --e{715}*/
2413  SCIP_PROPDATA* propdata;
2414  int i;
2415 
2416  assert(scip != NULL);
2417  assert(prop != NULL);
2418  assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
2419 
2420  /* get propagator data */
2421  propdata = SCIPpropGetData(prop);
2422  assert(propdata != NULL);
2424  /* note that because we reset filtered flags to false at each call to obbt, the same bound may be filtered multiple
2425  * times
2426  */
2427  SCIPstatisticMessage("DIVE-LP: %" SCIP_LONGINT_FORMAT " NFILTERED: %d NTRIVIALFILTERED: %d NSOLVED: %d "
2428  "FILTER-LP: %" SCIP_LONGINT_FORMAT " NGENVB(dive): %d NGENVB(aggr.): %d NGENVB(triv.) %d\n",
2429  propdata->nprobingiterations, propdata->nfiltered, propdata->ntrivialfiltered, propdata->nsolvedbounds,
2430  propdata->nfilterlpiters, propdata->ngenvboundsprobing, propdata->ngenvboundsaggrfil, propdata->ngenvboundstrivfil);
2431 
2432  /* free memory allocated for the bounds */
2433  if( propdata->nbounds > 0 )
2434  {
2435  /* free bounds */
2436  for( i = propdata->nbounds - 1; i >= 0; i-- )
2437  {
2438  SCIPfreeMemory(scip, &(propdata->bounds[i]));
2439  }
2440  SCIPfreeMemoryArray(scip, &(propdata->bounds));
2441  }
2442 
2443  propdata->nbounds = -1;
2444 
2445  return SCIP_OKAY;
2446 }
2447 
2448 /** destructor of propagator to free user data (called when SCIP is exiting) */
2449 static
2450 SCIP_DECL_PROPFREE(propFreeObbt)
2451 { /*lint --e{715}*/
2452  SCIP_PROPDATA* propdata;
2453 
2454  assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
2455 
2456  /* free propagator data */
2457  propdata = SCIPpropGetData(prop);
2458  assert(propdata != NULL);
2459 
2460  SCIPfreeMemory(scip, &propdata);
2461 
2463 
2464  return SCIP_OKAY;
2465 }
2466 
2467 
2468 /*
2469  * propagator specific interface methods
2470  */
2471 
2472 /** creates the obbt propagator and includes it in SCIP */
2474  SCIP* scip /**< SCIP data structure */
2475  )
2476 {
2477  SCIP_PROPDATA* propdata;
2478  SCIP_PROP* prop;
2479 
2480  /* create obbt propagator data */
2481  SCIP_CALL( SCIPallocMemory(scip, &propdata) );
2482 
2483  /* initialize statistic variables */
2484  propdata->nprobingiterations = 0;
2485  propdata->nfiltered = 0;
2486  propdata->ntrivialfiltered = 0;
2487  propdata->nsolvedbounds = 0;
2488  propdata->ngenvboundsprobing = 0;
2489  propdata->ngenvboundsaggrfil = 0;
2490  propdata->ngenvboundstrivfil = 0;
2491  propdata->nfilterlpiters = 0;
2492  propdata->lastidx = -1;
2493  propdata->propagatecounter = 0;
2494  propdata->npropagatedomreds = 0;
2495 
2496  /* include propagator */
2498  propExecObbt, propdata) );
2499 
2500  SCIP_CALL( SCIPsetPropFree(scip, prop, propFreeObbt) );
2501  SCIP_CALL( SCIPsetPropExitsol(scip, prop, propExitsolObbt) );
2502  SCIP_CALL( SCIPsetPropInitsol(scip, prop, propInitsolObbt) );
2503  SCIP_CALL( SCIPsetPropResprop(scip, prop, propRespropObbt) );
2504 
2505  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/creategenvbounds",
2506  "should obbt try to provide genvbounds if possible?",
2507  &propdata->creategenvbounds, TRUE, DEFAULT_CREATE_GENVBOUNDS, NULL, NULL) );
2508 
2509  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/normalize",
2510  "should coefficients in filtering be normalized w.r.t. the domains sizes?",
2511  &propdata->normalize, TRUE, DEFAULT_FILTERING_NORM, NULL, NULL) );
2512 
2513  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/applyfilterrounds",
2514  "try to filter bounds in so-called filter rounds by solving auxiliary LPs?",
2515  &propdata->applyfilterrounds, TRUE, DEFAULT_APPLY_FILTERROUNDS, NULL, NULL) );
2516 
2517  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/applytrivialfilter",
2518  "try to filter bounds with the LP solution after each solve?",
2519  &propdata->applytrivialfilter, TRUE, DEFAULT_APPLY_TRIVIALFITLERING, NULL, NULL) );
2520 
2521  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/genvbdsduringfilter",
2522  "should we try to generate genvbounds during trivial and aggressive filtering?",
2523  &propdata->genvbdsduringfilter, TRUE, DEFAULT_GENVBDSDURINGFILTER, NULL, NULL) );
2524 
2525  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/genvbdsduringsepa",
2526  "try to create genvbounds during separation process?",
2527  &propdata->genvbdsduringsepa, TRUE, DEFAULT_GENVBDSDURINGSEPA, NULL, NULL) );
2528 
2529  SCIP_CALL( SCIPaddIntParam(scip, "propagating/" PROP_NAME "/minfilter",
2530  "minimal number of filtered bounds to apply another filter round",
2531  &propdata->nminfilter, TRUE, DEFAULT_FILTERING_MIN, 1, INT_MAX, NULL, NULL) );
2532 
2533  SCIP_CALL( SCIPaddRealParam(scip, "propagating/" PROP_NAME "/itlimitfactor",
2534  "multiple of root node LP iterations used as total LP iteration limit for obbt (<= 0: no limit )",
2535  &propdata->itlimitfactor, FALSE, DEFAULT_ITLIMITFACTOR, SCIP_REAL_MIN, SCIP_REAL_MAX, NULL, NULL) );
2536 
2537  SCIP_CALL( SCIPaddLongintParam(scip, "propagating/" PROP_NAME "/minitlimit",
2538  "minimum LP iteration limit",
2539  &propdata->minitlimit, FALSE, DEFAULT_MINITLIMIT, 0L, SCIP_LONGINT_MAX, NULL, NULL) );
2540 
2541  SCIP_CALL( SCIPaddRealParam(scip, "propagating/" PROP_NAME "/dualfeastol",
2542  "feasibility tolerance for reduced costs used in obbt; this value is used if SCIP's dual feastol is greater",
2543  &propdata->dualfeastol, FALSE, DEFAULT_DUALFEASTOL, 0.0, SCIP_REAL_MAX, NULL, NULL) );
2544 
2545  SCIP_CALL( SCIPaddRealParam(scip, "propagating/" PROP_NAME "/conditionlimit",
2546  "maximum condition limit used in LP solver (-1.0: no limit)",
2547  &propdata->conditionlimit, FALSE, DEFAULT_CONDITIONLIMIT, -1.0, SCIP_REAL_MAX, NULL, NULL) );
2548 
2549  SCIP_CALL( SCIPaddRealParam(scip, "propagating/" PROP_NAME "/boundstreps",
2550  "minimal relative improve for strengthening bounds",
2551  &propdata->boundstreps, FALSE, DEFAULT_BOUNDSTREPS, 0.0, 1.0, NULL, NULL) );
2552 
2553  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/onlynonconvexvars",
2554  "only apply obbt on non-convex variables",
2555  &propdata->onlynonconvexvars, TRUE, DEFAULT_ONLYNONCONVEXVARS, NULL, NULL) );
2556 
2557  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/tightintboundsprobing",
2558  "should integral bounds be tightened during the probing mode?",
2559  &propdata->tightintboundsprobing, TRUE, DEFAULT_TIGHTINTBOUNDSPROBING, NULL, NULL) );
2560 
2561  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/tightcontboundsprobing",
2562  "should continuous bounds be tightened during the probing mode?",
2563  &propdata->tightcontboundsprobing, TRUE, DEFAULT_TIGHTCONTBOUNDSPROBING, NULL, NULL) );
2564 
2565  SCIP_CALL( SCIPaddIntParam(scip, "propagating/" PROP_NAME "/orderingalgo",
2566  "select the type of ordering algorithm which should be used (0: no special ordering, 1: greedy, 2: greedy reverse)",
2567  &propdata->orderingalgo, TRUE, DEFAULT_ORDERINGALGO, 0, 2, NULL, NULL) );
2568 
2569  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/separatesol",
2570  "should the obbt LP solution be separated?",
2571  &propdata->separatesol, TRUE, DEFAULT_SEPARATESOL, NULL, NULL) );
2572 
2573  SCIP_CALL( SCIPaddIntParam(scip, "propagating/" PROP_NAME "/sepaminiter",
2574  "minimum number of iteration spend to separate an obbt LP solution",
2575  &propdata->sepaminiter, TRUE, DEFAULT_SEPAMINITER, 0, INT_MAX, NULL, NULL) );
2576 
2577  SCIP_CALL( SCIPaddIntParam(scip, "propagating/" PROP_NAME "/sepamaxiter",
2578  "maximum number of iteration spend to separate an obbt LP solution",
2579  &propdata->sepamaxiter, TRUE, DEFAULT_SEPAMAXITER, 0, INT_MAX, NULL, NULL) );
2580 
2581  SCIP_CALL( SCIPaddIntParam(scip, "propagating/" PROP_NAME "/propagatefreq",
2582  "trigger a propagation round after that many bound tightenings (0: no propagation)",
2583  &propdata->propagatefreq, TRUE, DEFAULT_PROPAGATEFREQ, 0, INT_MAX, NULL, NULL) );
2584 
2585  return SCIP_OKAY;
2586 }
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:1943
SCIP_RETCODE SCIPsetPropExitsol(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPEXITSOL((*propexitsol)))
Definition: scip.c:6994
#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:41180
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:32398
#define PROP_NAME
Definition: prop_obbt.c:49
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:41293
#define PROP_FREQ
Definition: prop_obbt.c:53
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:10735
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:5847
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16341
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:41256
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16521
enum SCIP_BaseStat SCIP_BASESTAT
Definition: type_lpi.h:84
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1220
#define DEFAULT_BOUNDSTREPS
Definition: prop_obbt.c:71
SCIP_Longint SCIPgetNRootLPIterations(SCIP *scip)
Definition: scip.c:37082
#define infty2infty(infty1, infty2, val)
Definition: prop_obbt.c:109
SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
Definition: scip.c:37064
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:10690
#define SCIP_MAXSTRLEN
Definition: def.h:198
#define DEFAULT_SEPAMAXITER
Definition: prop_obbt.c:99
#define NULL
Definition: lpi_spx.cpp:130
static SCIP_DECL_PROPEXITSOL(propExitsolObbt)
Definition: prop_obbt.c:2423
#define DEFAULT_ITLIMITFACTOR
Definition: prop_obbt.c:75
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17011
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4262
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1125
SCIP_RETCODE SCIPapplyCutsProbing(SCIP *scip, SCIP_Bool *cutoff)
Definition: scip.c:32490
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:16965
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
int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4326
static int nextBound(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_Bool convexphase)
Definition: prop_obbt.c:1311
SCIP_RETCODE SCIPpropagateProbing(SCIP *scip, int maxproprounds, SCIP_Bool *cutoff, SCIP_Longint *ndomredsfound)
Definition: scip.c:32162
#define FALSE
Definition: def.h:53
#define DEFAULT_SEPAMINITER
Definition: prop_obbt.c:98
SCIP_Real SCIPdualfeastol(SCIP *scip)
Definition: scip.c:40748
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:8169
#define DEFAULT_APPLY_TRIVIALFITLERING
Definition: prop_obbt.c:65
#define TRUE
Definition: def.h:52
#define SCIPdebug(x)
Definition: pub_message.h:74
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
#define SCIPstatisticMessage
Definition: pub_message.h:104
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:4078
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:38147
SCIP_PROP * SCIPfindProp(SCIP *scip, const char *name)
Definition: scip.c:7092
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:26426
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:3570
#define SCIPdebugMessage
Definition: pub_message.h:77
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20414
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:16803
#define GENVBOUND_PROP_NAME
Definition: prop_obbt.c:90
#define SCIP_LONGINT_MAX
Definition: def.h:110
enum SCIP_LPSolStat SCIP_LPSOLSTAT
Definition: type_lp.h:42
SCIP_Real SCIPgetLPObjval(SCIP *scip)
Definition: scip.c:26469
SCIP_Bool SCIPallColsInLP(SCIP *scip)
Definition: scip.c:26816
SCIP_Bool SCIPisLbBetter(SCIP *scip, SCIP_Real newlb, SCIP_Real oldlb, SCIP_Real oldub)
Definition: scip.c:41863
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:3516
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:27645
static unsigned int getScore(SCIP *scip, BOUND *bound, int nlcount, int maxnlcount)
Definition: prop_obbt.c:1900
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16460
SCIP_RETCODE SCIPchgDualfeastol(SCIP *scip, SCIP_Real dualfeastol)
Definition: scip.c:40835
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:3542
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16532
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:18673
SCIP_Real coef
Definition: type_expr.h:102
#define DEFAULT_FILTERING_NORM
Definition: prop_obbt.c:59
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41193
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:2485
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:41317
#define SCIPallocMemory(scip, ptr)
Definition: scip.h:20355
SCIP_PROPDATA * SCIPpropGetData(SCIP_PROP *prop)
Definition: prop.c:735
static SCIP_Bool includeVarGenVBound(SCIP *scip, SCIP_VAR *var)
Definition: prop_obbt.c:368
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:20426
static SCIP_DECL_PROPRESPROP(propRespropObbt)
Definition: prop_obbt.c:2414
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:28394
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41515
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:19125
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:41366
constraint handler for quadratic constraints
#define DEFAULT_GENVBDSDURINGSEPA
Definition: prop_obbt.c:100
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:16669
#define REALABS(x)
Definition: def.h:148
int SCIPexprtreeGetNVars(SCIP_EXPRTREE *tree)
Definition: expr.c:8452
static SCIP_Bool varIsInteresting(SCIP *scip, SCIP_VAR *var, int nlcount)
Definition: prop_obbt.c:2155
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:41245
#define SCIP_CALL(x)
Definition: def.h:263
#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:2013
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip.c:31741
unsigned int score
Definition: prop_obbt.c:121
static int getIterationsLeft(SCIP *scip, SCIP_Longint nolditerations, SCIP_Longint itlimit)
Definition: prop_obbt.c:395
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:41219
#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:20259
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17021
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:7075
#define SCIP_Bool
Definition: def.h:50
SCIP_RETCODE SCIPsetPropFree(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPFREE((*propfree)))
Definition: scip.c:6930
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:6877
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:32450
optimization-based bound tightening propagator
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip.h:20427
SCIP_RETCODE SCIPcacheRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:27798
#define MAX(x, y)
Definition: tclique_def.h:75
methods for debugging
SCIP_Bool SCIPallowObjProp(SCIP *scip)
Definition: scip.c:23080
#define DEFAULT_CREATE_GENVBOUNDS
Definition: prop_obbt.c:58
static SCIP_DECL_PROPFREE(propFreeObbt)
Definition: prop_obbt.c:2462
SCIP_RETCODE SCIPgetNlRowQuadratic(SCIP *scip, SCIP_CONS *cons, SCIP_NLROW **nlrow)
#define SCIPfreeMemoryArray(scip, ptr)
Definition: scip.h:20373
SCIP_RETCODE SCIPstartProbing(SCIP *scip)
Definition: scip.c:31763
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:31895
SCIP_RETCODE SCIPseparateSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool pretendroot, SCIP_Bool onlydelayed, SCIP_Bool *delayed, SCIP_Bool *cutoff)
Definition: scip.c:31045
#define SCIPallocMemoryArray(scip, ptr, num)
Definition: scip.h:20357
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:17580
SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
Definition: scip.c:36389
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:6978
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:37750
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:17329
#define SCIP_REAL_MAX
Definition: def.h:125
unsigned int found
Definition: prop_obbt.c:123
SCIP_RETCODE SCIPchgVarObjProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip.c:32081
#define SCIP_REAL_MIN
Definition: def.h:126
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16506
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:41378
#define SCIPfreeMemory(scip, ptr)
Definition: scip.h:20371
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:16955
#define PROP_TIMING
Definition: prop_obbt.c:51
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition: lp.c:18934
SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:27821
SCIP_VAR ** SCIPnlrowGetQuadVars(SCIP_NLROW *nlrow)
Definition: nlp.c:3275
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:31962
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41541
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16648
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:124
SCIP_RETCODE SCIPgetNLPVarsNonlinearity(SCIP *scip, int *nlcount)
Definition: scip.c:28505
int SCIPgetNCuts(SCIP *scip)
Definition: scip.c:31095
SCIP_RETCODE SCIPchgVarLbProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:31928
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:20365
struct SCIP_PropData SCIP_PROPDATA
Definition: type_prop.h:38
#define MIN(x, y)
Definition: memory.c:63
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41567
SCIP_RETCODE SCIPgetNlRowNonlinear(SCIP *scip, SCIP_CONS *cons, SCIP_NLROW **nlrow)
#define SCIP_INVALID
Definition: def.h:144
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:9978
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip.c:27725
static SCIP_RETCODE filterBounds(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_Longint itlimit)
Definition: prop_obbt.c:971
#define SCIP_Longint
Definition: def.h:109
#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:2288
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:10609
#define PROP_DELAY
Definition: prop_obbt.c:54
#define PROP_PRIORITY
Definition: prop_obbt.c:52
#define DEFAULT_CONDITIONLIMIT
Definition: prop_obbt.c:70
SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
Definition: scip.c:3766
unsigned int nonconvex
Definition: prop_obbt.c:125
#define DEFAULT_TIGHTINTBOUNDSPROBING
Definition: prop_obbt.c:80
int SCIPgetNNLPVars(SCIP *scip)
Definition: scip.c:28483
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
SCIP_Real SCIPgetVarObjProbing(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:31995
static SCIP_RETCODE initBounds(SCIP *scip, SCIP_PROPDATA *propdata)
Definition: prop_obbt.c:2171
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:41305
static SCIP_DECL_PROPEXEC(propExecObbt)
Definition: prop_obbt.c:2316
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:3598
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:27851
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:36444
SCIP_Bool SCIPisUbBetter(SCIP *scip, SCIP_Real newub, SCIP_Real oldlb, SCIP_Real oldub)
Definition: scip.c:41878
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)