Scippy

SCIP

Solving Constraint Integer Programs

prop_pseudoobj.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2016 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file prop_pseudoobj.c
17  * @brief Pseudo objective propagator
18  * @author Tobias Achterberg
19  * @author Stefan Heinz
20  *
21  * This propagator propagates the objective function using the cutoff bound and the pseudo objective value. The pseudo
22  * objective value can be seen as minimum activity of the linear objective function. Using this, this propagator checks
23  * if variables with non-zero objective coefficients can exceed the cutoff bound. If this is the case the corresponding
24  * bound can be tightened.
25  *
26  * @todo use the complete implication to initialize the objective implication data structure
27  */
28 
29 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
30 
31 #include <assert.h>
32 #include <string.h>
33 
34 #include "scip/prop_pseudoobj.h"
35 
36 
37 #define PROP_NAME "pseudoobj"
38 #define PROP_DESC "pseudo objective function propagator"
39 #define PROP_TIMING SCIP_PROPTIMING_BEFORELP | SCIP_PROPTIMING_AFTERLPLOOP | SCIP_PROPTIMING_DURINGLPLOOP
40 #define PROP_PRIORITY 3000000 /**< propagator priority */
41 #define PROP_FREQ 1 /**< propagator frequency */
42 #define PROP_DELAY FALSE /**< should propagation method be delayed, if other propagators found reductions? */
43 #define PROP_PRESOL_PRIORITY +6000000 /**< priority of the presolving method (>= 0: before, < 0: after constraint handlers); combined with presolvers */
44 #define PROP_PRESOL_MAXROUNDS -1 /**< maximal number of presolving rounds the presolver participates in (-1: no
45  * limit) */
46 #define PROP_PRESOLTIMING SCIP_PRESOLTIMING_FAST /* timing of the presolving method (fast, medium, or exhaustive) */
47 
48 #define EVENTHDLR_NAME "pseudoobj"
49 #define EVENTHDLR_DESC "bound change event handler for pseudo objective function propagator"
50 
51 #define DEFAULT_MINUSELESS 100 /**< minimal number of successive none binary variable propagator whithout a
52  * bound reduction before aborted */
53 #define DEFAULT_MAXVARSFRAC 0.1 /**< maximal fraction of none binary variables with non-zero objective
54  * without a bound reduction before aborted */
55 #define DEFAULT_PROPFULLINROOT TRUE /**< do we want to propagate all non-binary variables if we are propagating the root node? */
56 #define DEFAULT_PROPCUTOFFBOUND TRUE /**< propagate new cutoff bound directly globally */
57 #define DEFAULT_FORCE FALSE /**< should the propagator be forced even if active pricer are present? Note that
58  * can be done if it is known that the pseudo objective activity is given by
59  * the zero bound for all variables which are currently not present in the
60  * problem */
61 #define DEFAULT_MAXNEWVARS 1000 /**< number of variable added after the propagator is reinitialized? */
62 #define DEFAULT_PROPUSEIMPLICS TRUE /**< use implications to strengthen the propagation of binary variable (increasing the objective change)? */
63 #define DEFAULT_RESPROPUSEIMPLICS TRUE /**< use implications to strengthen the resolve propagation of binary variable (increasing the objective change)? */
64 #define DEFAULT_MAXIMPLVARS 50000 /**< maximum number of binary variables the implications are used if turned on (-1: unlimited)? */
65 
66 
67 /*
68  * Data structures
69  */
70 
71 /** implication data structure for objective contributions of a binary variable */
72 struct SCIP_ObjImplics
73 {
74  SCIP_VAR** objvars; /**< variables y in implications y == 0 or y == 1, first we store the
75  * implications by x == 0 and second the implications x == 1 */
76  SCIP_Real maxobjchg; /**< maximum objective contribution if variables x is fixed to zero or one */
77  int nlbimpls; /**< number of all implications result through for x == 0 */
78  int nubimpls; /**< number of all implications result through for x == 1 */
79  int size; /**< size of the objvars array */
80 };
81 typedef struct SCIP_ObjImplics SCIP_OBJIMPLICS; /**< implications in the form x == 0 or x == 1 ==> y == 0 or y == 1 for (x and y binary) */
82 
83 
84 /** propagator data */
85 struct SCIP_PropData
86 {
87  SCIP_EVENTHDLR* eventhdlr; /**< event handler for global bound change events */
88  SCIP_VAR** minactvars; /**< binary variables with non-zero objective contribution w.r.t. minimum activity of the objective function */
89  SCIP_OBJIMPLICS** minactimpls; /**< implication data structure for the binary variables w.r.t. minimum activity */
90  SCIP_VAR** maxactvars; /**< binary variables with non-zero objective contribution w.r.t. maximum activity of the objective function */
91  SCIP_Real* maxactchgs; /**< the maximal potential change of the objective if the binary variable
92  * is fixed to its best bound w.r.t. maximum activity of the objective function */
93  SCIP_VAR** objintvars; /**< none binary variable with non-zero objective coefficient */
94  SCIP_HASHTABLE* addedvars; /**< hash table used during resolving of a bound change (conflict analysis) */
95  SCIP_Real lastlowerbound; /**< last lower bound which was propagated */
96  SCIP_Real cutoffbound; /**< last cutoff bound used for propagation */
97  SCIP_Real glbpseudoobjval; /**< last global pseudo objective used in presolving */
98  SCIP_Real maxvarsfrac; /**< maximal fraction of none binary variables with non-zero objective
99  * without a bound reduction before aborted */
100  SCIP_Real maxpseudoobjact; /**< maximal global pseudo objective activity */
101  int maxpseudoobjactinf; /**< number of coefficients contributing with infinite value to maxpseudoobjact */
102  int nminactvars; /**< number of binary variables with non-zero objective contribution w.r.t. minimum activity of the objective function */
103  int nmaxactvars; /**< number of binary variables with non-zero objective contribution w.r.t. maximum activity of the objective function */
104  int nobjintvars; /**< number of none binary variables with non-zero objective */
105  int minuseless; /**< minimal number of successive none binary variable propagator whithout
106  * a bound reduction before aborted */
107  int lastvarnum; /**< last none binary variable number that was looked at */
108  int glbfirstnonfixed; /**< index of first globally non-fixed binary variable in minactvars array */
109  int maxactfirstnonfixed;/**< index of first globally non-fixed binary variable in maxctvars array */
110  int firstnonfixed; /**< index of first locally non-fixed binary variable in minactvars array */
111  int nnewvars; /**< counter for counting number of new variables added */
112  int maxnewvars; /**< number of variable added after the propagator is reinitialized? */
113  int maximplvars; /**< maximum number of binary variables the implications are used if turned on (-1: unlimited)? */
114  SCIP_Bool glbpropagated; /**< are global domains propagated */
115  SCIP_Bool propfullinroot; /**< do we want to propagate all non-binary variables if we are propagating the root node */
116  SCIP_Bool propcutoffbound; /**< propagate new cutoff bound directly globally */
117  SCIP_Bool force; /**< should the propagator be forced even if active pricer are present? */
118  SCIP_Bool catchvaradded; /**< do we catch the variable added event? */
119  SCIP_Bool propuseimplics; /**< use implications to strengthen the propagation of binary variable (increasing the objective change)? */
120  SCIP_Bool respropuseimplics; /**< use implications to strengthen the resolve propagation of binary variable (increasing the objective change)? */
121  SCIP_Bool initialized; /**< is propagator data structure initialized */
122 };
123 
124 /*
125  * Debug methods
126  */
127 
128 #ifndef NDEBUG
129 /** check that the implications are applied for a globally fixed variable */
130 static
132  SCIP* scip, /**< SCIP data structure */
133  SCIP_VAR* var /**< variable to check the implications */
134  )
135 {
136  SCIP_VAR** vars;
137  SCIP_Real* bounds;
138  SCIP_BOUNDTYPE* boundtypes;
139  SCIP_Bool varfixing;
140  int nvars;
141  int v;
142 
143  /* check that the given variable is locally or globally fixed */
144  assert(SCIPvarGetLbLocal(var) > 0.5 || SCIPvarGetUbLocal(var) < 0.5);
145 
146  /* get fixed value */
147  varfixing = SCIPvarGetLbGlobal(var) > 0.5;
148 
149  vars = SCIPvarGetImplVars(var, varfixing);
150  nvars = SCIPvarGetNImpls(var, varfixing);
151  bounds = SCIPvarGetImplBounds(var, varfixing);
152  boundtypes = SCIPvarGetImplTypes(var, varfixing);
153 
154  /* check that each implication was applied */
155  for( v = 0; v < nvars; ++v )
156  {
157  if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER )
158  {
159  SCIP_Real lb;
160 
161  lb = SCIPvarGetLbGlobal(vars[v]);
162  assert(SCIPisLE(scip, lb, bounds[v]));
163  }
164  else
165  {
166  SCIP_Real ub;
167 
168  assert(boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
169 
170  ub = SCIPvarGetLbGlobal(vars[v]);
171  assert(SCIPisGE(scip, ub, bounds[v]));
172  }
173  }
174 }
175 
176 /** check if the global fixed indices are correct */
177 static
179  SCIP* scip, /**< SCIP data structure */
180  SCIP_PROPDATA* propdata /**< propagator data */
181  )
182 {
183  SCIP_VAR* var;
184  int v;
185 
186  for( v = 0; v < propdata->glbfirstnonfixed; ++v )
187  {
188  var = propdata->minactvars[v];
189  assert(var != NULL);
190 
191  assert(SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5);
192  }
193 
194  for( v = 0; v < propdata->maxactfirstnonfixed; ++v )
195  {
196  var = propdata->maxactvars[v];
197  assert(var != NULL);
198 
199  assert(SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5);
200  }
201 }
202 #endif /* end of debug methods */
203 
204 /*
205  * Comparer
206  */
207 
208 /** compares objective implications w.r.t. their maximum contribution */
209 static
210 SCIP_DECL_SORTPTRCOMP(objimplicsComp)
211 {
212  SCIP_OBJIMPLICS* objimplics1;
213  SCIP_OBJIMPLICS* objimplics2;
214 
215  objimplics1 = (SCIP_OBJIMPLICS*)elem1;
216  objimplics2 = (SCIP_OBJIMPLICS*)elem2;
217 
218  if( objimplics1->maxobjchg > objimplics2->maxobjchg )
219  return +1;
220 
221  if( objimplics1->maxobjchg < objimplics2->maxobjchg )
222  return -1;
223 
224  return 0;
225 }
226 
227 /** compare variables w.r.t.
228  * (i) the absolute value the objective coefficient;
229  * (ii) the locks which indicate most effect -- for the variables with a positive (negative) objective coefficient the
230  * down (up) lock is used since this lock indicates that tightened of the upper (lower) bound will triegger
231  * further domain propagations;
232  * (iii) the other locks;
233  * (iv) variable problem index;
234  */
235 static
236 SCIP_DECL_SORTPTRCOMP(varCompObj)
237 {
238  SCIP_VAR* var1;
239  SCIP_VAR* var2;
240  int locks1;
241  int locks2;
243  var1 = (SCIP_VAR*)elem1;
244  var2 = (SCIP_VAR*)elem2;
245 
246  assert(SCIPvarGetObj(var1) != 0.0);
247  assert(SCIPvarGetObj(var2) != 0.0);
248 
249  /* first criteria is the absolute value of objective coefficient */
250  if( REALABS(SCIPvarGetObj(var1)) < REALABS(SCIPvarGetObj(var2)) )
251  return -1;
252  else if( REALABS(SCIPvarGetObj(var1)) > REALABS(SCIPvarGetObj(var2)) )
253  return +1;
254 
255  /* second criteria the locks which indicate most effect */
256  if( SCIPvarGetObj(var1) > 0.0 )
257  locks1 = SCIPvarGetNLocksDown(var1);
258  else
259  locks1 = SCIPvarGetNLocksUp(var1);
260 
261  if( SCIPvarGetObj(var2) > 0.0 )
262  locks2 = SCIPvarGetNLocksDown(var2);
263  else
264  locks2 = SCIPvarGetNLocksUp(var2);
265 
266  if( locks1 < locks2 )
267  return -1;
268  if( locks1 > locks2 )
269  return 1;
270 
271  /* third criteria the other locks */
272  if( SCIPvarGetObj(var1) > 0.0 )
273  locks1 = SCIPvarGetNLocksUp(var1);
274  else
275  locks1 = SCIPvarGetNLocksDown(var1);
276 
277  if( SCIPvarGetObj(var2) > 0.0 )
278  locks2 = SCIPvarGetNLocksUp(var2);
279  else
280  locks2 = SCIPvarGetNLocksDown(var2);
281 
282  if( locks1 < locks2 )
283  return -1;
284  if( locks1 > locks2 )
285  return 1;
286 
287  /* forth criteria use the problem index */
288  return SCIPvarCompare(var1, var2);
289 }
290 
291 /** hash key retrieval function for cliques*/
292 static
293 SCIP_DECL_HASHGETKEY(cliqueGetHashkey)
294 { /*lint --e{715}*/
295  return elem;
296 }
297 
298 /** returns TRUE iff the cliques are equal */
299 static
300 SCIP_DECL_HASHKEYEQ(cliqueIsHashkeyEq)
301 { /*lint --e{715}*/
302  if( key1 == key2 )
303  return TRUE;
304  return FALSE;
305 }
307 /** returns the hash value of the key */
308 static
309 SCIP_DECL_HASHKEYVAL(cliqueGetHashkeyVal)
310 { /*lint --e{715}*/
311  assert( SCIPcliqueGetId((SCIP_CLIQUE*) key) >= 0 );
312  return (unsigned int) SCIPcliqueGetId((SCIP_CLIQUE*) key);
313 }
314 
315 /*
316  * methods for SCIP_OBJIMPLICS data structure
317  */
318 
319 /** creates an objective implication data structure, fixes (globally) variables which are implied by lower and upper
320  * bound fixing, and clears the collected arrays for lower and upper bound
321  */
322 static
324  SCIP* scip, /**< SCIP data structure */
325  SCIP_OBJIMPLICS** objimplics, /**< pointer to objective implication data structure */
326  SCIP_VAR** objvars, /**< objective contributor variables, or NULL */
327  SCIP_HASHMAP* binobjvarmap, /**< hash map mapping binary variables with none-zero objective to position in collected variables arrays, or NULL */
328  SCIP_Bool* collectedlbvars, /**< temporary buffer to mark collected variables for lower bound fixing, or NULL */
329  SCIP_Bool* collectedubvars, /**< temporary buffer to mark collected variables for upper bound fixing, or NULL */
330  SCIP_Real maxlbobjchg, /**< maximum objective contributor if variables id fixed to zero */
331  SCIP_Real maxubobjchg, /**< maximum objective contributor if variables id fixed to one */
332  int nlbimpls, /**< number of variables contributing to to lower bound fix */
333  int nubimpls /**< number of variables contributing to to upper bound fix */
334  )
335 
336 {
337  assert(scip != NULL);
338  assert(objimplics != NULL);
339  assert(!SCIPisNegative(scip, maxlbobjchg));
340  assert(!SCIPisNegative(scip, maxubobjchg));
341 
342  /* allocate block memory for the implication data structure */
343  SCIP_CALL( SCIPallocBlockMemory(scip, objimplics) );
344 
345  if( nlbimpls + nubimpls == 0 )
346  {
347  assert(nlbimpls == 0);
348  assert(nubimpls == 0);
349  (*objimplics)->objvars = NULL;
350  (*objimplics)->maxobjchg = 0.0;
351  (*objimplics)->nlbimpls = 0;
352  (*objimplics)->nubimpls = 0;
353  (*objimplics)->size = 0;
354  }
355  else
356  {
357  SCIP_VAR* var;
358  int nvars;
359  int pos;
360  int v;
361 
362  assert(objvars != NULL);
363  assert(binobjvarmap != NULL);
364  assert(collectedlbvars != NULL);
365  assert(collectedubvars != NULL);
366 
367  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*objimplics)->objvars, nlbimpls + nubimpls) );
368  (*objimplics)->size = nlbimpls + nubimpls;
369 
370  nvars = 0;
371 
372  for( v = 0; v < nlbimpls; ++v )
373  {
374  var = objvars[v];
375  assert(var != NULL);
376  assert(!SCIPisZero(scip, SCIPvarGetObj(var)));
377 
378  assert(SCIPhashmapExists(binobjvarmap, var));
379  pos = (int)(size_t)SCIPhashmapGetImage(binobjvarmap, (void*)var);
380  assert(pos > 0);
381  assert(collectedlbvars[pos]);
382 
383  if( collectedubvars[pos] )
384  {
385  SCIP_Bool infeasible;
386  SCIP_Bool tightened;
387 
389  {
390  SCIPdebugMessage("fix variables <%s> to 1.0 due to implications\n", SCIPvarGetName(var));
391 
392  SCIP_CALL( SCIPtightenVarLbGlobal(scip, var, 1.0, FALSE, &infeasible, &tightened) );
393  maxlbobjchg -= SCIPvarGetObj(var);
394  }
395  else
396  {
397  SCIPdebugMessage("fix variables <%s> to 0.0 due to implications\n", SCIPvarGetName(var));
398 
399  SCIP_CALL( SCIPtightenVarUbGlobal(scip, var, 0.0, FALSE, &infeasible, &tightened) );
400  maxlbobjchg += SCIPvarGetObj(var);
401  }
402  assert(!infeasible);
403  assert(tightened);
404  }
405  else
406  {
407  (*objimplics)->objvars[nvars] = var;
408  nvars++;
409  }
410  collectedlbvars[pos] = FALSE;
411  }
412  (*objimplics)->nlbimpls = nvars;
413 
414  for( v = 0; v < nubimpls; ++v )
415  {
416  var = objvars[nlbimpls + v];
417  assert(var != NULL);
418  assert(!SCIPisZero(scip, SCIPvarGetObj(var)));
419 
420  assert(SCIPhashmapExists(binobjvarmap, var));
421  pos = (int)(size_t)SCIPhashmapGetImage(binobjvarmap, (void*)var);
422  assert(pos > 0);
423  assert(collectedubvars[pos]);
424 
425  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
426  {
428  maxubobjchg -= SCIPvarGetObj(var);
429  else
430  maxubobjchg += SCIPvarGetObj(var);
431  }
432  else
433  {
434  (*objimplics)->objvars[nvars] = var;
435  nvars++;
436  }
437  collectedubvars[pos] = FALSE;
438  }
439  (*objimplics)->nubimpls = nvars - (*objimplics)->nlbimpls;
440 
441  /* capture the variables */
442  for( v = 0; v < nvars; ++v )
443  {
444  assert(SCIPvarIsBinary((*objimplics)->objvars[v]));
445  assert(!SCIPisZero(scip, SCIPvarGetObj((*objimplics)->objvars[v])));
446  SCIP_CALL( SCIPcaptureVar(scip, (*objimplics)->objvars[v]) );
447  }
448  }
449 
450  (*objimplics)->maxobjchg = MAX(maxlbobjchg, maxubobjchg);
451 
452  return SCIP_OKAY;
453 }
454 
455 /** frees an objective implication data structure */
456 static
458  SCIP* scip, /**< SCIP data structure */
459  SCIP_OBJIMPLICS** objimplics /**< pointer to objective implication data structure */
460  )
461 {
462  int v;
464  assert(scip != NULL);
465  assert(objimplics != NULL);
466  assert(*objimplics != NULL);
467 
468  /* release all variables */
469  for( v = 0; v < (*objimplics)->nlbimpls + (*objimplics)->nubimpls; ++v )
470  {
471  SCIP_CALL( SCIPreleaseVar(scip, &(*objimplics)->objvars[v]) );
472  }
473 
474  /* free objective variable array */
475  SCIPfreeBlockMemoryArrayNull(scip, &(*objimplics)->objvars, (*objimplics)->size);
476 
477  /* frees block memory for the implication data structure */
478  SCIPfreeBlockMemory(scip, objimplics);
479 
480  return SCIP_OKAY;
481 }
482 
483 /** remove the given variable at the given pos from the objective implication data structure */
484 static
486  SCIP* scip, /**< SCIP data structure */
487  SCIP_OBJIMPLICS* objimplics, /**< objective implication data structure */
488  int pos /**< position */
489  )
490 {
491  assert(0 <= pos);
492  assert(pos < objimplics->nlbimpls + objimplics->nubimpls);
493 
494  SCIPdebugMessage("variable <%s> ", SCIPvarGetName(objimplics->objvars[pos]));
495 
496  /* release variable */
497  SCIP_CALL( SCIPreleaseVar(scip, &objimplics->objvars[pos]) );
498 
499  /* copy last lower bound variable to that position */
500  if( pos < objimplics->nlbimpls )
501  {
502  objimplics->nlbimpls--;
503  assert(objimplics->nlbimpls >= 0);
504 
505  /* copy last lower bound variable to that position */
506  objimplics->objvars[pos] = objimplics->objvars[objimplics->nlbimpls];
507 
508  /* copy last upper bound variable to open slot */
509  objimplics->objvars[objimplics->nlbimpls] = objimplics->objvars[objimplics->nlbimpls + objimplics->nubimpls];
510 
511  SCIPdebugPrintf("remove lower bound implication\n");
512  }
513  else
514  {
515  objimplics->nubimpls--;
516  assert(objimplics->nubimpls >= 0);
517 
518  /* copy last upper bound variable to that position */
519  objimplics->objvars[pos] = objimplics->objvars[objimplics->nlbimpls + objimplics->nubimpls];
520 
521  SCIPdebugPrintf("remove upper bound implication\n");
522  }
523 
524  return SCIP_OKAY;
525 }
526 
527 /*
528  * Local methods
529  */
530 
531 
532 /** catch bound change events if the variable has a non-zero objective coefficient to check if the maximum activity of
533  * the objective function changed
534  */
535 static
537  SCIP* scip, /**< SCIP data structure */
538  SCIP_PROPDATA* propdata, /**< propagator data */
539  SCIP_EVENTHDLR* eventhdlr, /**< event handler for global bound change events */
540  SCIP_VAR* var /**< variable for which the event should be dropped */
541  )
542 {
543  SCIP_Real objval;
544 
545  assert(propdata != NULL);
546  assert(eventhdlr != NULL);
547 
548  objval = SCIPvarGetObj(var);
549 
550  if( !SCIPisZero(scip, objval) )
551  {
552  if( objval > 0.0 )
553  {
554  SCIP_CALL( SCIPcatchVarEvent(scip, var, SCIP_EVENTTYPE_GUBCHANGED, eventhdlr, (SCIP_EVENTDATA*)propdata, NULL) );
555  }
556  else
557  {
558  SCIP_CALL( SCIPcatchVarEvent(scip, var, SCIP_EVENTTYPE_GLBCHANGED, eventhdlr, (SCIP_EVENTDATA*)propdata, NULL) );
559  }
560  }
561 
562  return SCIP_OKAY;
563 }
564 
565 /** drop variable event w.r.t. objective coefficient */
566 static
568  SCIP* scip, /**< SCIP data structure */
569  SCIP_PROPDATA* propdata, /**< propagator data */
570  SCIP_EVENTHDLR* eventhdlr, /**< event handler for global bound change events */
571  SCIP_VAR* var /**< variable for which the event should be dropped */
572  )
573 {
574  SCIP_Real objval;
575 
576  assert(propdata != NULL);
577  assert(eventhdlr != NULL);
578 
579  objval = SCIPvarGetObj(var);
580 
581  /* drop bound change event */
582  if( !SCIPisZero(scip, objval) )
583  {
584  if( objval > 0.0 )
585  {
586  SCIP_CALL( SCIPdropVarEvent(scip, var, SCIP_EVENTTYPE_GUBCHANGED, eventhdlr, (SCIP_EVENTDATA*)propdata, -1) );
587  }
588  else
589  {
590  SCIP_CALL( SCIPdropVarEvent(scip, var, SCIP_EVENTTYPE_GLBCHANGED, eventhdlr, (SCIP_EVENTDATA*)propdata, -1) );
591  }
592  }
593  return SCIP_OKAY;
594 }
595 
596 /** drop all variable events */
597 static
599  SCIP* scip, /**< SCIP data structure */
600  SCIP_PROPDATA* propdata /**< propagator data */
601  )
602 {
603  SCIP_EVENTHDLR* eventhdlr;
604  SCIP_VAR* var;
605  int k;
606 
607  assert(scip != NULL);
608  assert(propdata != NULL);
609 
610  eventhdlr = propdata->eventhdlr;
611  assert(eventhdlr != NULL);
612 
613  /* drop all events and release variables */
614  for( k = 0; k < propdata->nminactvars; ++k )
615  {
616  var = propdata->minactvars[k];
617  assert(var != NULL);
618  assert(SCIPvarIsBinary(var));
619 
620  /* drop bound relax event which is caught for all binary variables which are used for propagation the objective
621  * function via the minimum activity of the objective function
622  */
623  SCIP_CALL( SCIPdropVarEvent(scip, var, SCIP_EVENTTYPE_BOUNDRELAXED, eventhdlr, (SCIP_EVENTDATA*)propdata, -1) );
624 
625  /* release variable */
626  SCIP_CALL( SCIPreleaseVar(scip, &var) );
627  }
628 
629  /* release variables */
630  for( k = 0; k < propdata->nmaxactvars; ++k )
631  {
632  var = propdata->maxactvars[k];
633  assert(var != NULL);
634  assert(SCIPvarIsBinary(var));
635 
636  /* drop events which are needed for evaluating the maximum activity of the objective function */
637  SCIP_CALL( dropObjEvent(scip, propdata, eventhdlr, var) );
638 
639  /* release variable */
640  SCIP_CALL( SCIPreleaseVar(scip, &var) );
641  }
642 
643  /* drop all events and release variables */
644  for( k = 0; k < propdata->nobjintvars; ++k )
645  {
646  var = propdata->objintvars[k];
647  assert(var != NULL);
648 
649  /* drop events which are needed for evaluating the maximum activity of the objective function */
650  SCIP_CALL( dropObjEvent(scip, propdata, eventhdlr, var) );
651 
652  /* release variable */
653  SCIP_CALL( SCIPreleaseVar(scip, &var) );
654  }
655 
656  return SCIP_OKAY;
657 }
658 
659 /** reset propagatore data structure */
660 static
661 void propdataReset(
662  SCIP* scip, /**< SCIP data structure */
663  SCIP_PROPDATA* propdata /**< propagator data */
664  )
665 {
666  propdata->minactvars = NULL;
667  propdata->minactimpls = NULL;
668  propdata->maxactvars = NULL;
669  propdata->maxactchgs = NULL;
670  propdata->objintvars = NULL;
671  propdata->nminactvars = 0;
672  propdata->nmaxactvars = 0;
673  propdata->nobjintvars = 0;
674  propdata->maxpseudoobjact = SCIP_INVALID;
675  propdata->maxpseudoobjactinf = 0;
676  propdata->lastvarnum = -1;
677  propdata->glbpropagated = FALSE;
678  propdata->cutoffbound = SCIP_INVALID;
679  propdata->lastlowerbound = -SCIP_INVALID;
680  propdata->glbpseudoobjval = -SCIP_INVALID;
681  propdata->glbfirstnonfixed = 0;
682  propdata->maxactfirstnonfixed = 0;
683  propdata->firstnonfixed = 0;
684  propdata->nnewvars = 0;
685  propdata->catchvaradded = FALSE;
686  propdata->initialized = FALSE;
687 }
688 
689 /** free propagator data */
690 static
692  SCIP* scip, /**< SCIP data structure */
693  SCIP_PROPDATA* propdata /**< propagator data */
694  )
695 {
696  int v;
698  if( !propdata->initialized )
699  return SCIP_OKAY;
700 
701  if( propdata->addedvars != NULL )
702  SCIPhashtableFree(&propdata->addedvars);
703 
704  /* drop events for the variables */
705  SCIP_CALL( dropVarEvents(scip, propdata) );
706 
707  for( v = 0; v < propdata->nminactvars; ++v )
708  {
709  SCIP_CALL( objimplicsFree(scip, &(propdata->minactimpls[v])) );
710  }
711 
712  /* free memory for non-zero objective variables */
713  SCIPfreeMemoryArrayNull(scip, &propdata->minactvars);
714  SCIPfreeMemoryArrayNull(scip, &propdata->minactimpls);
715  SCIPfreeMemoryArrayNull(scip, &propdata->maxactvars);
716  SCIPfreeMemoryArrayNull(scip, &propdata->maxactchgs);
717  SCIPfreeMemoryArrayNull(scip, &propdata->objintvars);
718 
719  /* reset propagator data structure */
720  propdataReset(scip, propdata);
721 
722  return SCIP_OKAY;
723 }
724 
725 /** returns the objective change for the given binary variable */
726 static
728  SCIP_VAR* var, /**< variable to get objective change for */
729  SCIP_BOUNDTYPE boundtype, /**< bound type to consider */
730  SCIP_BOUNDTYPE bound /**< fixing bound */
731  )
732 {
733  assert(SCIPvarIsBinary(var));
734  assert((int)SCIP_BOUNDTYPE_LOWER == 0);
735  assert((int)SCIP_BOUNDTYPE_UPPER == 1);
736 
737  /* collect contribution of variable itself */
738  return (SCIP_Real)((int)bound - (int)(boundtype == SCIP_BOUNDTYPE_UPPER)) * SCIPvarGetObj(var);
739 }
740 
741 /** returns the objective change provided by the implication variable by fixing it to the given bound
742  * w.r.t. minimum activity of the objective function; additionally it collects all contributors for that objective
743  * change;
744  */
745 static
747  SCIP* scip, /**< SCIP data structure */
748  SCIP_VAR* var, /**< variable to computes the objective contribution */
749  SCIP_HASHMAP* binobjvarmap, /**< hash map mapping binary variables with none-zero objective to position in collected variables arrays */
750  SCIP_Bool* collectedvars, /**< temporary buffer to mark collected variables */
751  int nbinobjvars, /**< number of binary variables with non-zero objective coefficient */
752  SCIP_VAR** contributors, /**< array to store the contributors */
753  int* ncontributors /**< pointer to store number of contributor to the objective contribution */
754  )
755 {
756  SCIP_Real objval;
757  int pos;
758 
759  assert(scip != NULL);
760  assert(var != NULL);
761  assert(binobjvarmap != NULL);
762  assert(collectedvars != NULL);
763  assert(contributors != NULL);
764  assert(ncontributors != NULL);
765 
766  /* ignore global fixed variables */
767  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
768  return 0.0;
769 
770  objval = SCIPvarGetObj(var);
771 
772  /* ignore variables with zero objective coefficient */
773  if( SCIPisZero(scip, objval) )
774  return 0.0;
775 
776  assert(SCIPhashmapExists(binobjvarmap, var));
777  pos = (int)(size_t)SCIPhashmapGetImage(binobjvarmap, var);
778  assert(pos > 0);
779 
780  /* check if the variables was already collected through other cliques */
781  if( collectedvars[pos] )
782  return 0.0;
783 
784  /* collect variable */
785  assert(*ncontributors < nbinobjvars);
786  contributors[*ncontributors] = var;
787  (*ncontributors)++;
788 
789  /* mark variable to be collected */
790  collectedvars[pos] = TRUE;
791 
792  /* return the absolute value of the objective coefficient as constriction */
793  return REALABS(objval);
794 }
795 
796 #define MAX_CLIQUELENGTH 50
797 /** returns the objective change provided by the implications of the given variable by fixing it to the given bound
798  * w.r.t. minimum activity of the objective function; additionally it collects all contributors for that objective
799  * change;
800  *
801  * Let I(0) and I(1) be all implications of the given variable which follow by fixing it to given bound and evaluate to
802  * fixing the implication variable to zero (I(0)) or one (I(1)), respectively. The objective change provided by the
803  * implications are:
804  *
805  * \f[
806  * \displaystyle
807  * sum_{x\in I(1)} (1 - \mbox{bestbound}(x)) \cdot \mbox{objval}(x) - sum_{x\in I(1)} \mbox{bestbound}(x) \cdot \mbox{objval}(x)
808  * =
809  * sum_{x\in I(0) \cup I(1)} (\mbox{impliedbound}(x) - \mbox{bestbound}(x)) \cdot \mbox{objval}(x)
810  * \f]
811  */
812 static
814  SCIP* scip, /**< SCIP data structure */
815  SCIP_VAR* var, /**< variable to computes the objective contribution */
816  SCIP_BOUNDTYPE bound, /**< bound to check for */
817  SCIP_HASHMAP* binobjvarmap, /**< hash map mapping binary variables with none-zero objective to position in collected variables arrays */
818  SCIP_Bool* collectedvars, /**< temporary buffer to mark collected variables */
819  int nbinobjvars, /**< number of binary variables with non-zero objective coefficient */
820  SCIP_VAR** contributors, /**< array to store the contributors */
821  SCIP_HASHTABLE* uselesscliques, /**< hash table to store useless cliques, or NULL */
822  int* ncontributors, /**< pointer to store number of contributor to the objective contribution */
823  SCIP_Real* objchg /**< pointer to store the objective change */
824  )
825 {
826  SCIP_CLIQUE** cliques;
827  SCIP_CLIQUE* clique;
828  SCIP_VAR** vars;
829  SCIP_VAR* implvar;
830  SCIP_Bool* values;
831  SCIP_Bool varfixing;
832  int nbinvars;
833  int ncliques;
834  int c;
835  int v;
836 
837  assert(SCIPvarIsBinary(var));
838  assert(SCIPvarGetLbGlobal(var) < 0.5);
839  assert(SCIPvarGetUbGlobal(var) > 0.5);
840  assert(bound == SCIP_BOUNDTYPE_LOWER || bound == SCIP_BOUNDTYPE_UPPER);
841  assert(objchg != NULL);
842  assert(contributors != NULL);
843  assert(ncontributors != NULL);
844  assert(*ncontributors == 0);
845 
847  assert((SCIP_Bool)SCIP_BOUNDTYPE_UPPER == TRUE);
848  varfixing = (SCIP_Bool)bound;
849 
850  cliques = SCIPvarGetCliques(var, varfixing);
851  ncliques = SCIPvarGetNCliques(var, varfixing);
852 
853 #ifndef NDEBUG
854  /* check that the marker array is reset */
855  for( c = 0; c < nbinobjvars; ++c )
856  assert(collectedvars[c] == FALSE);
857 #endif
858 
859  /* collect all implication which are given via cliques */
860  for( c = 0; c < ncliques; ++c )
861  {
862  SCIP_Bool useless;
863 
864  assert(uselesscliques != NULL);
865 
866  clique = cliques[c];
867  assert(clique != NULL);
868 
869  /* check if the clique was previously detected to be useless with respect to minimum activity */
870  if( SCIPhashtableExists(uselesscliques, (void*)clique) )
871  continue;
872 
873  nbinvars = SCIPcliqueGetNVars(clique);
874 
875  if( nbinvars > MAX_CLIQUELENGTH )
876  {
877  SCIP_CALL( SCIPhashtableInsert(uselesscliques, (void*)clique) );
878  continue;
879  }
880 
881  vars = SCIPcliqueGetVars(clique);
882  values = SCIPcliqueGetValues(clique);
883  useless = TRUE;
884 
885  for( v = 0; v < nbinvars; ++v )
886  {
887  implvar = vars[v];
888  assert(implvar != NULL);
889 
890  if( implvar == var )
891  {
892  /* check if the clique is useful at all */
893  if( useless )
894  {
895  SCIP_Real objval;
896 
897  objval = SCIPvarGetObj(var);
898 
899  if( varfixing == (SCIP_Bool)SCIPvarGetBestBoundType(var) && !SCIPisZero(scip, objval) )
900  useless = FALSE;
901  }
902  }
903  else if( values[v] == (SCIP_Bool)SCIPvarGetBestBoundType(implvar) )
904  {
905  useless = FALSE;
906  (*objchg) += collectMinactImplicVar(scip, implvar, binobjvarmap, collectedvars, nbinobjvars, contributors, ncontributors);
907  }
908  }
909 
910  /* if the clique is useless store it in the hash table to skip it later */
911  if( useless )
912  {
913  assert(!SCIPhashtableExists(uselesscliques, (void*)clique));
914  SCIP_CALL( SCIPhashtableInsert(uselesscliques, (void*)clique) );
915  }
916  }
917 
918  return SCIP_OKAY;
919 }
920 
921 /** returns the objective change provided by the implications of the given variable by fixing it to the given bound
922  * w.r.t. minimum activity of the objective function
923  *
924  * Let I(0) and I(1) be all implications of the given variable which follow by fixing it to given bound and evaluate to
925  * fixing the implication variable to zero (I(0)) or one (I(1)), respectively. The objective change provided by the
926  * implications are:
927  *
928  * \f[
929  * \displaystyle
930  * sum_{x\in I(1)} (1 - \mbox{bestbound}(x)) \cdot \mbox{objval}(x) - sum_{x\in I(1)} \mbox{bestbound}(x) \cdot \mbox{objval}(x)
931  * =
932  * sum_{x\in I(0) \cup I(1)} (\mbox{impliedbound}(x) - \mbox{bestbound}(x)) \cdot \mbox{objval}(x)
933  * \f]
934  *
935  * This can be done w.r.t. global variable bounds (local == FALSE), w.r.t. local variable bounds (local == TRUE &&
936  * bdchgidx == NULL), and w.r.t. given time stamp (local == TRUE && bdchgidx != NULL)
937  */
938 static
940  SCIP* scip, /**< SCIP data structure */
941  SCIP_VAR* var, /**< variable to computes the objective contribution */
942  SCIP_OBJIMPLICS* objimplics, /**< objective implication data for the given variable */
943  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node, or NULL */
944  SCIP_BOUNDTYPE bound, /**< bound to check for */
945  SCIP_Bool local, /**< propagate local bounds, otherwise global bounds */
946  SCIP_Real* objchg /**< pointer to store the objective change */
947  )
948 {
949  SCIP_VAR* implvar;
950  SCIP_Bool lb;
951  SCIP_Bool ub;
952  int nbinvars;
953  int v;
954 
955  assert(SCIPvarIsBinary(var));
956  assert(!local || SCIPvarGetLbAtIndex(var, bdchgidx, FALSE) < 0.5);
957  assert(!local || SCIPvarGetUbAtIndex(var, bdchgidx, FALSE) > 0.5);
958  assert(SCIPvarGetLbGlobal(var) < 0.5);
959  assert(SCIPvarGetUbGlobal(var) > 0.5);
960  assert(bound == SCIP_BOUNDTYPE_LOWER || bound == SCIP_BOUNDTYPE_UPPER);
961 
962  if( bound == SCIP_BOUNDTYPE_LOWER )
963  {
964  v = 0;
965  nbinvars = objimplics->nlbimpls;
966  }
967  else
968  {
969  assert(bound == SCIP_BOUNDTYPE_UPPER);
970  v = objimplics->nlbimpls;
971  nbinvars = objimplics->nlbimpls + objimplics->nubimpls;
972  }
973 
974  /* loop over all implications */
975  while( v < nbinvars )
976  {
977  implvar = objimplics->objvars[v];
978  assert(implvar != NULL);
979  assert(!SCIPisZero(scip, SCIPvarGetObj(implvar)));
980 
981  if( local )
982  {
983  lb = SCIPvarGetLbAtIndex(implvar, bdchgidx, FALSE) > 0.5;
984  ub = SCIPvarGetUbAtIndex(implvar, bdchgidx, FALSE) > 0.5;
985 
986  /* check if variable is fixed */
987  if( lb == TRUE || ub == FALSE )
988  {
989  v++;
990  continue;
991  }
992  }
993  else
994  {
995  lb = SCIPvarGetLbGlobal(implvar) > 0.5;
996  ub = SCIPvarGetUbGlobal(implvar) > 0.5;
997 
998  /* check if variable is global fixed; if so remove it from the objective implication data structure and
999  * continue with the next candidate
1000  */
1001  if( lb == TRUE || ub == FALSE )
1002  {
1003  SCIP_CALL( objimplicsDelPos(scip, objimplics, v) );
1004  nbinvars--;
1005  continue;
1006  }
1007  }
1008 
1009  assert(SCIPvarGetObj(implvar) > 0.0 || SCIPvarsHaveCommonClique(var, (SCIP_Bool) bound, implvar, TRUE, TRUE));
1010  assert(SCIPvarGetObj(implvar) < 0.0 || SCIPvarsHaveCommonClique(var, (SCIP_Bool) bound, implvar, FALSE, TRUE));
1011 
1012  /* add objective change */
1013  (*objchg) += REALABS(SCIPvarGetObj(implvar));
1014  v++;
1015  }
1016 
1017  return SCIP_OKAY;
1018 }
1019 
1020 /** computes for the given binary variable the objective contribution by fixing it to given bound w.r.t. minimum
1021  * activity of the objective function; additionally it collects all contributors for that objective change;
1022  */
1023 static
1025  SCIP* scip, /**< SCIP data structure */
1026  SCIP_VAR* var, /**< variable to computes the objective contribution */
1027  SCIP_BOUNDTYPE bound, /**< bound to check for */
1028  SCIP_HASHMAP* binobjvarmap, /**< hash map mapping binary variables with none-zero objective to position in collected variables arrays */
1029  SCIP_Bool* collectedvars, /**< temporary buffer to mark collected variables */
1030  int nbinobjvars, /**< number of binary variables with non-zero objective coefficient */
1031  SCIP_VAR** contributors, /**< array to store the contriboters */
1032  SCIP_HASHTABLE* uselesscliques, /**< hash table to store useless cliques, or NULL */
1033  int* ncontributors, /**< pointer to store number of contributor to the objective contribution */
1034  SCIP_Real* objchg /**< pointer to store the objective change */
1035  )
1036 {
1037  assert(SCIPvarIsBinary(var));
1038  assert(contributors != NULL);
1039  assert(ncontributors != NULL);
1040 
1041  /* collects the contribution of the variable itself w.r.t. the best bound */
1042  (*objchg) = getVarObjchg(var, SCIPvarGetBestBoundType(var), bound);
1043 
1044  (*ncontributors) = 0;
1045 
1046  /* add the objective contribution from the implication variable */
1047  SCIP_CALL( collectMinactImplicVars(scip, var, bound, binobjvarmap, collectedvars, nbinobjvars, contributors, uselesscliques, ncontributors, objchg) );
1048 
1049  return SCIP_OKAY;
1050 }
1051 
1052 /** computes for the given binary variable the objective contribution by fixing it to given bound w.r.t. minimum
1053  * activity of the objective function; this can be done w.r.t. global variable bounds (local == FALSE), w.r.t. local
1054  * variable bounds (local == TRUE && bdchgidx == NULL), and w.r.t. given time stamp (local == TRUE && bdchgidx != NULL)
1055  */
1056 static
1058  SCIP* scip, /**< SCIP data structure */
1059  SCIP_VAR* var, /**< variable to computes the objective contribution */
1060  SCIP_OBJIMPLICS* objimplics, /**< objective implication data for the given variable */
1061  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node, or NULL */
1062  SCIP_BOUNDTYPE bound, /**< bound to check for */
1063  SCIP_Bool local, /**< propagate local bounds, otherwise global bounds */
1064  SCIP_Real* objchg /**< pointer to store the objective change */
1065  )
1066 {
1067  assert(SCIPvarIsBinary(var));
1068 
1069  /* collects the contribution of the variable itself w.r.t. the best bound */
1070  (*objchg) = getVarObjchg(var, SCIPvarGetBestBoundType(var), bound);
1071 
1072  /* add the objective contribution from the implication variable */
1073  SCIP_CALL( getMinactImplicObjchg(scip, var, objimplics, bdchgidx, bound, local, objchg) );
1074 
1075  return SCIP_OKAY;
1076 }
1077 
1078 /** returns the global (that means w.r.t. global bounds of the variables) objective change provided by all cliques of
1079  * the given variable by fixing it to the given bound w.r.t. maximum activity of the objective function
1080  *
1081  * Let I(0) and I(1) be all implications of the given variable which follow by fixing it to given bound and evaluate to
1082  * fixing the implication variable to zero (I(0)) or one (I(1)), respectively. The objective change provided by these
1083  * implications are:
1084  *
1085  * \f[
1086  * \displaystyle
1087  * sum_{x\in I(1)} (1 - \mbox{worstbound}(x)) \cdot \mbox{objval}(x) - sum_{x\in I(1)} \mbox{worst}(x) \cdot \mbox{objval}(x)
1088  * =
1089  * sum_{x\in I(0) \cup I(1)} (\mbox{impliedbound}(x) - \mbox{worstbound}(x)) \cdot \mbox{objval}(x)
1090  * \f]
1091  */
1092 static
1094  SCIP* scip, /**< SCIP data structure */
1095  SCIP_VAR* var, /**< variable to computes the objective contribution */
1096  SCIP_BOUNDTYPE bound, /**< bound to check for */
1097  SCIP_Real* objchg /**< pointer to store the objective change */
1098  )
1100  SCIP_Bool varfixing;
1101  int ncliques;
1102  int nvars;
1103 
1104  assert(scip != NULL);
1105  assert(SCIPvarIsBinary(var));
1106  assert(SCIPvarGetLbGlobal(var) < 0.5);
1107  assert(SCIPvarGetUbGlobal(var) > 0.5);
1108  assert(bound == SCIP_BOUNDTYPE_LOWER || bound == SCIP_BOUNDTYPE_UPPER);
1109  assert(objchg != NULL);
1110 
1111  varfixing = (SCIP_Bool)bound;
1112  assert((SCIP_Bool)SCIP_BOUNDTYPE_LOWER == FALSE);
1113  assert((SCIP_Bool)SCIP_BOUNDTYPE_UPPER == TRUE);
1114 
1115  *objchg = 0.0;
1116  ncliques = SCIPvarGetNCliques(var, varfixing);
1117 
1118  if( ncliques > 0 )
1119  {
1120  SCIP_CLIQUE** cliques;
1121  SCIP_CLIQUE* clique;
1122  SCIP_VAR** clqvars;
1123  SCIP_VAR** probvars;
1124  SCIP_VAR* clqvar;
1125  SCIP_Bool* clqvalues;
1126  int* entries;
1127  int* ids;
1128  SCIP_Real obj;
1129  int nclqvars;
1130  int nentries;
1131  int objmult;
1132  int nids;
1133  int id;
1134  int c;
1135  int v;
1136 
1137  assert(SCIPisTransformed(scip));
1138 
1139  nentries = SCIPgetNVars(scip) - SCIPgetNContVars(scip) + 1;
1140 
1141  SCIP_CALL( SCIPallocBufferArray(scip, &ids, 2*nentries) );
1142  nids = 0;
1143  /* @todo move this memory allocation to SCIP_SET and add a memory list there, to decrease the number of
1144  * allocations and clear ups
1145  */
1146  SCIP_CALL( SCIPallocBufferArray(scip, &entries, nentries) );
1147  BMSclearMemoryArray(entries, nentries);
1148 
1149  cliques = SCIPvarGetCliques(var, varfixing);
1150  assert(cliques != NULL);
1151 
1152  /* iterate over all cliques and determine all importantimplications */
1153  for( c = ncliques - 1; c >= 0; --c )
1154  {
1155  clique = cliques[c];
1156  clqvars = SCIPcliqueGetVars(clique);
1157  clqvalues = SCIPcliqueGetValues(clique);
1158  nclqvars = SCIPcliqueGetNVars(clique);
1159  assert(nclqvars > 0);
1160  assert(clqvars != NULL);
1161  assert(clqvalues != NULL);
1162 
1163  if( nclqvars > MAX_CLIQUELENGTH )
1164  continue;
1165 
1166  /* iterate over all clique variables */
1167  for( v = nclqvars - 1; v >= 0; --v )
1168  {
1169  clqvar = clqvars[v];
1170  assert(clqvar != NULL);
1171 
1172  objmult = (int)!clqvalues[v] - (int)SCIPvarGetWorstBoundType(clqvar);
1173  assert(-1 <= objmult && objmult <= 1);
1174 
1175  /* ignore binary variable which are either fixed and were the objective contribution will not be zero */
1176  if( clqvar != var && objmult != 0 && SCIPvarIsActive(clqvar) &&
1177  (SCIPvarGetLbGlobal(clqvar) < 0.5 && SCIPvarGetUbGlobal(clqvar) > 0.5) && !SCIPisZero(scip, SCIPvarGetObj(clqvar)) )
1178  {
1179  int probindex = SCIPvarGetProbindex(clqvar) + 1;
1180  assert(0 < probindex && probindex < nentries);
1181 
1182  /* check that the variable was not yet visited */
1183  assert(entries[probindex] == 0 || entries[probindex] == objmult);
1184  if( entries[probindex] == 0 )
1185  {
1186  /* memorize probindex */
1187  ids[nids] = probindex;
1188  ++nids;
1189 
1190  assert(ABS(objmult) == 1);
1191 
1192  /* mark variable as visited */
1193  entries[probindex] = objmult;
1194  }
1195  }
1196  }
1197  }
1198 
1199  probvars = SCIPgetVars(scip);
1200  assert(probvars != NULL);
1201 
1202  /* add all implied objective values */
1203  for( v = nids - 1; v >= 0; --v )
1204  {
1205  id = ids[v];
1206  assert(0 < id && id < nentries);
1207  assert(entries[id] != 0);
1208 
1209  clqvar = probvars[id - 1];
1210  assert(clqvar != NULL);
1211  assert(SCIPvarIsBinary(clqvar));
1212  assert(SCIPvarIsActive(clqvar));
1213  assert(SCIPvarGetLbGlobal(clqvar) < 0.5);
1214  assert(SCIPvarGetUbGlobal(clqvar) > 0.5);
1215 
1216  obj = SCIPvarGetObj(clqvar);
1217  assert(!SCIPisZero(scip, obj));
1218 
1219  *objchg += entries[id] * obj;
1220  }
1221 
1222  /* free temporary memory */
1223  SCIPfreeBufferArray(scip, &entries);
1224  SCIPfreeBufferArray(scip, &ids);
1225  }
1226 
1227 #ifdef SCIP_MORE_DEBUG
1228  SCIPdebugMessage("objective contribution when variable <%s> fixed to %u using cliques is %g\n", SCIPvarGetName(var),
1229  varfixing, *objchg);
1230 #endif
1231 
1232  /* collect non-binary implication information */
1233  nvars = SCIPvarGetNImpls(var, varfixing);
1234 
1235  if( nvars > 0 )
1236  {
1237  SCIP_VAR** vars;
1238  SCIP_VAR* implvar;
1239  SCIP_Real* bounds;
1240  SCIP_BOUNDTYPE* boundtypes;
1241  SCIP_Real obj;
1242  SCIP_Real lb;
1243  SCIP_Real ub;
1244  int v;
1245 
1246  vars = SCIPvarGetImplVars(var, varfixing);
1247  boundtypes = SCIPvarGetImplTypes(var, varfixing);
1248  bounds = SCIPvarGetImplBounds(var, varfixing);
1249 
1250  for( v = nvars - 1; v >= 0; --v )
1251  {
1252  implvar = vars[v];
1253  assert(implvar != NULL);
1254 
1255  lb = SCIPvarGetLbLocal(implvar);
1256  ub = SCIPvarGetUbLocal(implvar);
1257  obj = SCIPvarGetObj(implvar);
1258 
1259  /* ignore binary variable which are fixed or not of column status */
1260  if( SCIPisZero(scip, obj) )
1261  continue;
1262 
1263  /* add up objective change if applicable */
1264  if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPvarGetWorstBoundType(implvar) == SCIP_BOUNDTYPE_LOWER && SCIPisFeasGT(scip, bounds[v], lb) )
1265  *objchg += (bounds[v] - lb)*obj;
1266  else if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPvarGetWorstBoundType(implvar) == SCIP_BOUNDTYPE_UPPER && SCIPisFeasLT(scip, bounds[v], ub) )
1267  *objchg += (bounds[v] - ub)*obj;
1268  }
1269  }
1270 
1271 #ifdef SCIP_MORE_DEBUG
1272  SCIPdebugMessage("objective contribution when variable <%s> fixed to %u using cliques and implications is %g\n", SCIPvarGetName(var),
1273  varfixing, *objchg);
1274 #endif
1275 
1276  return SCIP_OKAY;
1277 }
1278 
1279 /** computes for the given binary variable the gloabl (that means w.r.t. global bounds of the variables) objective
1280  * contribution by fixing it to given bound w.r.t. maximum activity of the objective function
1281  */
1282 static
1284  SCIP* scip, /**< SCIP data structure */
1285  SCIP_VAR* var, /**< variable to computes the objective contribution */
1286  SCIP_BOUNDTYPE bound, /**< bound to check for */
1287  SCIP_Bool useimplics, /**< should implications be used */
1288  SCIP_Real* objchg /**< pointer to store the objective change */
1289  )
1290 {
1291  assert(scip != NULL);
1292  assert(SCIPvarIsBinary(var));
1293  assert(objchg != NULL);
1294 
1295  *objchg = 0;
1296 
1297  /* check if the implications should be used to increase the objective contribution for given variable */
1298  if( useimplics )
1299  {
1300  /* using cliques and @todo other implications */
1301  SCIP_CALL( getMaxactImplicObjchg(scip, var, bound, objchg) );
1302  }
1303 
1304  /* collects the contribution of the variable itself w.r.t. the worst bound */
1305  *objchg += getVarObjchg(var, SCIPvarGetWorstBoundType(var), bound);
1306 
1307  return SCIP_OKAY;
1308 }
1309 
1310 /** reset variables array which marks variables which are collected */
1311 static
1312 void resetContributors(
1313  SCIP_HASHMAP* binobjvarmap, /**< hash map mapping binary variables with none-zero objective to position in collected variables arrays */
1314  SCIP_Bool* collectedvars, /**< temporary buffer to mark collected variables which should be reset */
1315  SCIP_VAR** contributors, /**< temporary buffer to use for collecting contributors */
1316  int ncontributors /**< number of contributors */
1317  )
1319  SCIP_VAR* var;
1320  int pos;
1321  int c;
1322 
1323  for( c = 0; c < ncontributors; ++c )
1324  {
1325  var = contributors[c];
1326  assert(var != NULL);
1327 
1328  assert(SCIPhashmapExists(binobjvarmap, var));
1329  pos = (int)(size_t)SCIPhashmapGetImage(binobjvarmap, var);
1330  assert(pos > 0);
1331  collectedvars[pos] = FALSE;
1332  }
1333 }
1334 
1335 /** check if the given variable should be collected for the minimum activity propagation */
1336 static
1338  SCIP* scip, /**< SCIP data structure */
1339  SCIP_VAR* var, /**< variable to check */
1340  SCIP_OBJIMPLICS** objimplics, /**< pointer to store the objective implication data structure w.r.t. minimum activity */
1341  SCIP_Bool useimplics, /**< should implications be used */
1342  SCIP_HASHMAP* binobjvarmap, /**< hash map mapping binary variables with none-zero objective to position in collected variables arrays */
1343  SCIP_Bool* collectedlbvars, /**< temporary buffer to mark collected variables for lower bound fixing */
1344  SCIP_Bool* collectedubvars, /**< temporary buffer to mark collected variables for upper bound fixing */
1345  int nbinobjvars, /**< number of binary variables with non-zero objective coefficient */
1346  SCIP_VAR** contributors, /**< temporary buffer to use for collecting contributors */
1347  SCIP_HASHTABLE* uselesscliques, /**< hash table to store useless cliques, or NULL */
1348  SCIP_Bool* collect /**< pointer to store if the variable should be stored */
1349  )
1350 {
1351  SCIP_Real lbobjchg;
1352  SCIP_Real ubobjchg;
1353  SCIP_Real objval;
1354  int nlbcliques;
1355  int nubcliques;
1356 
1357  assert(objimplics != NULL);
1358 
1359  objval = SCIPvarGetObj(var);
1360  (*objimplics) = NULL;
1361 
1362  if( SCIPisZero(scip, objval) )
1363  (*collect) = FALSE;
1364  else
1365  (*collect) = TRUE;
1366 
1367  nlbcliques = SCIPvarGetNCliques(var, FALSE);
1368  nubcliques = SCIPvarGetNCliques(var, TRUE);
1369 
1370  /* check if implications should be used and if implications are existing */
1371  if( useimplics && nlbcliques + nubcliques > 0 )
1372  {
1373  int nlbcontributors;
1374  int nubcontributors;
1375 
1376  assert((SCIP_Bool)SCIP_BOUNDTYPE_LOWER == FALSE);
1377  assert((SCIP_Bool)SCIP_BOUNDTYPE_UPPER == TRUE);
1378 
1379  /* get contribution of variable by fixing it to its lower bound w.r.t. minimum activity of the objective function */
1380  SCIP_CALL( collectMinactObjchg(scip, var, SCIP_BOUNDTYPE_LOWER, binobjvarmap, collectedlbvars, nbinobjvars,
1381  contributors, uselesscliques, &nlbcontributors, &lbobjchg) );
1382  assert(!SCIPisNegative(scip, lbobjchg));
1383 
1384  SCIPdebugMessage("variable <%s> fixed to bound=%d implies %d(%d)\n", SCIPvarGetName(var),
1385  SCIP_BOUNDTYPE_LOWER, 0, nlbcontributors);
1386 
1387  /* ignore implications if the variable has a zero objective coefficient and implications only one variable, since
1388  * this covered by that implied variable
1389  */
1390  if( !(*collect) && nlbcontributors == 1 )
1391  {
1392  /* reset lower bound contributors */
1393  resetContributors(binobjvarmap, collectedlbvars, contributors, nlbcontributors);
1394 
1395  assert(SCIPisZero(scip, objval));
1396  nlbcontributors = 0;
1397  }
1398 
1399  /* get contribution of variable by fixing it to its upper bound w.r.t. minimum activity of the objective function */
1400  SCIP_CALL( collectMinactObjchg(scip, var, SCIP_BOUNDTYPE_UPPER, binobjvarmap, collectedubvars, nbinobjvars,
1401  &contributors[nlbcontributors], uselesscliques, &nubcontributors, &ubobjchg) );
1402  assert(!SCIPisNegative(scip, ubobjchg));
1403 
1404  SCIPdebugMessage("variable <%s> fixed to bound=%d implies %d(%d)\n", SCIPvarGetName(var),
1405  SCIP_BOUNDTYPE_UPPER, 0, nubcontributors);
1406 
1407  /* ignore implications if the variable has a zero objective coefficient and implications only one variable, since
1408  * this covered by that implied variable
1409  */
1410  if( !(*collect) && nubcontributors == 1 )
1411  {
1412  /* reset upper bound contributors */
1413  resetContributors(binobjvarmap, collectedubvars, &contributors[nlbcontributors], nubcontributors);
1414 
1415  assert(SCIPisZero(scip, objval));
1416  nubcontributors = 0;
1417  }
1418 
1419  if( (*collect) || nlbcontributors > 1 || nubcontributors > 1 )
1420  {
1421  /* creates an objective implication data structure, fixes (globally) variables which are implied by lower and upper
1422  * bound fixing, and clears the collected arrays for lower and upper bound
1423  */
1424  SCIP_CALL( objimplicsCreate(scip, objimplics, contributors, binobjvarmap, collectedlbvars, collectedubvars, lbobjchg, ubobjchg, nlbcontributors, nubcontributors) );
1425  (*collect) = TRUE;
1426  }
1427  else
1428  {
1429  /* reset lower bound contributors */
1430  resetContributors(binobjvarmap, collectedlbvars, contributors, nlbcontributors);
1431 
1432  /* reset upper bound contributors */
1433  resetContributors(binobjvarmap, collectedubvars, &contributors[nlbcontributors], nubcontributors);
1434  }
1435  }
1436  else if( (*collect) )
1437  {
1440  assert(!SCIPisZero(scip, lbobjchg) || !SCIPisZero(scip, ubobjchg));
1441  assert(!SCIPisNegative(scip, lbobjchg));
1442  assert(!SCIPisNegative(scip, ubobjchg));
1443 
1444  /* creates an "empty" objective implication data structure */
1445  SCIP_CALL( objimplicsCreate(scip, objimplics, NULL, NULL, NULL, NULL, lbobjchg, ubobjchg, 0, 0) );
1446  }
1447 
1448  return SCIP_OKAY;
1449 }
1450 
1451 /** check if the given variable should be collected for the maximum activity propagation */
1452 static
1454  SCIP* scip, /**< SCIP data structure */
1455  SCIP_VAR* var, /**< variable to check */
1456  SCIP_Bool useimplics, /**< should implications be used */
1457  SCIP_Real* objchg, /**< pointer to store the objective change w.r.t. maximum activity */
1458  SCIP_Bool* isnotzero /**< pointer to store if the objective change is unequal to zero or not */
1459  )
1460 {
1461  SCIP_Real lbobjchg;
1462  SCIP_Real ubobjchg;
1463 
1464  assert(scip != NULL);
1465  assert(SCIPvarIsBinary(var));
1466  assert(objchg != NULL);
1467  assert(isnotzero != NULL);
1468 
1469  /* get contribution of variable by fixing it to its lower bound w.r.t. maximum activity of the objective function */
1470  SCIP_CALL( getMaxactObjchg(scip, var, SCIP_BOUNDTYPE_LOWER, useimplics, &lbobjchg) );
1471  assert(!SCIPisPositive(scip, lbobjchg));
1472 
1473  /* get contribution of variable by fixing it to its upper bound w.r.t. maximum activity of the objective function */
1474  SCIP_CALL( getMaxactObjchg(scip, var, SCIP_BOUNDTYPE_UPPER, useimplics, &ubobjchg) );
1475  assert(!SCIPisPositive(scip, ubobjchg));
1476 
1477  (*objchg) = MIN(lbobjchg, ubobjchg);
1478 
1479  /* only consider variables with non-zero objective contribution */
1480  if( SCIPisZero(scip, (*objchg)) )
1481  *isnotzero = FALSE;
1482  else
1483  *isnotzero = TRUE;
1484 
1485  return SCIP_OKAY;
1486 }
1487 
1488 /** initializate the propagator */
1489 static
1491  SCIP* scip, /**< SCIP data structure */
1492  SCIP_PROPDATA* propdata /**< propagator data */
1493  )
1494 {
1495  SCIP_VAR** vars;
1496  SCIP_VAR* var;
1497  SCIP_HASHMAP* binobjvarmap;
1498  int nvars;
1499  int nbinvars;
1500  int nintvars;
1501  int nminactvars;
1502  int nmaxactvars;
1503  int nobjintvars;
1504  int nobjcontvars;
1505  int nobjvars;
1506  int nbinobjvars;
1507  int v;
1508 
1509  assert(scip != NULL);
1510  assert(propdata != NULL);
1511 
1512  /* get problem variables */
1513  vars = SCIPgetVars(scip);
1514  nvars = SCIPgetNVars(scip);
1515  nintvars = nvars - SCIPgetNContVars(scip);
1516 
1517  nbinvars = 0;
1518  nobjvars = 0;
1519  nbinobjvars = 0;
1520 
1521  SCIP_CALL( SCIPhashmapCreate(&binobjvarmap, SCIPblkmem(scip), SCIPcalcHashtableSize(SCIPgetNObjVars(scip) * 5)) );
1522 
1523  /* count and collect variable problem indices of variables with non-zero objective coefficient */
1524  for( v = 0; v < nvars; ++v )
1525  {
1526  var = vars[v];
1527  assert(var != NULL);
1528 
1529  if( !SCIPisZero(scip, SCIPvarGetObj(var)) )
1530  {
1531  nobjvars++;
1532 
1533  if( SCIPvarIsBinary(var) )
1534  {
1535  SCIP_CALL( SCIPhashmapInsert(binobjvarmap, (void*)var, (void*)(size_t)(nbinobjvars + 1)) );
1536  nbinobjvars++;
1537  }
1538  }
1539 
1540  if( SCIPvarIsBinary(var) )
1541  nbinvars++;
1542  }
1543 
1544  nminactvars = 0;
1545  nmaxactvars = 0;
1546  nobjintvars = 0;
1547  nobjcontvars = 0;
1548 
1549  if( nobjvars > 0 )
1550  {
1551  SCIP_EVENTHDLR* eventhdlr;
1552  SCIP_OBJIMPLICS* objimplics;
1553  SCIP_HASHTABLE* uselesscliques;
1554  SCIP_VAR** contributors;
1555  SCIP_Bool* collectedlbvars;
1556  SCIP_Bool* collectedubvars;
1557  SCIP_Bool collect;
1558  SCIP_Bool useimplics;
1559  SCIP_Real objval;
1560  SCIP_Real objchg;
1561 
1562  eventhdlr = propdata->eventhdlr;
1563  assert(eventhdlr != NULL);
1564 
1565  useimplics = (propdata->propuseimplics && nbinobjvars < propdata->maximplvars);
1566 
1567  /* allocate memory for all arrays */
1568  SCIP_CALL( SCIPallocMemoryArray(scip, &propdata->minactvars, nbinvars) );
1569  SCIP_CALL( SCIPallocMemoryArray(scip, &propdata->minactimpls, nbinvars) );
1570  SCIP_CALL( SCIPallocMemoryArray(scip, &propdata->maxactvars, nbinvars) );
1571  SCIP_CALL( SCIPallocMemoryArray(scip, &propdata->maxactchgs, nbinvars) );
1572  SCIP_CALL( SCIPallocMemoryArray(scip, &propdata->objintvars, nobjvars - nbinobjvars) );
1573 
1574  if( useimplics )
1575  {
1576  int ncliques;
1577 
1578  /* create temporary buffer */
1579  SCIP_CALL( SCIPallocBufferArray(scip, &contributors, nbinobjvars) );
1580  SCIP_CALL( SCIPallocBufferArray(scip, &collectedlbvars, nbinobjvars+1) );
1581  BMSclearMemoryArray(collectedlbvars, nbinobjvars+1);
1582  SCIP_CALL( SCIPallocBufferArray(scip, &collectedubvars, nbinobjvars+1) );
1583  BMSclearMemoryArray(collectedubvars, nbinobjvars+1);
1584 
1585  ncliques = SCIPgetNCliques(scip);
1586 
1587  if( ncliques > 0 )
1588  {
1589  SCIP_CALL( SCIPhashtableCreate(&uselesscliques, SCIPblkmem(scip), SCIPcalcHashtableSize(ncliques),
1590  cliqueGetHashkey, cliqueIsHashkeyEq, cliqueGetHashkeyVal, NULL) );
1591  }
1592  else
1593  uselesscliques = NULL;
1594  }
1595  else
1596  {
1597  contributors = NULL;
1598  collectedlbvars = NULL;
1599  collectedubvars = NULL;
1600  uselesscliques = NULL;
1601  }
1602 
1603  /* collect the variables with non-zero objective contribution and catch global bound tighten events that decrease the
1604  * maximal pseudo objective activity
1605  */
1606  for( v = 0; v < nvars && (nobjintvars == 0 || nobjintvars < nobjvars - nbinobjvars); ++v )
1607  {
1608  var = vars[v];
1609  assert(var != NULL);
1610 
1611  objval = SCIPvarGetObj(var);
1612 
1613  if( SCIPvarIsBinary(var) )
1614  {
1615  /* ignore variables which are globally fixed */
1616  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
1617  {
1618 #ifndef NDEBUG
1619  /* check that the binary implications are applied for binary variables which are globally fixed */
1620  checkImplicsApplied(scip, var);
1621 #endif
1622  continue;
1623  }
1624 
1625  /* check if the variable should be collected for the minimum activity propagation */
1626  SCIP_CALL( collectMinactVar(scip, var, &objimplics, useimplics, binobjvarmap, collectedlbvars, collectedubvars,
1627  nbinobjvars, contributors, uselesscliques, &collect) );
1628 
1629  if( collect )
1630  {
1631  assert(nminactvars < nbinvars);
1632  assert(objimplics != NULL);
1633  assert(objimplics->nlbimpls + objimplics->nubimpls <= nbinobjvars);
1634 
1635  /* collect the binary variable with non-zero objective contribution */
1636  propdata->minactvars[nminactvars] = var;
1637  propdata->minactimpls[nminactvars] = objimplics;
1638  nminactvars++;
1639 
1640  /* catch bound relax event for the binary variable to handel the firstnonfixed index correctly */
1641  SCIP_CALL( SCIPcatchVarEvent(scip, var, SCIP_EVENTTYPE_BOUNDRELAXED, eventhdlr, (SCIP_EVENTDATA*)propdata, NULL) );
1642 
1643  SCIPdebugMessage("variable <%s>[obj: <%g>] implicit objective change %g\n",
1644  SCIPvarGetName(var), objval, objimplics->maxobjchg);
1645 
1646  /* captures the variable */
1647  SCIP_CALL( SCIPcaptureVar(scip, var) ) ;
1648  }
1649  /* check if the variable should be collected for the maximum activity propagation */
1650  SCIP_CALL( collectMaxactVar(scip, var, useimplics, &objchg, &collect) );
1651 
1652  if( collect )
1653  {
1654  assert(nmaxactvars < nbinvars);
1655 
1656  /* collect the binary variable with non-zero objective contribution */
1657  propdata->maxactvars[nmaxactvars] = var;
1658  propdata->maxactchgs[nmaxactvars] = -objchg;
1659  nmaxactvars++;
1660 
1661  /* catch bound change events if the variable has a non-zero objective coefficient to check if the maximum
1662  * activity of the objective function changed
1663  */
1664  SCIP_CALL( catchObjEvent(scip, propdata, eventhdlr, var) );
1665 
1666  /* captures the variable */
1667  SCIP_CALL( SCIPcaptureVar(scip, var) ) ;
1668  }
1669  }
1670  else
1671  {
1672  /* only consider none binary variables with a non-zero objective */
1673  if( SCIPisZero(scip, objval) )
1674  continue;
1675 
1676  assert(nobjintvars < nobjvars - nbinobjvars);
1677 
1678  propdata->objintvars[nobjintvars] = var;
1679  nobjintvars++;
1680 
1681  if( v >= nintvars )
1682  nobjcontvars++;
1683 
1684  /* catch bound change events if the variable has a non-zero objective coefficient to check if the maximum
1685  * activity of the objective function changed
1686  */
1687  SCIP_CALL( catchObjEvent(scip, propdata, eventhdlr, var) );
1688 
1689  /* captures the variable */
1690  SCIP_CALL( SCIPcaptureVar(scip, var) );
1691  }
1692  }
1693 
1694  if( useimplics )
1695  {
1696  if( uselesscliques != NULL )
1697  SCIPhashtableFree(&uselesscliques);
1698 
1699  SCIPfreeBufferArray(scip, &collectedubvars);
1700  SCIPfreeBufferArray(scip, &collectedlbvars);
1701  SCIPfreeBufferArray(scip, &contributors);
1702  }
1703 
1704  if( nminactvars == 0 )
1705  {
1706  SCIPfreeMemoryArray(scip, &propdata->minactvars);
1707  SCIPfreeMemoryArray(scip, &propdata->minactimpls);
1708  propdata->minactvars = NULL;
1709  propdata->minactimpls = NULL;
1710  }
1711  else
1712  {
1713  /* sort binary variables with respect to the absolute value of their maximal potential objective contribution for
1714  * the minimum activity of the objective function
1715  */
1716  SCIPsortDownPtrPtr((void**)propdata->minactimpls, (void**)propdata->minactvars, objimplicsComp, nminactvars);
1717 
1718  SCIPdebugMessage("%d binary variables with non-zero objective contribution w.r.t. the minimum activity of the objective function\n", nminactvars);
1719  }
1720 
1721  if( nmaxactvars == 0 )
1722  {
1723  SCIPfreeMemoryArray(scip, &propdata->maxactvars);
1724  SCIPfreeMemoryArray(scip, &propdata->maxactchgs);
1725  propdata->maxactvars = NULL;
1726  propdata->maxactchgs = NULL;
1727  }
1728  else
1729  {
1730  /* sort binary variables with respect to the absolute value of their maximal potential objective contribution for
1731  * the maximum activity of the objective function
1732  */
1733  SCIPsortDownRealPtr(propdata->maxactchgs, (void**)propdata->maxactvars, nmaxactvars);
1734 
1735  SCIPdebugMessage("%d binary variables with non-zero objective contribution w.r.t. the maximum activity of the objective function\n", nmaxactvars);
1736  }
1737 
1738  if( nobjintvars == 0 )
1739  {
1740  SCIPfreeMemoryArray(scip, &propdata->objintvars);
1741  propdata->objintvars = NULL;
1742  }
1743  else
1744  {
1745  /* sort integer variables with respect to the absolute value of their objective coefficient */
1746  SCIPsortDownPtr((void**)propdata->objintvars, varCompObj, nobjintvars - nobjcontvars);
1747 
1748  /* sort continuous variables with respect to the absolute value of their objective coefficient */
1749  SCIPsortDownPtr((void**)(&propdata->objintvars[nobjintvars - nobjcontvars]), varCompObj, nobjcontvars);
1750 
1751  SCIPdebugMessage("%d integer variables and %d continuous variables with non-zero objective contribution\n",
1752  nobjintvars - nobjcontvars, nobjcontvars);
1753  }
1754  }
1755 
1756  SCIPhashmapFree(&binobjvarmap);
1757 
1758  propdata->nminactvars = nminactvars;
1759  propdata->nmaxactvars = nmaxactvars;
1760  propdata->nobjintvars = nobjintvars;
1761  propdata->maxpseudoobjact = SCIP_INVALID;
1762  propdata->maxpseudoobjactinf = 0;
1763  propdata->lastvarnum = -1;
1764  propdata->glbfirstnonfixed = 0;
1765  propdata->maxactfirstnonfixed = 0;
1766  propdata->firstnonfixed = 0;
1767  propdata->nnewvars = 0;
1768  propdata->cutoffbound = SCIPinfinity(scip);
1769  propdata->lastlowerbound = -SCIPinfinity(scip);
1770  propdata->glbpseudoobjval = -SCIPinfinity(scip);
1771 
1772  propdata->initialized = TRUE;
1773 
1774  /* due to scaling after presolving we need to update the global pseudoactivity and the cutoffbound */
1775  propdata->glbpropagated = FALSE;
1776  propdata->glbpseudoobjval = SCIPgetGlobalPseudoObjval(scip);
1777  propdata->cutoffbound = SCIPgetCutoffbound(scip);
1778  assert(SCIPgetDepth(scip) > 0 || SCIPisFeasEQ(scip, propdata->glbpseudoobjval, SCIPgetPseudoObjval(scip)));
1779 
1780  /* create hash table which is used for resolving bound changes */
1781  if( nminactvars > 0 )
1782  {
1783  SCIP_CALL( SCIPhashtableCreate(&propdata->addedvars, SCIPblkmem(scip), SCIPcalcHashtableSize(5*nvars),
1784  SCIPvarGetHashkey, SCIPvarIsHashkeyEq, SCIPvarGetHashkeyVal, NULL) );
1785  }
1786  else
1787  propdata->addedvars = NULL;
1788 
1789 
1790  return SCIP_OKAY;
1791 }
1792 
1793 /** adds for the given none binary variable a conflict bound depending on its objective contribution */
1794 static
1796  SCIP* scip, /**< SCIP data structure */
1797  SCIP_VAR* var, /**< variable to check for objective contribution */
1798  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
1799  SCIP_Real* reqpseudoobjval /**< pointer to store the remaining minimum activity which has to be proven */
1800  )
1802  SCIP_Real objval;
1803 
1804  objval = SCIPvarGetObj(var);
1805  assert(!SCIPisZero(scip, objval));
1806 
1807  if( objval > 0.0 )
1808  {
1809  SCIP_Real loclb;
1810  SCIP_Real glblb;
1811 
1812  glblb = SCIPvarGetLbGlobal(var);
1813  loclb = SCIPvarGetLbAtIndex(var, bdchgidx, FALSE);
1814  assert(SCIPisFeasGE(scip, loclb, glblb));
1815 
1816  /* check if the local lower bound (at time stamp bdchgidx) is larger than the global lower bound */
1817  if( SCIPisGT(scip, loclb, glblb) )
1818  {
1819  SCIPdebugMessage(" add bound change <%s>[%g] >= <%g>\n", SCIPvarGetName(var), objval, loclb);
1820  SCIP_CALL( SCIPaddConflictLb(scip, var, bdchgidx) );
1821 
1822  /* hard comparison is enough to make requiredpseudoobjval nonincreasing */
1823  assert((loclb - glblb) * objval > 0.0);
1824 
1825  (*reqpseudoobjval) -= (loclb - glblb) * objval;
1826  }
1827  }
1828  else
1829  {
1830  SCIP_Real locub;
1831  SCIP_Real glbub;
1832 
1833  glbub = SCIPvarGetUbGlobal(var);
1834  locub = SCIPvarGetUbAtIndex(var, bdchgidx, FALSE);
1835  assert(SCIPisFeasLE(scip, locub, glbub));
1836 
1837  /* check if the local upper bound (at time stamp bdchgidx) is smaller than the global upper bound */
1838  if( SCIPisLT(scip, locub, glbub) )
1839  {
1840  SCIPdebugMessage(" add bound change <%s>[%g] <= <%g>\n", SCIPvarGetName(var), objval, locub);
1841  SCIP_CALL( SCIPaddConflictUb(scip, var, bdchgidx) );
1842 
1843  /* hard comparison is enough to make requiredpseudoobjval nonincreasing */
1844  assert((locub - glbub) * objval > 0.0);
1845 
1846  (*reqpseudoobjval) -= (locub - glbub) * objval;
1847  }
1848  }
1849 
1850  return SCIP_OKAY;
1851 }
1852 
1853 /** check for the given implication variables of they also contribute to the required minimum activity */
1854 static
1856  SCIP* scip, /**< SCIP data structure */
1857  SCIP_VAR** vars, /**< variable to check for objective contribution */
1858  int start, /**< start index */
1859  int end, /**< end index */
1860  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
1861  SCIP_HASHTABLE* addedvars, /**< hash table containing variables which are already add directly or implicitly due to implications */
1862  SCIP_Real* reqpseudoobjval, /**< pointer to store the remaining minimum activity which has to be proven */
1863  SCIP_Bool* foundimplics /**< pointer to store if an implication is found */
1864  )
1865 {
1866  SCIP_VAR* var;
1867  SCIP_Real lb;
1868  SCIP_Real ub;
1869  int v;
1870 
1871  assert(foundimplics != NULL);
1872  assert(*foundimplics == FALSE);
1873 
1874  for( v = start; v < end; ++v )
1875  {
1876  var = vars[v];
1877  assert(var != NULL);
1878  assert(SCIPvarIsBinary(var));
1879 
1880  lb = SCIPvarGetLbAtIndex(var, bdchgidx, FALSE);
1881  ub = SCIPvarGetUbAtIndex(var, bdchgidx, FALSE);
1882 
1883  if( lb < 0.5 && ub > 0.5 && !SCIPhashtableExists(addedvars, (void*)var) )
1884  {
1885  (*reqpseudoobjval) -= REALABS(SCIPvarGetObj(var));
1886  SCIPdebugMessage(" implicated variables <%s>[%g] bdchgidx [%g,%g] -> remaining <%g>\n", SCIPvarGetName(var), SCIPvarGetObj(var), lb, ub, *reqpseudoobjval);
1887 
1888  SCIP_CALL( SCIPhashtableInsert(addedvars, (void*)var) );
1889  assert(SCIPhashtableExists(addedvars, (void*)var));
1890  (*foundimplics) = TRUE;
1891  }
1892  }
1893 
1894  return SCIP_OKAY;
1895 }
1896 
1897 /** adds for the given binary variable a conflict bound depending on its objective contribution */
1898 static
1900  SCIP* scip, /**< SCIP data structure */
1901  SCIP_VAR* var, /**< variable to check for objective contribution */
1902  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
1903  SCIP_OBJIMPLICS* objimplics, /**< objective implication data for the given variable */
1904  SCIP_HASHTABLE* addedvars, /**< hash table containing variables which are already add directly or implicitly due to implications */
1905  SCIP_Bool respropuseimplics, /**< should implications be used */
1906  SCIP_Real* reqpseudoobjval /**< pointer to store the remaining minimum activity which has to be proven */
1907  )
1908 {
1909  SCIP_Real objval;
1910  SCIP_Real lb;
1911  SCIP_Real ub;
1912  SCIP_Bool foundimplics;
1913 
1914  assert(SCIPvarIsBinary(var));
1915 
1916  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
1917  return SCIP_OKAY;
1918 
1919  lb = SCIPvarGetLbAtIndex(var, bdchgidx, FALSE);
1920  ub = SCIPvarGetUbAtIndex(var, bdchgidx, FALSE);
1921 
1922  objval = SCIPvarGetObj(var);
1923  foundimplics = FALSE;
1924 
1925  /* only consider variables which are fixed */
1926  if( lb > 0.5 )
1927  {
1928  if( respropuseimplics )
1929  {
1930  SCIP_CALL( getConflictImplics(scip, objimplics->objvars, objimplics->nlbimpls, objimplics->nlbimpls + objimplics->nubimpls,
1931  bdchgidx, addedvars, reqpseudoobjval, &foundimplics) );
1932  }
1933 
1934  /* check if the binary variable has a positive contribution (positive objective coefficient since it is fixed to
1935  * one) or is needed due a positive contribution of an implied variable
1936  */
1937  if( foundimplics || SCIPisPositive(scip, objval) )
1938  {
1939  SCIPdebugMessage(" add bound change <%s>[%g] >= <%g> bdchgidx [%g,%g]\n", SCIPvarGetName(var), objval, lb, lb, ub);
1940  SCIP_CALL( SCIPaddConflictLb(scip, var, NULL) );
1941 
1942  (*reqpseudoobjval) -= MAX(0.0, objval);
1943 
1944  if( addedvars != NULL )
1945  {
1946  assert(!SCIPhashtableExists(addedvars, (void*)var));
1947  SCIP_CALL( SCIPhashtableInsert(addedvars, (void*)var) );
1948  }
1949  }
1950  }
1951  else if( ub < 0.5 )
1952  {
1953  if( respropuseimplics )
1954  {
1955  SCIP_CALL( getConflictImplics(scip, objimplics->objvars, 0, objimplics->nlbimpls,
1956  bdchgidx, addedvars, reqpseudoobjval, &foundimplics) );
1957  }
1958 
1959  /* check if the binary variable has a positive contribution (negative objective coefficient since it is fixed to
1960  * zero) or is needed due a positive contribution of an implied variable
1961  */
1962  if( foundimplics || SCIPisNegative(scip, objval) )
1963  {
1964  SCIPdebugMessage(" add bound change <%s>[%g] <= <%g> bdchgidx=[%g,%g]\n", SCIPvarGetName(var), objval, ub, lb, ub);
1965  SCIP_CALL( SCIPaddConflictUb(scip, var, NULL) );
1966 
1967  (*reqpseudoobjval) += MIN(0.0, objval);
1968 
1969  if( addedvars != NULL )
1970  {
1971  assert(!SCIPhashtableExists(addedvars, (void*)var));
1972  SCIP_CALL( SCIPhashtableInsert(addedvars, (void*)var) );
1973  }
1974  }
1975  }
1976 
1977  return SCIP_OKAY;
1978 }
1979 
1980 
1981 /** resolves a propagation by supplying the variables whose bound changes increased the pseudo objective value above the
1982  * cutoff bound
1983  */
1984 static
1986  SCIP* scip, /**< SCIP data structure */
1987  SCIP_PROPDATA* propdata, /**< propagator data */
1988  SCIP_VAR* var, /**< variable that was deduced */
1989  int inferinfo, /**< inference information */
1990  SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
1991  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
1992  SCIP_HASHTABLE* addedvars, /**< hash table which contains variable which are already added or implict given as reason for the resolve, or NULL */
1993  SCIP_Real* cutoffbound /**< pointer to store the adjusted cutoff bound */
1994  )
1995 {
1996  if( inferinfo != -1 )
1997  {
1998  SCIP_OBJIMPLICS* objimplics;
1999  SCIP_Bool foundimplics;
2000  int start;
2001  int end;
2002 
2003  assert(var != NULL);
2004  assert(SCIPvarIsBinary(var));
2005  assert(bdchgidx != NULL);
2006  assert(SCIPisEQ(scip, SCIPvarGetLbAtIndex(var, bdchgidx, TRUE), SCIPvarGetUbAtIndex(var, bdchgidx, TRUE)));
2007  assert(inferinfo >= 0);
2008  assert(inferinfo < propdata->nminactvars);
2009  assert((SCIP_Bool)SCIP_BOUNDTYPE_LOWER == FALSE);
2010  assert((SCIP_Bool)SCIP_BOUNDTYPE_UPPER == TRUE);
2011 
2012  objimplics = propdata->minactimpls[inferinfo];
2013  assert(objimplics != NULL);
2014 
2015  /* get the objective contribution if we would fix the binray inference variable to its other bound */
2016  (*cutoffbound) -= getVarObjchg(var, SCIPvarGetBestBoundType(var), boundtype);
2017  foundimplics = FALSE;
2018 
2019  if( boundtype == SCIP_BOUNDTYPE_LOWER )
2020  {
2021  start = 0;
2022  end = objimplics->nlbimpls;
2023  }
2024  else
2025  {
2026  start = objimplics->nlbimpls;
2027  end = objimplics->nlbimpls + objimplics->nubimpls;
2028  }
2029 
2030  SCIP_CALL( getConflictImplics(scip, objimplics->objvars, start, end, bdchgidx, addedvars, cutoffbound, &foundimplics) );
2031  }
2032  else
2033  {
2034  SCIP_Real glbbound;
2035  SCIP_Real newbound;
2036  SCIP_Real objval;
2037 
2038  objval = SCIPvarGetObj(var);
2039 
2040  assert(!SCIPisZero(scip, objval));
2041 
2042  if( objval > 0.0 )
2043  {
2044  newbound = SCIPvarGetUbAtIndex(var, bdchgidx, TRUE);
2045  glbbound = SCIPvarGetLbGlobal(var);
2046  }
2047  else
2048  {
2049  newbound = SCIPvarGetLbAtIndex(var, bdchgidx, TRUE);
2050  glbbound = SCIPvarGetUbGlobal(var);
2051  }
2052 
2053  /* in case the variable is integral we just need to prove the newbound plus/minus (1 - epsilon) since the this bound
2054  * would be rounded to newbound due to integrability which is global information
2055  */
2056  if( SCIPvarIsIntegral(var) )
2057  {
2058  if( objval > 0.0 )
2059  newbound += 1 - 10 * SCIPfeastol(scip);
2060  else
2061  newbound -= 1 - 10 * SCIPfeastol(scip);
2062  }
2063 
2064  /* adjust the cutoff bound by the portion the inference variable contributes to the presudo objective activitiy
2065  * (minactivity)
2066  */
2067  assert(!SCIPisNegative(scip, objval * (newbound - glbbound)));
2068  (*cutoffbound) -= objval * (newbound - glbbound);
2069  }
2070 
2071  return SCIP_OKAY;
2072 }
2073 
2074 
2075 /** resolves a propagation by supplying the variables whose bound changes increased the pseudo objective value above the
2076  * cutoff bound
2077  */
2078 static
2080  SCIP* scip, /**< SCIP data structure */
2081  SCIP_PROPDATA* propdata, /**< propagator data */
2082  SCIP_Real cutoffbound, /**< the global cutoff */
2083  SCIP_VAR* infervar, /**< variable that was deduced, or NULL for conflict analysis initialization */
2084  int inferinfo, /**< inference information */
2085  SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
2086  SCIP_BDCHGIDX* bdchgidx /**< bound change index (time stamp of bound change), or NULL for current time */
2087  )
2088 {
2089  SCIP_HASHTABLE* addedvars;
2090  SCIP_VAR** vars;
2091  SCIP_VAR* var;
2092  SCIP_Real glbpseudoobjval;
2093  SCIP_Real reqpseudoobjval;
2094  SCIP_Bool infinity;
2095  int nvars;
2096  int v;
2097 
2098  infinity = FALSE;
2099  addedvars = NULL;
2100  nvars = propdata->nminactvars;
2101 
2102  /* the global pseudo value gives us a global valid minimal activity
2103  *
2104  * @note The global pseudo objective activity can be minus infinity. In that case all variable are part of the
2105  * reason/explanation
2106  *
2107  * @note If the global pseudo objective activity is greater than the required minactivity, the local bound change
2108  * which has to explained is actually (now) a global one. That means, the reason/explanation is empty
2109  */
2110  glbpseudoobjval = SCIPgetGlobalPseudoObjval(scip);
2111 
2112  if( SCIPisInfinity(scip, -glbpseudoobjval) )
2113  {
2114  infinity = TRUE;
2115  reqpseudoobjval = cutoffbound;
2116  }
2117  else
2118  {
2119  /* clear hash table for storing variables which are not needed to add the reason due to global implications or
2120  * already added
2121  */
2122  if( nvars > 0 )
2123  {
2124  addedvars = propdata->addedvars;
2125  SCIPhashtableRemoveAll(addedvars);
2126  }
2127 
2128  if( infervar != NULL )
2129  {
2130  SCIP_CALL( adjustCutoffbound(scip, propdata, infervar, inferinfo, boundtype, bdchgidx, addedvars, &cutoffbound) );
2131  }
2132 
2133  reqpseudoobjval = cutoffbound - glbpseudoobjval;
2134  }
2135 
2136  SCIPdebugMessage("resolve propagation global pseudo objective <%g>, cutoff bounda <%g>, required minactivity <%g>\n",
2137  glbpseudoobjval, cutoffbound, reqpseudoobjval);
2138 
2139  /* the variables responsible for the propagation are the ones with
2140  * - obj > 0 and local lb > global lb
2141  * - obj < 0 and local ub < global ub
2142  *
2143  * collect all variables which contribute positively to the pseudo objective value (minimum activity) until we
2144  * reached the (adjusted) required minimum activity for the inference bound change
2145  */
2146 
2147  /* first, consider the binary variables */
2148  if( nvars > 0 )
2149  {
2150  SCIP_OBJIMPLICS** minactimpls;
2151 
2152  vars = propdata->minactvars;
2153  assert(vars != NULL);
2154 
2155  minactimpls = propdata->minactimpls;
2156  assert(minactimpls != NULL);
2157 
2158 #ifndef NDEBUG
2159  checkGlbfirstnonfixed(scip, propdata);
2160 #endif
2161 
2162  if( infinity )
2163  {
2164  /* if the required minimum activity is minus infinity, we have to add all variables which contribute the local
2165  * pseudo objective activity
2166  */
2167 
2168  for( v = propdata->glbfirstnonfixed; v < nvars; ++v )
2169  {
2170  var = vars[v];
2171  assert(var != NULL);
2172 
2173  /* @note binary variables can have a zero objective value */
2174 
2175  if( var == infervar )
2176  continue;
2177 
2178  SCIP_CALL( addConflictBinvar(scip, var, bdchgidx, NULL, NULL, FALSE, &reqpseudoobjval) );
2179  }
2180  }
2181  else
2182  {
2183  assert(addedvars != NULL);
2184 
2185  for( v = propdata->glbfirstnonfixed; v < nvars && SCIPisPositive(scip, reqpseudoobjval); ++v )
2186  {
2187  var = vars[v];
2188  assert(var != NULL);
2189 
2190  /* @note binary variables can have a zero objective value */
2191 
2192  if( var == infervar )
2193  continue;
2194 
2195  if( SCIPhashtableExists(addedvars, (void*)var) )
2196  continue;
2197 
2198  SCIP_CALL( addConflictBinvar(scip, var, bdchgidx, minactimpls[v], addedvars, propdata->respropuseimplics, &reqpseudoobjval) );
2199  }
2200  }
2201  }
2202 
2203  vars = propdata->objintvars;
2204  nvars = propdata->nobjintvars;
2205  assert(nvars == 0 || vars != NULL);
2206 
2207  /* second, consider the non-binary variables */
2208  for( v = 0; v < nvars && (infinity || SCIPisPositive(scip, reqpseudoobjval)); ++v )
2209  {
2210  var = vars[v];
2211  assert(var != NULL);
2212  assert(!SCIPisZero(scip, SCIPvarGetObj(var)));
2213 
2214  if( var == infervar )
2215  continue;
2216 
2217  SCIP_CALL( addConflictBounds(scip, var, bdchgidx, &reqpseudoobjval) );
2218  }
2219 
2220  return SCIP_OKAY;
2221 }
2222 
2223 /** propagates the given variable against the cutoff bound */
2224 static
2226  SCIP* scip, /**< SCIP data structure */
2227  SCIP_PROP* prop, /**< propagator, or NULL */
2228  SCIP_VAR* var, /**< variable to propagate */
2229  int inferinfo, /**< inference information to store with the bound change */
2230  SCIP_Real objchg, /**< objective change */
2231  SCIP_Real cutoffbound, /**< cutoff bound to use */
2232  SCIP_Real pseudoobjval, /**< pseudo objective value to use */
2233  SCIP_Bool local, /**< local or global propagation */
2234  SCIP_Bool* tightened /**< pointer to store if the variable domain was tightened */
2235  )
2236 {
2237  SCIP_Real lb;
2238  SCIP_Real ub;
2239  SCIP_Real newbd;
2240  SCIP_Bool infeasible;
2241 
2242  assert(!SCIPisZero(scip, objchg));
2243  assert(!SCIPisInfinity(scip, -pseudoobjval));
2244  assert(!SCIPisInfinity(scip, cutoffbound));
2245  assert(SCIPisLT(scip, pseudoobjval, cutoffbound) );
2246  assert(tightened != NULL);
2247 
2248  *tightened = FALSE;
2249 
2250  /* collect bounds of the variable */
2251  if( local )
2252  {
2253  assert(prop != NULL);
2254  lb = SCIPvarGetLbLocal(var);
2255  ub = SCIPvarGetUbLocal(var);
2256  }
2257  else
2258  {
2259  lb = SCIPvarGetLbGlobal(var);
2260  ub = SCIPvarGetUbGlobal(var);
2261  }
2262 
2263  if( SCIPisFeasEQ(scip, lb, ub) )
2264  return SCIP_OKAY;
2265 
2266  /* depending on the objective contribution we can try to tighten the lower or upper bound of the variable */
2267  if( objchg > 0.0 )
2268  {
2269  newbd = lb + (cutoffbound - pseudoobjval) / objchg;
2270 
2271  if( local )
2272  {
2273  SCIP_CALL( SCIPinferVarUbProp(scip, var, newbd, prop, inferinfo, FALSE, &infeasible, tightened) );
2274  assert(!infeasible);
2275 
2276  if( *tightened ) /* might not be tightened due to numerical reasons */
2277  {
2278  SCIPdebugMessage(" -> new (local) upper bound of variable <%s>[%g,%g]: %g, objective change <%g>, pseudo objective <%g>, cutoff bound <%g>\n",
2279  SCIPvarGetName(var), lb, ub, newbd, objchg, pseudoobjval, cutoffbound);
2280  }
2281  }
2282  else
2283  {
2284  SCIP_CALL( SCIPtightenVarUbGlobal(scip, var, newbd, FALSE, &infeasible, tightened) );
2285  assert(!infeasible);
2286 
2287  if( *tightened )
2288  {
2289  SCIPdebugMessage(" -> new (global) upper bound of variable <%s>[%g,%g]: %g, objective change <%g>, pseudo objective <%g>, cutoff bound <%g>\n",
2290  SCIPvarGetName(var), lb, ub, newbd, objchg, pseudoobjval, cutoffbound);
2291  }
2292  }
2293  }
2294  else
2295  {
2296  newbd = ub + (cutoffbound - pseudoobjval) / objchg;
2297 
2298  if( local )
2299  {
2300  SCIP_CALL( SCIPinferVarLbProp(scip, var, newbd, prop, inferinfo, FALSE, &infeasible, tightened) );
2301  assert(!infeasible);
2302 
2303  if( *tightened ) /* might not be tightened due to numerical reasons */
2304  {
2305  SCIPdebugMessage(" -> new (local) lower bound of variable <%s>[%g,%g]: %g, objective change <%g>, pseudo objective <%g>, cutoff bound <%g>\n",
2306  SCIPvarGetName(var), lb, ub, newbd, objchg, pseudoobjval, cutoffbound);
2307  }
2308  }
2309  else
2310  {
2311  SCIP_CALL( SCIPtightenVarLbGlobal(scip, var, newbd, FALSE, &infeasible, tightened) );
2312  assert(!infeasible);
2313 
2314  if( *tightened )
2315  {
2316  SCIPdebugMessage(" -> new (global) lower bound of variable <%s>[%g,%g]: %g, objective change <%g>, pseudo objective <%g>, cutoff bound <%g>\n",
2317  SCIPvarGetName(var), lb, ub, newbd, objchg, pseudoobjval, cutoffbound);
2318  }
2319  }
2320  }
2321 
2322  return SCIP_OKAY;
2323 }
2324 
2325 /** propagates the given binary variable against the cutoff bound */
2326 static
2328  SCIP* scip, /**< SCIP data structure */
2329  SCIP_PROP* prop, /**< propagator, or NULL */
2330  SCIP_VAR* var, /**< variable to propagate */
2331  int pos, /**< position of the variable in the corresponding propdata variable array */
2332  SCIP_Real cutoffbound, /**< cutoff bound to use */
2333  SCIP_Real pseudoobjval, /**< pseudo objective value to use */
2334  SCIP_Bool* tightened, /**< pointer to store if the variable domain was tightened */
2335  SCIP_Bool* cutoff, /**< pointer to store if a cutoff was detected */
2336  SCIP_Bool local /**< propagate local bounds, otherwise global bounds */
2337  )
2338 {
2339  SCIP_PROPDATA* propdata;
2340  SCIP_OBJIMPLICS* objimplics;
2341  SCIP_Real lbobjchg;
2342  SCIP_Real ubobjchg;
2343  SCIP_Real objchg;
2344 
2345  assert(SCIPvarIsBinary(var));
2346 
2347  propdata = SCIPpropGetData(prop);
2348  assert(propdata != NULL);
2349 
2350  objimplics = propdata->minactimpls[pos];
2351  assert(objimplics != NULL);
2352 
2353  /* get objective change in case of fixing the variable to its lower bound (that is zero) */
2354  SCIP_CALL( getMinactObjchg(scip, var, objimplics, NULL, SCIP_BOUNDTYPE_LOWER, local, &lbobjchg) );
2355  assert(!SCIPisNegative(scip, lbobjchg));
2356 
2357  /* get objective change in case of fixing the variable to its upper bound (that is one) */
2358  SCIP_CALL( getMinactObjchg(scip, var, objimplics, NULL, SCIP_BOUNDTYPE_UPPER, local, &ubobjchg) );
2359  assert(!SCIPisNegative(scip, ubobjchg));
2360 
2361  (*tightened) = FALSE;
2362 
2363  /* nothing can be done if the objective contribution is zero independently of the bound */
2364  if( SCIPisZero(scip, lbobjchg) && SCIPisZero(scip, ubobjchg) )
2365  return SCIP_OKAY;
2366 
2367  /* if the lbobjchg and ubobjchg are both able to fix the variable to its upper (1.0) or lower (0.0) bound,
2368  * respectively, we detected an cutoff
2369  *
2370  * @note There is no need to use SCIPisFeasLT() in case the objective is integral since the cutoff bound in that case
2371  * is the upper bound minus 1 plus the SCIPcutoffbounddelta() (which is MIN(100.0 * feastol, 0.0001)). However,
2372  * if the objective is not integral we have to check w.r.t. an epsilon to avoid numerical problems.
2373  */
2374  if( SCIPisFeasLT(scip, cutoffbound, pseudoobjval + ubobjchg) && SCIPisFeasLT(scip, cutoffbound, pseudoobjval + lbobjchg) )
2375  {
2376  /* check if conflict analysis is applicable */
2377  if( local && SCIPisConflictAnalysisApplicable(scip) )
2378  {
2379  assert(SCIPgetDepth(scip) > 0);
2380 
2381  /* initialize conflict analysis */
2383 
2384  /* add all variable whose best bound changes increased the pseudo objective value above to cutoff bound */
2385  SCIP_CALL( resolvePropagation(scip, propdata, pseudoobjval, NULL, -1, SCIP_BOUNDTYPE_UPPER, NULL) );
2386 
2387  /* analyze the conflict */
2388  SCIP_CALL( SCIPanalyzeConflict(scip, 0, NULL) );
2389  }
2390 
2391  (*cutoff) = TRUE;
2392  }
2393  else
2394  {
2395  /* try to tighten the variable bound use the larger objective contribution */
2396  if( lbobjchg > ubobjchg )
2397  objchg = -lbobjchg;
2398  else
2399  objchg = ubobjchg;
2400 
2401  SCIP_CALL( propagateCutoffboundVar(scip, prop, var, pos, objchg, cutoffbound, pseudoobjval, local, tightened) );
2402  }
2403 
2404  return SCIP_OKAY;
2405 }
2406 
2407 /** globally propagates if a new cutoff bound or global pseudo objective value (minimum activity of the objective
2408  * function) is available
2409  */
2410 static
2412  SCIP* scip, /**< SCIP data structure */
2413  SCIP_PROP* prop, /**< propagator */
2414  int* nchgbds, /**< pointer to store the number of bound changes */
2415  SCIP_Bool* cutoff /**< pointer to store if a cutoff was detected */
2416  )
2418  SCIP_PROPDATA* propdata;
2419  SCIP_VAR** minactvars;
2420  SCIP_VAR** objintvars;
2421  SCIP_VAR* var;
2422  SCIP_Bool tightened;
2423  SCIP_Real pseudoobjval;
2424  SCIP_Real cutoffbound;
2425  int nminactvars;
2426  int nobjintvars;
2427  int v;
2428 
2429  /* this method should not be called in the root node of the search tree since the standard propagation already does
2430  * the job
2431  */
2432  assert(SCIPgetDepth(scip) > 0);
2433 
2434  propdata = SCIPpropGetData(prop);
2435  assert(propdata != NULL);
2436 
2437  pseudoobjval = SCIPgetGlobalPseudoObjval(scip);
2438  cutoffbound = propdata->cutoffbound;
2439 
2440  /* nothing can be done if the global pseudo objective is minus infinity */
2441  if( SCIPisInfinity(scip, -pseudoobjval) )
2442  return SCIP_OKAY;
2443 
2444  /* check if the global pseudo objective value (minimum activity of the objective function) is greater or equal to
2445  * the cutoff bound
2446  */
2447  if( SCIPisGE(scip, pseudoobjval, cutoffbound) )
2448  {
2449  *cutoff = TRUE;
2450  return SCIP_OKAY;
2451  }
2452 
2453  minactvars = propdata->minactvars;
2454  objintvars = propdata->objintvars;
2455  nminactvars = propdata->nminactvars;
2456  nobjintvars = propdata->nobjintvars;
2457 
2458 #ifndef NDEBUG
2459  checkGlbfirstnonfixed(scip, propdata);
2460 #endif
2461 
2462  *cutoff = FALSE;
2463 
2464  /* always propagate the binary variables completely */
2465  for( v = propdata->glbfirstnonfixed; v < nminactvars; ++v )
2466  {
2467  var = minactvars[v];
2468  assert(var != NULL);
2469 
2470  /* check if the variables is already globally fixed; if so continue with the potential candidate */
2471  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5)
2472  continue;
2473 
2474  /* propagates the cutoff bound for the given binary variable */
2475  SCIP_CALL( propagateCutoffboundBinvar(scip, prop, var, v, cutoffbound, pseudoobjval, &tightened, cutoff, FALSE) );
2476 
2477  /* the binary variables are sorted in non-increasing manner w.r.t. the absolute value of their objective
2478  * contribution w.r.t. minimum activity (pseudo objective value) of the objective function; these values are the
2479  * increase in the pseudo objective activity we would get if we fix the variable to its worse bound; hence, we can
2480  * stop if for a variable this potential increase is not enough too exceed the cutoff bound;
2481  */
2482  if( !tightened )
2483  {
2484  SCIPdebugMessage("interrupt global pseudo objective propagation w.r.t. cutoff bound <%.15g> for binary variables after %d from %d binary variables\n",
2485  cutoffbound, v, nminactvars);
2486  break;
2487  }
2488 
2489  if( *cutoff )
2490  return SCIP_OKAY;
2491 
2492  /* @note The variable might not be globally fixed right away since this would destroy the local internal
2493  * data structure of a search node; the bound change is in that case pending; hence we cannot assert
2494  * that the variable is globally fixed
2495  */
2496  (*nchgbds)++;
2497  }
2498  propdata->glbfirstnonfixed = v;
2499  propdata->firstnonfixed = MAX(propdata->firstnonfixed, v);
2500 
2501  /* check all binary variables which could potentially be fixed */
2502  for( ; v < nminactvars && cutoffbound - pseudoobjval < propdata->minactimpls[v]->maxobjchg; ++v )
2503  {
2504  var = minactvars[v];
2505  assert(var != NULL);
2506 
2507  /* check if the variables is already globally fixed; if so continue with the potential candidate */
2508  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5)
2509  continue;
2510 
2511  /* propagates the cutoff bound for the given binary variable */
2512  SCIP_CALL( propagateCutoffboundBinvar(scip, prop, var, v, cutoffbound, pseudoobjval, &tightened, cutoff, FALSE) );
2513 
2514  /* check if the domain of the variable was reduced */
2515  if( tightened )
2516  (*nchgbds)++;
2517 
2518  if( *cutoff )
2519  return SCIP_OKAY;
2520  }
2521 
2522 #if 0 /* might fail, but is not a real error, still need to investigate */
2523 #ifndef NDEBUG
2524  /* check that the abort criteria for the binary variables works */
2525  for( ; v < nminactvars; ++v )
2526  {
2527  assert(cutoffbound - pseudoobjval >= propdata->minactimpls[v]->maxobjchg);
2528 
2529  var = minactvars[v];
2530  assert(var != NULL);
2531 
2532  /* check if the variable is already locally fixed; in that case we just continue with the next potential
2533  * candidate
2534  */
2535  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5)
2536  continue;
2537 
2538  /* propagates the cutoff bound for the given binary variable */
2539  SCIP_CALL( propagateCutoffboundBinvar(scip, prop, var, v, cutoffbound, pseudoobjval, &tightened, cutoff, FALSE) );
2540  assert(!tightened);
2541  assert(!(*cutoff));
2542  }
2543 #endif
2544 #endif
2545 
2546  /* propagate the none binary variables completely */
2547  for( v = 0; v < nobjintvars; ++v )
2548  {
2549  var = objintvars[v];
2550  assert(var != NULL);
2551  assert(!SCIPisZero(scip, SCIPvarGetObj(var)));
2552 
2553  /* try to tighten the bound of the variable */
2554  SCIP_CALL( propagateCutoffboundVar(scip, NULL, var, -1, SCIPvarGetObj(var), cutoffbound, pseudoobjval, FALSE, &tightened) );
2555 
2556  /* check if the domain of the variable was reduced */
2557  if( tightened )
2558  (*nchgbds)++;
2559  }
2560 
2561  propdata->glbpropagated = TRUE;
2562 
2563  return SCIP_OKAY;
2564 }
2565 
2566 /** propagates the cutoff bound for binary variables (c*x <= cutoff) */
2567 static
2569  SCIP* scip, /**< SCIP data structure */
2570  SCIP_PROP* prop, /**< propagator */
2571  SCIP_Real cutoffbound, /**< cutoff bound to use */
2572  SCIP_Real pseudoobjval, /**< pseudo objective value to use */
2573  int* nfixedvars, /**< pointer to store the number of fixed variables */
2574  SCIP_Bool* cutoff /**< pointer to store if a cutoff was detected */
2575  )
2576 {
2577  SCIP_PROPDATA* propdata;
2578  SCIP_VAR** minactvars;
2579  SCIP_VAR* var;
2580  SCIP_Bool tightened;
2581  int nminactvars;
2582  int v;
2583 
2584  propdata = SCIPpropGetData(prop);
2585  assert(propdata != NULL);
2586 
2587  minactvars = propdata->minactvars;
2588  nminactvars = propdata->nminactvars;
2589  assert(nminactvars == 0 || minactvars != NULL);
2590 
2591  /* always propagate the binary variables completely; note that the variables before the firstnonfixed indexed are
2592  * already locally fixed and those before glbfirstnonfixed are already globally fixed
2593  */
2594 
2595 #ifndef NDEBUG
2596  /* check that the variables before glbfirstnonfixed are globally fixed */
2597  checkGlbfirstnonfixed(scip, propdata);
2598 
2599  /* check that the variables before firstnonfixed are locally fixed */
2600  for( v = propdata->glbfirstnonfixed; v < propdata->firstnonfixed; ++v )
2601  {
2602  var = minactvars[v];
2603  assert(var != NULL);
2604 
2605  assert(SCIPvarGetLbLocal(var) > 0.5 || SCIPvarGetUbLocal(var) < 0.5);
2606  }
2607 #endif
2608 
2609  (*cutoff) = FALSE;
2610 
2611  for( v = propdata->firstnonfixed; v < nminactvars; ++v )
2612  {
2613  var = minactvars[v];
2614  assert(var != NULL);
2615 
2616  /* check if the variable is already locally fixed; in that case we just continue with the next potential
2617  * candidate
2618  */
2619  if( SCIPvarGetLbLocal(var) > 0.5 || SCIPvarGetUbLocal(var) < 0.5)
2620  continue;
2621 
2622  /* propagates the cutoff bound for the given binary variable */
2623  SCIP_CALL( propagateCutoffboundBinvar(scip, prop, var, v, cutoffbound, pseudoobjval, &tightened, cutoff, TRUE) );
2624 
2625  /* the binary variables are sorted in non-increasing manner w.r.t. the absolute value of their objective
2626  * contribution w.r.t. minimum activity of the objective function; These values are the increase in the pseudo
2627  * objective activity (minimum activity of the objective function) we would get if we fix the variable to its
2628  * worse bound; hence, we can stop if for a variable this potential increase is not enough too exceed the cutoff
2629  * bound;
2630  */
2631  if( !tightened )
2632  {
2633  SCIPdebugMessage("interrupt local pseudo objective propagation w.r.t. cutoff bound <%.15g> for binary variables after %d from %d binary variables\n",
2634  cutoffbound, v, nminactvars);
2635  break;
2636  }
2637 
2638  if( *cutoff )
2639  return SCIP_OKAY;
2640 
2641  /* check that the binary variable is locally fixed */
2642  assert(SCIPvarGetLbLocal(var) > 0.5 || SCIPvarGetUbLocal(var) < 0.5);
2643  (*nfixedvars)++;
2644  }
2645  propdata->firstnonfixed = v;
2646 
2647  /* check all binary variables which could potentially be fixed */
2648  for( ; v < nminactvars && cutoffbound - pseudoobjval < propdata->minactimpls[v]->maxobjchg; ++v )
2649  {
2650  var = minactvars[v];
2651  assert(var != NULL);
2652 
2653  /* check if the variable is already locally fixed; in that case we just continue with the next potential
2654  * candidate
2655  */
2656  if( SCIPvarGetLbLocal(var) > 0.5 || SCIPvarGetUbLocal(var) < 0.5)
2657  continue;
2658 
2659  /* propagates the cutoff bound for the given binary variable */
2660  SCIP_CALL( propagateCutoffboundBinvar(scip, prop, var, v, cutoffbound, pseudoobjval, &tightened, cutoff, TRUE) );
2661 
2662  if( tightened )
2663  {
2664  assert(SCIPvarGetLbLocal(var) > 0.5 || SCIPvarGetUbLocal(var) < 0.5);
2665  (*nfixedvars)++;
2666  }
2667 
2668  if( *cutoff )
2669  return SCIP_OKAY;
2670  }
2671 
2672 #if 0 /* might fail, but is not a real error, still need to investigate */
2673 #ifndef NDEBUG
2674  /* check that the abort criteria for the binary variables works */
2675  for( ; v < nminactvars; ++v )
2676  {
2677  var = minactvars[v];
2678  assert(var != NULL);
2679 
2680  assert(cutoffbound - pseudoobjval >= propdata->minactimpls[v]->maxobjchg);
2681 
2682  /* check if the variable is already locally fixed; in that case we just continue with the next potential
2683  * candidate
2684  */
2685  if( SCIPvarGetLbLocal(var) > 0.5 || SCIPvarGetUbLocal(var) < 0.5)
2686  continue;
2687 
2688  /* propagates the cutoff bound for the given binary variable */
2689  SCIP_CALL( propagateCutoffboundBinvar(scip, prop, var, v, cutoffbound, pseudoobjval, &tightened, cutoff, TRUE) );
2690  assert(!tightened);
2691  assert(!(*cutoff));
2692  }
2693 #endif
2694 #endif
2695 
2696  return SCIP_OKAY;
2697 }
2698 
2699 /** propagates the cutoff bound c*x <= cutoff */
2700 static
2702  SCIP* scip, /**< SCIP data structure */
2703  SCIP_PROP* prop, /**< propagator */
2704  SCIP_RESULT* result /**< pointer to store the result of the callback method */
2705  )
2706 {
2707  SCIP_PROPDATA* propdata;
2708  SCIP_Real pseudoobjval;
2709  SCIP_Real cutoffbound;
2710  SCIP_Bool cutoff;
2711  SCIP_Bool tightened;
2712  int nchgbds;
2713 
2714  assert(result != NULL);
2715 
2716  (*result) = SCIP_DIDNOTRUN;
2717 
2718  propdata = SCIPpropGetData(prop);
2719  assert(propdata != NULL);
2720 
2721  /* get current pseudo objective value (minimum activity of the objective function) and cutoff bound */
2722  pseudoobjval = SCIPgetPseudoObjval(scip);
2723  if( SCIPisInfinity(scip, -pseudoobjval) )
2724  return SCIP_OKAY;
2725  cutoffbound = SCIPgetCutoffbound(scip);
2726  if( SCIPisInfinity(scip, cutoffbound) )
2727  return SCIP_OKAY;
2728 
2729  /* @note A new global pseudo objective value could be used to retrieve global fixings. There is, however, no need to
2730  * check if a new global pseudo objective value is available. This is the case since a new (better) global
2731  * pseudo activity implicis that a global bound change was performed. That causes that the root node of the
2732  * search tree get marked for repropagation. That will result in propagation call of the pseudo objective
2733  * propagator.
2734  */
2735 
2736  /* check current cutoff bound */
2737  if( cutoffbound < propdata->cutoffbound )
2738  {
2739  propdata->glbpropagated = FALSE;
2740  propdata->cutoffbound = cutoffbound;
2741  }
2742 
2743  nchgbds = 0;
2744  cutoff = FALSE;
2745  (*result) = SCIP_DIDNOTFIND;
2746 
2747  /* check if we have a new cutoff bound; in that case we globally propagate this new bound
2748  *
2749  * @note there is no need to propagate the cutoff bound if we are in the root node since this will be done by the
2750  * standard local propagation
2751  */
2752  if( propdata->propcutoffbound && !propdata->glbpropagated && SCIPgetDepth(scip) > 0 )
2753  {
2754  /* first globally propagate new cutoff bound or pseudo objective activity */
2755  SCIP_CALL( propagateCutoffboundGlobally(scip, prop, &nchgbds, &cutoff) );
2756 
2757  if( cutoff )
2758  {
2759  /* we are done with solving since a global pseudo activity is greater or equal to the cutoff bound */
2760  SCIP_CALL( SCIPcutoffNode(scip, SCIPgetRootNode(scip)) );
2761 
2762  (*result) = SCIP_CUTOFF;
2763  return SCIP_OKAY;
2764  }
2765 
2766  /* check if the global propagation cut off the active/current node */
2767  if( SCIPgetCutoffdepth(scip) <= SCIPgetDepth(scip) )
2768  {
2769  (*result) = SCIP_CUTOFF;
2770  return SCIP_OKAY;
2771  }
2772  }
2773 
2774  /* check if the pseudo objective value (minimum activity of the objective function) is greater or equal to the cutoff
2775  * bound
2776  */
2777  if( SCIPisGE(scip, pseudoobjval, cutoffbound) )
2778  {
2779  SCIPdebugMessage("pseudo objective value <%g> exceeds cutoff bound <%g>\n", pseudoobjval, cutoffbound);
2780 
2781  /* check if conflict analysis is applicable */
2783  {
2784  assert(SCIPgetDepth(scip) > 0);
2785 
2786  /* initialize conflict analysis */
2788 
2789  /* add all variable whose best bound changes increased the pseudo objective value above to cutoff bound */
2790  SCIP_CALL( resolvePropagation(scip, propdata, cutoffbound, NULL, -1, SCIP_BOUNDTYPE_UPPER, NULL) );
2791 
2792  /* analyze the conflict */
2793  SCIP_CALL( SCIPanalyzeConflict(scip, 0, NULL) );
2794  }
2795  (*result) = SCIP_CUTOFF;
2796 
2797  return SCIP_OKAY;
2798  }
2799 
2800  SCIPdebugMessage("propagating pseudo objective function (pseudoobj: %g, cutoffbound: %g)\n", pseudoobjval, cutoffbound);
2801 
2802  /* propagate binary variables */
2803  SCIP_CALL( propagateCutoffboundBinvars(scip, prop, cutoffbound, pseudoobjval, &nchgbds, &cutoff) );
2804 
2805  if( cutoff )
2806  {
2807  (*result) = SCIP_CUTOFF;
2808  return SCIP_OKAY;
2809  }
2810 
2811  /* tighten domains of none binary variables, if they would increase the pseudo objective value above the cutoff
2812  * bound
2813  */
2814  if( propdata->propfullinroot && SCIPgetDepth(scip) == 0 )
2815  {
2816  SCIP_VAR** objintvars;
2817  SCIP_VAR* var;
2818  SCIP_Real objval;
2819  int nobjintvars;
2820  int v;
2821 
2822  objintvars = propdata->objintvars;
2823  nobjintvars = propdata->nobjintvars;
2824  assert(nobjintvars == 0 || objintvars != NULL);
2825 
2826  /* propagate all none binary variables */
2827  for( v = 0; v < nobjintvars; ++v )
2828  {
2829  var = objintvars[v];
2830  assert(var != NULL);
2831 
2832  objval = SCIPvarGetObj(var);
2833  assert(!SCIPisZero(scip, objval));
2834 
2835  /* try to tighten the bound of the variable */
2836  SCIP_CALL( propagateCutoffboundVar(scip, NULL, var, -1, objval, cutoffbound, pseudoobjval, FALSE, &tightened) );
2837 
2838  /* check if the domain of the variable was reduced */
2839  if( tightened )
2840  nchgbds++;
2841  }
2842  }
2843  else
2844  {
2845  SCIP_VAR** objintvars;
2846  SCIP_VAR* var;
2847  SCIP_Real objval;
2848  int nobjintvars;
2849  int nmaxuseless;
2850  int nuseless;
2851  int c;
2852  int v;
2853 
2854  objintvars = propdata->objintvars;
2855  nobjintvars = propdata->nobjintvars;
2856  assert(nobjintvars == 0 || objintvars != NULL);
2857 
2858  /* compute maximum number of useless propagations before aborting */
2859  nmaxuseless = MAX(propdata->minuseless, (int)propdata->maxvarsfrac*(nobjintvars));
2860 
2861  nuseless = 0;
2862  v = propdata->lastvarnum;
2863 
2864  for( c = 0; c < nobjintvars && nuseless < nmaxuseless; ++c )
2865  {
2866  v++;
2867  if( v >= nobjintvars )
2868  v = 0;
2869 
2870  var = objintvars[v];
2871  assert(var != NULL);
2872 
2873  objval = SCIPvarGetObj(var);
2874  assert(!SCIPisZero(scip, objval));
2875 
2876  /* try to tighten the bound of the variable */
2877  SCIP_CALL( propagateCutoffboundVar(scip, prop, var, -1, objval, cutoffbound, pseudoobjval, TRUE, &tightened) );
2878 
2879  /* check if the domain of the variable was reduced */
2880  if( tightened )
2881  nchgbds++;
2882  else
2883  nuseless++;
2884  }
2885  propdata->lastvarnum = v;
2886  }
2887 
2888  /* check if we chanced bounds */
2889  if( nchgbds > 0 )
2890  (*result) = SCIP_REDUCEDDOM;
2891 
2892  return SCIP_OKAY;
2893 }
2894 
2895 /** recalculates the maximum objective pseudoactivity */
2896 static
2898  SCIP* scip, /**< SCIP data structure */
2899  SCIP_PROPDATA* propdata /**< propagator data */
2900  )
2901 {
2902  SCIP_VAR** vars;
2903  SCIP_Real objval;
2904  SCIP_Real contrib;
2905  int nvars;
2906  int v;
2907 
2908  assert(propdata != NULL);
2909 
2910  /* get problem variables */
2911  vars = SCIPgetVars(scip);
2912  nvars = SCIPgetNVars(scip);
2913 
2914  /* calculate current max pseudo activity and largest contribution */
2915  propdata->maxpseudoobjact = 0.0;
2916  propdata->maxpseudoobjactinf = 0;
2917 
2918  for( v = 0; v < nvars; ++v )
2919  {
2920  objval = SCIPvarGetObj(vars[v]);
2921  if( SCIPisPositive(scip, objval) )
2922  {
2923  contrib = SCIPvarGetUbGlobal(vars[v]);
2924  if( !SCIPisInfinity(scip, contrib) )
2925  contrib *= objval;
2926  }
2927  else if( SCIPisNegative(scip, objval) )
2928  {
2929  contrib = SCIPvarGetLbGlobal(vars[v]);
2930  if( !SCIPisInfinity(scip, -contrib) )
2931  contrib *= objval;
2932  else
2933  contrib *= -1.0;
2934  }
2935  else
2936  continue;
2937 
2938  if( SCIPisInfinity(scip, contrib) )
2939  propdata->maxpseudoobjactinf++;
2940  else
2941  propdata->maxpseudoobjact += contrib;
2942  }
2943 }
2944 
2945 /** updates the pseudo objective activity if necessary */
2946 static
2948  SCIP* scip, /**< SCIP data structure */
2949  SCIP_PROPDATA* propdata /**< propagator data */
2950  )
2951 {
2952  assert(propdata != NULL);
2954  /* if necessary, calculate the maximum pseudo objective activity */
2955  if( propdata->maxpseudoobjact == SCIP_INVALID ) /*lint !e777*/
2956  calcMaxObjPseudoactivity(scip, propdata);
2957  assert(propdata->maxpseudoobjact != SCIP_INVALID); /*lint !e777*/
2958 }
2959 
2960 /** returns the residual pseudo objective activity without the given value */
2961 static
2963  SCIP* scip, /**< SCIP data structure */
2964  SCIP_PROPDATA* propdata, /**< propagator data */
2965  SCIP_Real contrib /**< value to eliminate from pseudo objective activity */
2966  )
2967 {
2968  SCIP_Real residual;
2969 
2970  assert(propdata != NULL);
2971 
2972  /* if necessary, calculate the maximum pseudo objective activity */
2973  if( propdata->maxpseudoobjact == SCIP_INVALID ) /*lint !e777*/
2974  calcMaxObjPseudoactivity(scip, propdata);
2975  assert(propdata->maxpseudoobjact != SCIP_INVALID); /*lint !e777*/
2976 
2977  if( SCIPisInfinity(scip, contrib) )
2978  {
2979  assert(propdata->maxpseudoobjactinf >= 1);
2980  /* check if this variable yields the only infinite contribution */
2981  if( propdata->maxpseudoobjactinf == 1 )
2982  residual = propdata->maxpseudoobjact;
2983  else
2984  residual = SCIPinfinity(scip);
2985  }
2986  else
2987  {
2988  /* check if there is an infinite contribution */
2989  if( propdata->maxpseudoobjactinf >= 1 )
2990  residual = SCIPinfinity(scip);
2991  else
2992  residual = propdata->maxpseudoobjact - contrib;
2993  }
2994 
2995  return residual;
2996 }
2997 
2998 /** returns the residual pseudo objective activity */
2999 static
3001  SCIP* scip, /**< SCIP data structure */
3002  SCIP_PROPDATA* propdata, /**< propagator data */
3003  SCIP_VAR* var /**< variable to get residual activity for */
3004  )
3005 {
3006  SCIP_Real objval;
3007  SCIP_Real contrib;
3008 
3009  assert(propdata != NULL);
3010 
3011  contrib = 0.0;
3012  objval = SCIPvarGetObj(var);
3014  {
3015  contrib = SCIPvarGetUbGlobal(var);
3016  if( !SCIPisInfinity(scip, contrib) )
3017  contrib *= objval;
3018  }
3019  else
3020  {
3022  contrib = SCIPvarGetLbGlobal(var);
3023  if( !SCIPisInfinity(scip, -contrib) )
3024  contrib *= objval;
3025  else
3026  contrib *= -1.0;
3027  }
3028 
3029  return getMaxObjPseudoactivityResidualValue(scip, propdata, contrib);
3030 }
3031 
3032 /** returns the maximum pseudo objective activity of the objective function */
3033 static
3035  SCIP* scip, /**< SCIP data structure */
3036  SCIP_PROPDATA* propdata /**< propagator data */
3037  )
3038 {
3039  return getMaxObjPseudoactivityResidualValue(scip, propdata, 0.0);
3041 
3042 /** propagates the global domain of the given binary variable against the lower bound (c*x >= lowerbound) */
3043 static
3045  SCIP* scip, /**< SCIP data structure */
3046  SCIP_VAR* var, /**< variable to propagate */
3047  SCIP_Real lowerbound, /**< lower bound to use */
3048  SCIP_Real maxpseudoobjact, /**< maximum pseudo objective activity */
3049  SCIP_Bool useimplics, /**< should implications be used */
3050  SCIP_Bool* infeasible, /**< pointer to store if the variable domain got empty, infeasible */
3051  SCIP_Bool* tightened /**< pointer to store if the variable domain was tightened */
3052  )
3053 {
3054  SCIP_Real lbobjchg;
3055  SCIP_Real ubobjchg;
3056 
3057  assert(SCIPvarIsBinary(var));
3058  assert(SCIPisLE(scip, lowerbound, maxpseudoobjact));
3059  assert(!SCIPisInfinity(scip, maxpseudoobjact));
3060 
3061  /*@todo Instead of running always over all implications use SCIP_OBJIMPLICS in the same way as for the propagation of
3062  * the minimum activity against the cutoff bound. If so we could use the cliques as well.
3063  */
3064 
3065  /* get contribution of variable by fixing it to its lower bound w.r.t. maximum activity of the objective function */
3066  SCIP_CALL( getMaxactObjchg(scip, var, SCIP_BOUNDTYPE_LOWER, useimplics, &lbobjchg) );
3067  assert(!SCIPisPositive(scip, lbobjchg));
3068 
3069  /* get contribution of variable by fixing it to its upper bound w.r.t. maximum activity of the objective function */
3070  SCIP_CALL( getMaxactObjchg(scip, var, SCIP_BOUNDTYPE_UPPER, useimplics, &ubobjchg) );
3071  assert(!SCIPisPositive(scip, ubobjchg));
3072 
3073  (*infeasible) = FALSE;
3074  (*tightened) = FALSE;
3075 
3076  /* if the maximum activity of the objective function without the contribution of the given variable shrinks below the
3077  * global lower bound, the contribution of the variable is need; hence, we can fix it to corresponding bound globally
3078  */
3079  if( SCIPisFeasLT(scip, maxpseudoobjact + lbobjchg, lowerbound) && SCIPisFeasLT(scip, maxpseudoobjact + ubobjchg, lowerbound) )
3080  {
3081  /* fixing the variable to zero or one leads to decreases of the maximum activity below the lower bound, hence, we
3082  * detected an cutoff
3083  */
3084  (*infeasible) = TRUE;
3085  }
3086  else if( SCIPisFeasLT(scip, maxpseudoobjact + lbobjchg, lowerbound) )
3087  {
3088  SCIP_CALL( SCIPtightenVarLbGlobal(scip, var, 1.0, FALSE, infeasible, tightened) );
3089  }
3090  else if( SCIPisFeasLT(scip, maxpseudoobjact + ubobjchg, lowerbound) )
3091  {
3092  SCIP_CALL( SCIPtightenVarLbGlobal(scip, var, 0.0, FALSE, infeasible, tightened) );
3093  }
3094 
3095  return SCIP_OKAY;
3096 }
3097 
3098 /** propagates the global domains of the given variable with non-zero objective coefficient against the lower bound
3099  * (c*x >= lowerbound)
3100  */
3101 static
3103  SCIP* scip, /**< SCIP data structure */
3104  SCIP_PROPDATA* propdata, /**< propagator data */
3105  SCIP_VAR* var, /**< variable to propagate */
3106  SCIP_Real lowerbound, /**< lower bound to use */
3107  SCIP_Bool* infeasible, /**< pointer to store if the variable domain got empty, infeasible */
3108  SCIP_Bool* tightened /**< pointer to store if the variable domain was tightened */
3109  )
3110 {
3111  SCIP_Real residual;
3112  SCIP_Real newbd;
3113  SCIP_Real objval;
3114 
3115  objval = SCIPvarGetObj(var);
3116  assert(!SCIPisZero(scip, objval));
3117 
3118  (*tightened) = FALSE;
3119 
3120  /* get residual pseudo objective activity, that is the pseudo objective activity without the given variable */
3121  residual = getMaxObjPseudoactivityResidual(scip, propdata, var);
3122 
3123  if( SCIPisInfinity(scip, residual) )
3124  return SCIP_OKAY;
3125 
3126  /* compute potential mew bound */
3127  newbd = (lowerbound - residual) / objval;
3128 
3129  /**@note In case the variable is integral we force the update of the new bound */
3130 
3131  if( objval > 0.0 )
3132  {
3133  SCIP_Real lb;
3134 
3135  lb = SCIPvarGetLbGlobal(var);
3136 
3137  if( !SCIPvarIsIntegral(var) )
3138  {
3139  SCIP_CALL( SCIPtightenVarLbGlobal(scip, var, newbd, FALSE, infeasible, tightened) );
3140  }
3141  else if( SCIPisFeasGT(scip, newbd, lb) )
3142  {
3143  SCIP_CALL( SCIPtightenVarLbGlobal(scip, var, newbd, TRUE, infeasible, tightened) );
3144  }
3145  }
3146  else
3147  {
3148  SCIP_Real ub;
3149 
3150  ub = SCIPvarGetUbGlobal(var);
3151 
3152  if( !SCIPvarIsIntegral(var) )
3153  {
3154  SCIP_CALL( SCIPtightenVarUbGlobal(scip, var, newbd, FALSE, infeasible, tightened) );
3155  }
3156  else if( SCIPisFeasLT(scip, newbd, ub) )
3157  {
3158  SCIP_CALL( SCIPtightenVarUbGlobal(scip, var, newbd, TRUE, infeasible, tightened) );
3159  }
3160  }
3161 
3162  return SCIP_OKAY;
3163 }
3164 
3165 /** propagates the global lower (dual) bound c*x >= lowerbound */
3166 static
3168  SCIP* scip, /**< SCIP data structure */
3169  SCIP_PROP* prop, /**< propagator */
3170  SCIP_RESULT* result /**< pointer to store the result of the callback method */
3171  )
3172 { /*lint --e{715}*/
3173  SCIP_PROPDATA* propdata;
3174  SCIP_Real lowerbound;
3175  SCIP_Real maxpseudoobjact;
3176  SCIP_Bool cutoff;
3177  int nchgbds;
3178 
3179  assert(result != NULL);
3180 
3181  (*result) = SCIP_DIDNOTRUN;
3182  cutoff = FALSE;
3183  nchgbds = 0;
3184 
3185  propdata = SCIPpropGetData(prop);
3186  assert(propdata != NULL);
3187  assert(propdata->nminactvars > 0 || propdata->nobjintvars > 0);
3188 
3189  /* check if there is a chance to find a reduction */
3190  lowerbound = SCIPgetLowerbound(scip);
3191 
3192  if( SCIPisInfinity(scip, -lowerbound) )
3193  return SCIP_OKAY;
3194 
3195  /* if the lower bound did not change since the last propagation as well as the global bounds of the variables with a
3196  * non-zero objective coefficient we do nothing since there is no new information available
3197  */
3198  if( SCIPisLE(scip, lowerbound, propdata->lastlowerbound) && propdata->maxpseudoobjact < SCIP_INVALID )
3199  return SCIP_OKAY;
3200 
3201  /* updates the pseudo objective activity if necessary */
3202  updateMaxObjPseudoactivity(scip, propdata);
3203 
3204  /* if more than one variable contributes an infinity to the maximal pseudo activity we can do nothing */
3205  assert(propdata->maxpseudoobjact < SCIP_INVALID);
3206  if( propdata->maxpseudoobjactinf > 1 )
3207  return SCIP_OKAY;
3208 
3209  maxpseudoobjact = getMaxObjPseudoactivity(scip, propdata);
3210  assert(!SCIPisInfinity(scip, maxpseudoobjact) || !SCIPisInfinity(scip, lowerbound));
3211 
3212 #ifndef NDEBUG
3213  /* check that the global indices are correct */
3214  checkGlbfirstnonfixed(scip, propdata);
3215 #endif
3216 
3217  /* if the maximum pseudo objective activity is smaller than the lower bound the problem is infeasible */
3218  if( SCIPisLT(scip, maxpseudoobjact, lowerbound) )
3219  cutoff = TRUE;
3220  else
3221  {
3222  SCIP_VAR** objintvars;
3223  SCIP_VAR* var;
3224  SCIP_Bool tightened;
3225  int nobjintvars;
3226  int v;
3227 
3228  if( propdata->maxpseudoobjactinf == 0 && !SCIPisInfinity(scip, maxpseudoobjact) )
3229  {
3230  SCIP_VAR** maxactvars;
3231  int nmaxactvars;
3232 
3233  maxactvars = propdata->maxactvars;
3234  nmaxactvars = propdata->nmaxactvars;
3235  assert(nmaxactvars == 0 || maxactvars != NULL);
3236 
3237  for( v = propdata->maxactfirstnonfixed; v < nmaxactvars; ++v )
3238  {
3239  var = maxactvars[v];
3240  assert(var != NULL);
3241  assert(SCIPvarIsBinary(var));
3242 
3243  /* check if the variables is already globally fixed; if so continue with the next potential candidate */
3244  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5)
3245  continue;
3246 
3247  /* try to propagate variable domain globally */
3248  SCIP_CALL( propagateLowerboundBinvar(scip, var, lowerbound, maxpseudoobjact, propdata->propuseimplics, &cutoff, &tightened) );
3249 
3250  /* the binary variables are sorted in non-increasing manner w.r.t. the absolute value of their objective
3251  * contribution w.r.t. maximum activity of the objective function; These values are the decrease we would
3252  * get with the maximum pseudo objective activity if we fix the variable to its best bound; hence, we can
3253  * stop if for a variable this potential decrease is not enough anymore too fall below the lower bound.
3254  *
3255  * @note In case a fixing was performed. The variable might not be globally fixed right away since this would
3256  * destroy the local internal data structure of a search node; the bound change is in that case pending;
3257  * hence we cannot assert that the variable is globally fixed
3258  */
3259  if( !tightened )
3260  {
3261  assert(!SCIPisInfinity(scip, propdata->maxpseudoobjact));
3262  SCIPdebugMessage("interrupt pseudo objective propagation w.r.t. lower bound <%.15g> for binary variables after %d from %d binary variables\n",
3263  lowerbound, v, nmaxactvars);
3264  break;
3265  }
3266 
3267  if( cutoff )
3268  break;
3269 
3270  /* update maximum pseudo activity since the previous global bound change might invalidated the maximum
3271  * pseudo activity
3272  */
3273  maxpseudoobjact = getMaxObjPseudoactivity(scip, propdata);
3274  nchgbds++;
3275  }
3276 
3277  /* update globally fixed index if abort criteria was applied */
3278  propdata->maxactfirstnonfixed = v;
3279 
3280  /* check all binary variables which could potentially be fixed */
3281  for( ; v < nmaxactvars && maxpseudoobjact - lowerbound < propdata->maxactchgs[v] && !cutoff; ++v )
3282  {
3283  var = maxactvars[v];
3284  assert(var != NULL);
3285  assert(SCIPvarIsBinary(var));
3286 
3287  /* check if the variables is already globally fixed; if so continue with the potential candidate */
3288  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5)
3289  continue;
3290 
3291  /* propagates the cutoff bound for the given binary variable */
3292  SCIP_CALL( propagateLowerboundBinvar(scip, var, lowerbound, maxpseudoobjact, propdata->propuseimplics, &cutoff, &tightened) );
3293 
3294  if( tightened )
3295  {
3296  /* update maximum pseudo activity since the previous global bound change might invalidated the maximum
3297  * pseudo activity
3298  */
3299  maxpseudoobjact = getMaxObjPseudoactivity(scip, propdata);
3300  nchgbds++;
3301  }
3302  }
3303 
3304 #if 0 /* might fail, but is not a real error, still need to investigate */
3305 #ifndef NDEBUG
3306  /* check that the abort criteria for the binary variables works */
3307  for( ; v < nmaxactvars && !cutoff; ++v )
3308  {
3309  var = maxactvars[v];
3310  assert(var != NULL);
3311  assert(SCIPvarIsBinary(var));
3312 
3313  /* check if the variables is already globally fixed; if so continue with the next potential candidate */
3314  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5)
3315  continue;
3316 
3317  /* try to propagate variable domain globally */
3318  SCIP_CALL( propagateLowerboundBinvar(scip, var, lowerbound, maxpseudoobjact, propdata->propuseimplics, &cutoff, &tightened) );
3319  assert(!tightened);
3320  assert(!cutoff);
3321  }
3322 #endif
3323 #endif
3324  }
3325 
3326  objintvars = propdata->objintvars;
3327  nobjintvars = propdata->nobjintvars;
3328  assert(nobjintvars == 0 || objintvars != NULL);
3329 
3330  /* propagate c*x >= lowerbound for non-binary variables */
3331  for( v = 0; v < nobjintvars && !cutoff; ++v )
3332  {
3333  var = objintvars[v];
3334  assert(var != NULL);
3335  assert(!SCIPisZero(scip, SCIPvarGetObj(var)));
3336 
3337  /* try to propagate variable domain globally */
3338  SCIP_CALL( propagateLowerboundVar(scip, propdata, var, lowerbound, &cutoff, &tightened) );
3339 
3340  if( tightened )
3341  nchgbds++;
3342  }
3343  }
3344 
3345  /* evaluate propagation results */
3346  if( cutoff )
3347  {
3348  /* we are done with solving since a global bound change is infeasible: cutoff root node */
3349  SCIP_CALL( SCIPcutoffNode(scip, SCIPgetRootNode(scip)) );
3350  (*result) = SCIP_CUTOFF;
3351  }
3352  else if( nchgbds > 0 )
3353  (*result) = SCIP_REDUCEDDOM;
3354 
3355  /* remember the lower bound which we already propagated */
3356  propdata->lastlowerbound = lowerbound;
3357 
3358  return SCIP_OKAY;
3359 }
3360 
3361 
3362 /*
3363  * Callback methods of propagator
3364  */
3365 
3366 /** copy method for propagator plugins (called when SCIP copies plugins) */
3367 static
3368 SCIP_DECL_PROPCOPY(propCopyPseudoobj)
3369 { /*lint --e{715}*/
3370  assert(scip != NULL);
3371  assert(prop != NULL);
3372  assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
3373 
3374  /* call inclusion method of propagator */
3376 
3377  return SCIP_OKAY;
3378 }
3379 
3380 /** destructor of propagator to free user data (called when SCIP is exiting) */
3381 static
3382 SCIP_DECL_PROPFREE(propFreePseudoobj)
3383 { /*lint --e{715}*/
3384  SCIP_PROPDATA* propdata;
3385 
3386  /* free propagator data */
3387  propdata = SCIPpropGetData(prop);
3388  SCIPfreeMemory(scip, &propdata);
3389  SCIPpropSetData(prop, NULL);
3390 
3391  return SCIP_OKAY;
3392 }
3393 
3394 
3395 /** solving process initialization method of propagator (called when branch and bound process is about to begin) */
3396 static
3397 SCIP_DECL_PROPINITSOL(propInitsolPseudoobj)
3398 {
3399  SCIP_PROPDATA* propdata;
3400 
3401  propdata = SCIPpropGetData(prop);
3402  assert(propdata != NULL);
3404  /* do nothing if active pricer are present and force flag is not TRUE */
3405  if( !propdata->force && SCIPgetNActivePricers(scip) > 0 )
3406  return SCIP_OKAY;
3407 
3408  /* if active pricer are present we want to catch the variable added event */
3409  if( SCIPgetNActivePricers(scip) > 0 )
3410  {
3411  assert(!propdata->catchvaradded);
3412  SCIP_CALL( SCIPcatchEvent(scip, SCIP_EVENTTYPE_VARADDED, propdata->eventhdlr, (SCIP_EVENTDATA*)propdata, NULL) );
3413  propdata->catchvaradded = TRUE;
3414  }
3415 
3416  return SCIP_OKAY;
3417 }
3418 
3419 /** solving process deinitialization method of propagator (called before branch and bound process data is freed) */
3420 static
3421 SCIP_DECL_PROPEXITSOL(propExitsolPseudoobj)
3422 { /*lint --e{715}*/
3423  SCIP_PROPDATA* propdata;
3424 
3425  propdata = SCIPpropGetData(prop);
3426  assert(propdata != NULL);
3428  if( propdata->catchvaradded )
3429  {
3430  /* drop the variable added event */
3431  SCIP_CALL( SCIPdropEvent(scip, SCIP_EVENTTYPE_VARADDED, propdata->eventhdlr, (SCIP_EVENTDATA*)propdata, -1) );
3432  propdata->catchvaradded = FALSE;
3433  }
3434 
3435  /* free propagator data */
3436  SCIP_CALL( propdataExit(scip, propdata) );
3437 
3438  return SCIP_OKAY;
3439 }
3440 
3441 
3442 /** presolving method of propagator */
3443 static
3444 SCIP_DECL_PROPPRESOL(propPresolPseudoobj)
3445 { /*lint --e{715}*/
3446 
3447  SCIP_PROPDATA* propdata;
3448  SCIP_VAR** vars;
3449  SCIP_Real cutoffbound;
3450  SCIP_Real pseudoobjval;
3451  int oldnchgbds;
3452  int nvars;
3453  int v;
3454 
3455  assert(result != NULL);
3456 
3457  propdata = SCIPpropGetData(prop);
3458  assert(propdata != NULL);
3459 
3460  (*result) = SCIP_DIDNOTRUN;
3461 
3462  /* do nothing if active pricer are present and force flag is not TRUE */
3463  if( !propdata->force && SCIPgetNActivePricers(scip) > 0 )
3464  return SCIP_OKAY;
3465 
3466  /* do nothing if objective propagation is not allowed */
3467  if( !SCIPallowObjProp(scip) )
3468  return SCIP_OKAY;
3469 
3470  pseudoobjval = SCIPgetGlobalPseudoObjval(scip);
3471  if( SCIPisInfinity(scip, -pseudoobjval) )
3472  return SCIP_OKAY;
3473 
3474  cutoffbound = SCIPgetCutoffbound(scip);
3475  if( SCIPisInfinity(scip, cutoffbound) )
3476  return SCIP_OKAY;
3477 
3478  if( SCIPisGE(scip, pseudoobjval, cutoffbound) )
3479  {
3480  (*result) = SCIP_CUTOFF;
3481  return SCIP_OKAY;
3482  }
3483 
3484  /* only propagate if a new cutoff bound or global pseudo objective value is available */
3485  if( cutoffbound < propdata->cutoffbound || pseudoobjval > propdata->glbpseudoobjval )
3486  {
3487  SCIP_Real objval;
3488  SCIP_Bool tightened;
3489 
3490  (*result) = SCIP_DIDNOTFIND;
3491  oldnchgbds = *nchgbds;
3492 
3493  /* get the problem variables */
3494  vars = SCIPgetVars(scip);
3495  nvars = SCIPgetNVars(scip);
3496 
3497  /* scan the variables for pseudoobj bound reductions
3498  * (loop backwards, since a variable fixing can change the current and the subsequent slots in the vars array)
3499  */
3500  for( v = nvars - 1; v >= 0; --v )
3501  {
3502  objval = SCIPvarGetObj(vars[v]);
3503 
3504  if( SCIPisZero(scip, objval) )
3505  continue;
3506 
3507  SCIP_CALL( propagateCutoffboundVar(scip, NULL, vars[v], -1, objval, cutoffbound, pseudoobjval, FALSE, &tightened) );
3508 
3509  if( tightened )
3510  (*nchgbds)++;
3511  }
3512 
3513  /* evaluate if bound change was detected */
3514  if( *nchgbds > oldnchgbds )
3515  (*result) = SCIP_SUCCESS;
3516 
3517  /* store the old values */
3518  propdata->cutoffbound = cutoffbound;
3519  propdata->glbpseudoobjval = pseudoobjval;
3520  propdata->glbpropagated = TRUE;
3521  }
3522 
3523  return SCIP_OKAY;
3524 }
3525 
3526 /** execution method of propagator */
3527 static
3528 SCIP_DECL_PROPEXEC(propExecPseudoobj)
3529 { /*lint --e{715}*/
3530  SCIP_PROPDATA* propdata;
3531 
3532  propdata = SCIPpropGetData(prop);
3533  assert(propdata != NULL);
3535  (*result) = SCIP_DIDNOTRUN;
3536 
3537  if( SCIPinProbing(scip) )
3538  return SCIP_OKAY;
3539 
3540  if( proptiming == SCIP_PROPTIMING_DURINGLPLOOP && SCIPgetDepth(scip) != 0 )
3541  return SCIP_OKAY;
3542 
3543  /* do nothing if active pricer are present and force flag is not TRUE */
3544  if( !propdata->force && SCIPgetNActivePricers(scip) > 0 )
3545  return SCIP_OKAY;
3546 
3547  /* do not run if propagation w.r.t. objective is not allowed */
3548  if( !SCIPallowObjProp(scip) )
3549  return SCIP_OKAY;
3550 
3551  /* check if enough new variable are added (due to column generation to reinitialized the propagator data) */
3552  if( !propdata->initialized || propdata->nnewvars > propdata->maxnewvars )
3553  {
3554  /* free current propdata data */
3555  SCIP_CALL( propdataExit(scip, propdata) );
3556 
3557  /* initialize propdata data from scratch */
3558  SCIP_CALL( propdataInit(scip, propdata) );
3559  }
3560 
3561  /* nothing to do for zero objective */
3562  if( propdata->nminactvars == 0 && propdata->nmaxactvars == 0 && propdata->nobjintvars == 0 )
3563  return SCIP_OKAY;
3564 
3565  /* propagate c*x <= cutoff */
3566  SCIP_CALL( propagateCutoffbound(scip, prop, result) );
3567 
3568  if( (*result) != SCIP_CUTOFF && (propdata->nmaxactvars > 0 || propdata->nobjintvars > 0) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
3569  {
3570  SCIP_RESULT dualresult;
3571 
3572  /* propagates the global lower (dual) bound c*x >= lowerbound */
3573  SCIP_CALL( propagateLowerbound(scip, prop, &dualresult) );
3574 
3575  if( dualresult == SCIP_REDUCEDDOM || dualresult == SCIP_CUTOFF )
3576  (*result) = dualresult;
3577  }
3578 
3579  return SCIP_OKAY;
3580 }
3581 
3582 /** propagation conflict resolving method of propagator */
3583 static
3584 SCIP_DECL_PROPRESPROP(propRespropPseudoobj)
3585 { /*lint --e{715}*/
3586  SCIP_PROPDATA* propdata;
3587  SCIP_Real cutoffbound;
3588 
3589  assert(!SCIPisEQ(scip, SCIPvarGetLbGlobal(infervar), SCIPvarGetUbGlobal(infervar)));
3591  propdata = SCIPpropGetData(prop);
3592  assert(propdata != NULL);
3593 
3594  cutoffbound = SCIPgetCutoffbound(scip);
3595  assert(!SCIPisInfinity(scip, cutoffbound));
3596  assert(infervar != NULL);
3597 
3598  SCIPdebugMessage("resolve bound change <%s> %s <%g>(%g), cutoff bound <%g>\n", SCIPvarGetName(infervar),
3599  boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", SCIPvarGetLbAtIndex(infervar, bdchgidx, TRUE),
3600  SCIPvarGetLbAtIndex(infervar, bdchgidx, FALSE), cutoffbound);
3601 
3602  /* resolve the propagation of the inference variable w.r.t. required minactivity */
3603  SCIP_CALL( resolvePropagation(scip, propdata, cutoffbound, infervar, inferinfo, boundtype, bdchgidx) );
3604 
3605  (*result) = SCIP_SUCCESS;
3606 
3607  return SCIP_OKAY;
3608 }
3609 
3610 
3611 /*
3612  * Event handler
3613  */
3614 
3615 /** execution method of bound change event handler */
3616 static
3617 SCIP_DECL_EVENTEXEC(eventExecPseudoobj)
3618 { /*lint --e{715}*/
3619  SCIP_PROPDATA* propdata;
3620  SCIP_EVENTTYPE eventtype;
3621 
3622  propdata = (SCIP_PROPDATA*)eventdata;
3623  assert(propdata != NULL);
3624 
3625  assert(eventhdlr != NULL);
3626  assert(eventdata != NULL);
3627  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
3628  assert(event != NULL);
3629 
3630  eventtype = SCIPeventGetType(event);
3631 
3632  switch( eventtype )
3633  {
3636  /* if bound got relaxed we need to start up front for trial of bound tightening */
3637  propdata->firstnonfixed = 0;
3638  break;
3640  propdata->nnewvars++;
3641  break;
3642  default:
3643  assert(eventtype == SCIP_EVENTTYPE_GLBCHANGED || eventtype == SCIP_EVENTTYPE_GUBCHANGED);
3644 
3645  /* invalidate the maximum pseudo objective activity */
3646  propdata->maxpseudoobjact = SCIP_INVALID;
3647  propdata->maxpseudoobjactinf = 0;
3648  }
3649 
3650  return SCIP_OKAY;
3651 }
3652 
3653 
3654 /*
3655  * propagator specific interface methods
3656  */
3657 
3658 /** creates the pseudo objective function propagator and includes it in SCIP */
3660  SCIP* scip /**< SCIP data structure */
3661  )
3662 {
3663  SCIP_PROPDATA* propdata;
3664  SCIP_PROP* prop;
3666 
3667  /* create pseudoobj propagator data */
3668  SCIP_CALL( SCIPallocMemory(scip, &propdata) );
3669 
3670  /* reset propagator data structure */
3671  propdataReset(scip, propdata);
3672 
3673  propdata->eventhdlr = NULL;
3674  /* include event handler for gloabl bound change events and variable added event (in case of pricing) */
3675  SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &propdata->eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC,
3676  eventExecPseudoobj, NULL) );
3677 
3678  if( propdata->eventhdlr == NULL )
3679  {
3680  SCIPerrorMessage("event handler for pseudo objective propagator not found\n");
3681  return SCIP_PLUGINNOTFOUND;
3682  }
3683 
3684  /* include propagator */
3686  propExecPseudoobj,
3687  propdata) );
3688  assert(prop != NULL);
3689 
3690  /* set optional callbacks via setter functions */
3691  SCIP_CALL( SCIPsetPropCopy(scip, prop, propCopyPseudoobj) );
3692  SCIP_CALL( SCIPsetPropFree(scip, prop, propFreePseudoobj) );
3693  SCIP_CALL( SCIPsetPropInitsol(scip, prop, propInitsolPseudoobj) );
3694  SCIP_CALL( SCIPsetPropExitsol(scip, prop, propExitsolPseudoobj) );
3696  SCIP_CALL( SCIPsetPropResprop(scip, prop, propRespropPseudoobj) );
3697 
3698  /* add pseudoobj propagator parameters */
3699  SCIP_CALL( SCIPaddIntParam(scip,
3700  "propagating/" PROP_NAME "/minuseless",
3701  "minimal number of successive none binary variable propagator whithout a bound reduction before aborted",
3702  &propdata->minuseless, TRUE, DEFAULT_MINUSELESS, 0, INT_MAX, NULL, NULL) );
3703 
3705  "propagating/" PROP_NAME "/maxvarsfrac",
3706  "maximal fraction of none binary variables with non-zero objective without a bound reduction before aborted",
3707  &propdata->maxvarsfrac, TRUE, DEFAULT_MAXVARSFRAC, 0.0, 1.0, NULL, NULL) );
3708 
3710  "propagating/" PROP_NAME "/propfullinroot",
3711  "do we want to propagate all none binary variables if we are propagating the root node",
3712  &propdata->propfullinroot, TRUE, DEFAULT_PROPFULLINROOT, NULL, NULL) );
3713 
3715  "propagating/" PROP_NAME "/propcutoffbound",
3716  "propagate new cutoff bound directly globally",
3717  &propdata->propcutoffbound, TRUE, DEFAULT_PROPCUTOFFBOUND, NULL, NULL) );
3718 
3720  "propagating/" PROP_NAME "/force",
3721  "should the propagator be forced even if active pricer are present?",
3722  &propdata->force, TRUE, DEFAULT_FORCE, NULL, NULL) );
3723 
3724  SCIP_CALL( SCIPaddIntParam(scip,
3725  "propagating/" PROP_NAME "/maxnewvars",
3726  "number of variable added after the propgatore is reinitialized?",
3727  &propdata->maxnewvars, TRUE, DEFAULT_MAXNEWVARS, 0, INT_MAX, NULL, NULL) );
3728 
3730  "propagating/" PROP_NAME "/propuseimplics",
3731  "use implications to strengthen the propagation of binary variable (increasing the objective change)?",
3732  &propdata->propuseimplics, TRUE, DEFAULT_PROPUSEIMPLICS, NULL, NULL) );
3733 
3735  "propagating/" PROP_NAME "/respropuseimplics",
3736  "use implications to strengthen the resolve propagation of binary variable (increasing the objective change)?",
3737  &propdata->respropuseimplics, TRUE, DEFAULT_RESPROPUSEIMPLICS, NULL, NULL) );
3738 
3739  SCIP_CALL( SCIPaddIntParam(scip,
3740  "propagating/" PROP_NAME "/maximplvars",
3741  "maximum number of binary variables the implications are used if turned on (-1: unlimited)?",
3742  &propdata->maximplvars, TRUE, DEFAULT_MAXIMPLVARS, -1, INT_MAX, NULL, NULL) );
3743 
3744  return SCIP_OKAY;
3745 }
3746 
3747 /** propagates the cutoff bound for the given variables */
3749  SCIP* scip, /**< SCIP data structure */
3750  SCIP_PROP* prop, /**< propagator, or NULL */
3751  SCIP_VAR* var, /**< variables to propagate */
3752  SCIP_Real cutoffbound, /**< cutoff bound to use */
3753  SCIP_Real pseudoobjval, /**< pseudo objective value to use */
3754  SCIP_Bool* tightened /**< pointer to if the domain was tightened */
3755  )
3756 {
3757  SCIP_Real objval;
3758 
3759  objval = SCIPvarGetObj(var);
3760 
3761  SCIP_CALL( propagateCutoffboundVar(scip, prop, var, -1, objval, cutoffbound, pseudoobjval, TRUE, tightened) );
3762 
3763  return SCIP_OKAY;
3764 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:51
SCIP_VAR ** SCIPvarGetImplVars(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17352
SCIP_RETCODE SCIPsetPropExitsol(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPEXITSOL((*propexitsol)))
Definition: scip.c:7025
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41572
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
static SCIP_RETCODE adjustCutoffbound(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_VAR *var, int inferinfo, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_HASHTABLE *addedvars, SCIP_Real *cutoffbound)
static SCIP_RETCODE getMinactImplicObjchg(SCIP *scip, SCIP_VAR *var, SCIP_OBJIMPLICS *objimplics, SCIP_BDCHGIDX *bdchgidx, SCIP_BOUNDTYPE bound, SCIP_Bool local, SCIP_Real *objchg)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:41685
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:10698
#define SCIPallocMemory(scip, ptr)
Definition: scip.h:20526
SCIP_VAR ** SCIPcliqueGetVars(SCIP_CLIQUE *clique)
Definition: implics.c:3111
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16443
#define PROP_FREQ
SCIP_VAR ** objvars
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:41648
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:1567
#define PROP_PRIORITY
Pseudo objective propagator.
static SCIP_RETCODE propagateLowerbound(SCIP *scip, SCIP_PROP *prop, SCIP_RESULT *result)
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16623
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41920
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:10653
SCIP_CLIQUE ** SCIPvarGetCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17420
static SCIP_RETCODE propdataExit(SCIP *scip, SCIP_PROPDATA *propdata)
#define NULL
Definition: lpi_spx.cpp:130
static SCIP_RETCODE collectMinactVar(SCIP *scip, SCIP_VAR *var, SCIP_OBJIMPLICS **objimplics, SCIP_Bool useimplics, SCIP_HASHMAP *binobjvarmap, SCIP_Bool *collectedlbvars, SCIP_Bool *collectedubvars, int nbinobjvars, SCIP_VAR **contributors, SCIP_HASHTABLE *uselesscliques, SCIP_Bool *collect)
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17113
static SCIP_DECL_PROPINITSOL(propInitsolPseudoobj)
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17067
#define DEFAULT_MAXNEWVARS
void SCIPsortDownRealPtr(SCIP_Real *realarray, void **ptrarray, int len)
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
Definition: scip.c:24320
#define SCIPfreeMemoryArray(scip, ptr)
Definition: scip.h:20544
#define DEFAULT_PROPCUTOFFBOUND
static void updateMaxObjPseudoactivity(SCIP *scip, SCIP_PROPDATA *propdata)
#define SCIP_PROPTIMING_DURINGLPLOOP
Definition: type_timing.h:55
#define SCIPallocMemoryArray(scip, ptr, num)
Definition: scip.h:20528
#define FALSE
Definition: def.h:56
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2057
#define DEFAULT_MINUSELESS
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:17169
static SCIP_DECL_SORTPTRCOMP(objimplicsComp)
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:7778
#define TRUE
Definition: def.h:55
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
static SCIP_RETCODE addConflictBinvar(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_OBJIMPLICS *objimplics, SCIP_HASHTABLE *addedvars, SCIP_Bool respropuseimplics, SCIP_Real *reqpseudoobjval)
SCIP_RETCODE SCIPsetPropCopy(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPCOPY((*propcopy)))
Definition: scip.c:6945
#define SCIP_CALL(x)
Definition: def.h:266
static SCIP_RETCODE getMaxactObjchg(SCIP *scip, SCIP_VAR *var, SCIP_BOUNDTYPE bound, SCIP_Bool useimplics, SCIP_Real *objchg)
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:53
int SCIPgetNActivePricers(SCIP *scip)
Definition: scip.c:5017
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
Definition: scip.c:38561
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:20556
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15737
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_RETCODE SCIPinferVarLbProp(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_PROP *inferprop, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:20841
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:16905
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2116
SCIP_RETCODE SCIPcutoffNode(SCIP *scip, SCIP_NODE *node)
Definition: scip.c:37116
int SCIPgetNContVars(SCIP *scip)
Definition: scip.c:10878
static SCIP_RETCODE propagateCutoffbound(SCIP *scip, SCIP_PROP *prop, SCIP_RESULT *result)
#define PROP_DELAY
static void resetContributors(SCIP_HASHMAP *binobjvarmap, SCIP_Bool *collectedvars, SCIP_VAR **contributors, int ncontributors)
#define DEFAULT_FORCE
static SCIP_Real getMaxObjPseudoactivityResidual(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_VAR *var)
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:20554
#define EVENTHDLR_DESC
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11206
SCIP_RETCODE SCIPincludePropPseudoobj(SCIP *scip)
SCIP_Real SCIPgetLowerbound(SCIP *scip)
Definition: scip.c:38393
SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition: misc.c:1480
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3547
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2159
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3573
#define SCIP_EVENTTYPE_LBRELAXED
Definition: type_event.h:56
#define PROP_PRESOLTIMING
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16634
static SCIP_RETCODE addConflictBounds(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Real *reqpseudoobjval)
SCIP_RETCODE SCIPanalyzeConflict(SCIP *scip, int validdepth, SCIP_Bool *success)
Definition: scip.c:24689
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:36622
static SCIP_RETCODE collectMinactObjchg(SCIP *scip, SCIP_VAR *var, SCIP_BOUNDTYPE bound, SCIP_HASHMAP *binobjvarmap, SCIP_Bool *collectedvars, int nbinobjvars, SCIP_VAR **contributors, SCIP_HASHTABLE *uselesscliques, int *ncontributors, SCIP_Real *objchg)
#define SCIPfreeMemory(scip, ptr)
Definition: scip.h:20542
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip)
Definition: scip.c:24342
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41585
static SCIP_RETCODE objimplicsDelPos(SCIP *scip, SCIP_OBJIMPLICS *objimplics, int pos)
SCIP_NODE * SCIPgetRootNode(SCIP *scip)
Definition: scip.c:36798
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:41709
SCIP_PROPDATA * SCIPpropGetData(SCIP_PROP *prop)
Definition: prop.c:735
#define SCIPerrorMessage
Definition: pub_message.h:45
static SCIP_RETCODE propagateCutoffboundBinvar(SCIP *scip, SCIP_PROP *prop, SCIP_VAR *var, int pos, SCIP_Real cutoffbound, SCIP_Real pseudoobjval, SCIP_Bool *tightened, SCIP_Bool *cutoff, SCIP_Bool local)
#define SCIPdebugPrintf
Definition: pub_message.h:80
static SCIP_RETCODE getMaxactImplicObjchg(SCIP *scip, SCIP_VAR *var, SCIP_BOUNDTYPE bound, SCIP_Real *objchg)
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip.h:20574
SCIP_Real maxobjchg
void SCIPsortDownPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
int SCIPcalcHashtableSize(int minsize)
Definition: misc.c:1157
SCIP_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15859
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41598
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:41353
static SCIP_RETCODE collectMinactImplicVars(SCIP *scip, SCIP_VAR *var, SCIP_BOUNDTYPE bound, SCIP_HASHMAP *binobjvarmap, SCIP_Bool *collectedvars, int nbinobjvars, SCIP_VAR **contributors, SCIP_HASHTABLE *uselesscliques, int *ncontributors, SCIP_Real *objchg)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41907
#define MAX_CLIQUELENGTH
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:146
static SCIP_DECL_PROPPRESOL(propPresolPseudoobj)
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2075
#define PROP_DESC
#define PROP_PRESOL_MAXROUNDS
void SCIPsortDownPtrPtr(void **ptrarray1, void **ptrarray2, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
SCIP_BOUNDTYPE * SCIPvarGetImplTypes(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17367
#define SCIP_EVENTTYPE_UBRELAXED
Definition: type_event.h:58
#define DEFAULT_PROPUSEIMPLICS
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3204
static SCIP_RETCODE resolvePropagation(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_Real cutoffbound, SCIP_VAR *infervar, int inferinfo, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx)
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:41637
SCIP_Real SCIPgetGlobalPseudoObjval(SCIP *scip)
Definition: scip.c:26543
static SCIP_RETCODE dropObjEvent(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_EVENTHDLR *eventhdlr, SCIP_VAR *var)
SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition: var.c:10742
static SCIP_DECL_PROPCOPY(propCopyPseudoobj)
void SCIPhashtableRemoveAll(SCIP_HASHTABLE *hashtable)
Definition: misc.c:1753
SCIP_RETCODE SCIPsetPropPresol(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPPRESOL((*proppresol)), int presolpriority, int presolmaxrounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip.c:7073
static SCIP_RETCODE objimplicsFree(SCIP *scip, SCIP_OBJIMPLICS **objimplics)
SCIP_RETCODE SCIPinferVarUbProp(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_PROP *inferprop, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:20944
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip.c:32131
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41946
void SCIPpropSetData(SCIP_PROP *prop, SCIP_PROPDATA *propdata)
Definition: prop.c:745
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:16884
static SCIP_DECL_PROPFREE(propFreePseudoobj)
SCIP_RETCODE SCIPtightenVarLbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:21150
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41611
static SCIP_RETCODE propagateCutoffboundGlobally(SCIP *scip, SCIP_PROP *prop, int *nchgbds, SCIP_Bool *cutoff)
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:16850
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17123
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip.c:997
unsigned int SCIP_EVENTTYPE
Definition: type_event.h:125
SCIP_RETCODE SCIPsetPropResprop(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPRESPROP((*propresprop)))
Definition: scip.c:7106
static SCIP_DECL_PROPEXITSOL(propExitsolPseudoobj)
#define SCIP_Bool
Definition: def.h:53
SCIP_RETCODE SCIPsetPropFree(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPFREE((*propfree)))
Definition: scip.c:6961
static SCIP_DECL_PROPRESPROP(propRespropPseudoobj)
static SCIP_RETCODE getMinactObjchg(SCIP *scip, SCIP_VAR *var, SCIP_OBJIMPLICS *objimplics, SCIP_BDCHGIDX *bdchgidx, SCIP_BOUNDTYPE bound, SCIP_Bool local, SCIP_Real *objchg)
static SCIP_Real getMaxObjPseudoactivityResidualValue(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_Real contrib)
#define DEFAULT_PROPFULLINROOT
static void calcMaxObjPseudoactivity(SCIP *scip, SCIP_PROPDATA *propdata)
SCIP_RETCODE SCIPpropagateCutoffboundVar(SCIP *scip, SCIP_PROP *prop, SCIP_VAR *var, SCIP_Real cutoffbound, SCIP_Real pseudoobjval, SCIP_Bool *tightened)
SCIP_RETCODE SCIPincludePropBasic(SCIP *scip, SCIP_PROP **propptr, const char *name, const char *desc, int priority, int freq, SCIP_Bool delay, SCIP_PROPTIMING timingmask, SCIP_DECL_PROPEXEC((*propexec)), SCIP_PROPDATA *propdata)
Definition: scip.c:6908
static SCIP_RETCODE propdataInit(SCIP *scip, SCIP_PROPDATA *propdata)
static SCIP_RETCODE collectMaxactVar(SCIP *scip, SCIP_VAR *var, SCIP_Bool useimplics, SCIP_Real *objchg, SCIP_Bool *isnotzero)
static SCIP_RETCODE objimplicsCreate(SCIP *scip, SCIP_OBJIMPLICS **objimplics, SCIP_VAR **objvars, SCIP_HASHMAP *binobjvarmap, SCIP_Bool *collectedlbvars, SCIP_Bool *collectedubvars, SCIP_Real maxlbobjchg, SCIP_Real maxubobjchg, int nlbimpls, int nubimpls)
int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17335
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip.c:801
static SCIP_RETCODE propagateCutoffboundBinvars(SCIP *scip, SCIP_PROP *prop, SCIP_Real cutoffbound, SCIP_Real pseudoobjval, int *nfixedvars, SCIP_Bool *cutoff)
SCIP_Real SCIPgetPseudoObjval(SCIP *scip)
Definition: scip.c:26568
#define MAX(x, y)
Definition: tclique_def.h:75
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
Definition: scip.c:24369
static SCIP_Real getVarObjchg(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BOUNDTYPE bound)
SCIP_Bool * SCIPcliqueGetValues(SCIP_CLIQUE *clique)
Definition: implics.c:3123
SCIP_Bool SCIPallowObjProp(SCIP *scip)
Definition: scip.c:23093
static SCIP_DECL_HASHKEYEQ(cliqueIsHashkeyEq)
int SCIPgetNCliques(SCIP *scip)
Definition: scip.c:22108
SCIP_BOUNDTYPE SCIPvarGetWorstBoundType(SCIP_VAR *var)
Definition: var.c:17182
static SCIP_RETCODE getConflictImplics(SCIP *scip, SCIP_VAR **vars, int start, int end, SCIP_BDCHGIDX *bdchgidx, SCIP_HASHTABLE *addedvars, SCIP_Real *reqpseudoobjval, SCIP_Bool *foundimplics)
static void checkImplicsApplied(SCIP *scip, SCIP_VAR *var)
static SCIP_RETCODE catchObjEvent(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_EVENTHDLR *eventhdlr, SCIP_VAR *var)
SCIP_RETCODE SCIPsetPropInitsol(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPINITSOL((*propinitsol)))
Definition: scip.c:7009
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:38140
#define DEFAULT_RESPROPUSEIMPLICS
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41624
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:1510
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:36668
static SCIP_Real collectMinactImplicVar(SCIP *scip, SCIP_VAR *var, SCIP_HASHMAP *binobjvarmap, SCIP_Bool *collectedvars, int nbinobjvars, SCIP_VAR **contributors, int *ncontributors)
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20585
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17057
SCIP_RETCODE SCIPdropEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:36588
#define DEFAULT_MAXVARSFRAC
#define PROP_PRESOL_PRIORITY
#define EVENTHDLR_NAME
#define REALABS(x)
Definition: def.h:151
#define SCIPfreeMemoryArrayNull(scip, ptr)
Definition: scip.h:20545
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:278
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41933
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16750
static SCIP_DECL_HASHKEYVAL(cliqueGetHashkeyVal)
static void propdataReset(SCIP *scip, SCIP_PROPDATA *propdata)
SCIP_RETCODE SCIPtightenVarUbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:21260
#define SCIP_Real
Definition: def.h:127
struct SCIP_PropData SCIP_PROPDATA
Definition: type_prop.h:38
int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17409
#define MIN(x, y)
Definition: memory.c:67
static SCIP_RETCODE propagateLowerboundVar(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_VAR *var, SCIP_Real lowerbound, SCIP_Bool *infeasible, SCIP_Bool *tightened)
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41959
static SCIP_DECL_HASHGETKEY(cliqueGetHashkey)
#define SCIP_INVALID
Definition: def.h:147
static SCIP_RETCODE propagateCutoffboundVar(SCIP *scip, SCIP_PROP *prop, SCIP_VAR *var, int inferinfo, SCIP_Real objchg, SCIP_Real cutoffbound, SCIP_Real pseudoobjval, SCIP_Bool local, SCIP_Bool *tightened)
SCIP_Real SCIPfeastol(SCIP *scip)
Definition: scip.c:41146
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:917
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:20571
#define PROP_NAME
SCIP_Bool SCIPhashtableExists(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:1692
static SCIP_DECL_EVENTEXEC(eventExecPseudoobj)
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:20597
static void checkGlbfirstnonfixed(SCIP *scip, SCIP_PROPDATA *propdata)
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16730
int SCIPgetNObjVars(SCIP *scip)
Definition: scip.c:10926
int SCIPcliqueGetNVars(SCIP_CLIQUE *clique)
Definition: implics.c:3101
SCIP_Real * SCIPvarGetImplBounds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17381
static SCIP_RETCODE dropVarEvents(SCIP *scip, SCIP_PROPDATA *propdata)
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
Definition: scip.c:24436
int SCIPgetCutoffdepth(SCIP *scip)
Definition: scip.c:37155
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:2094
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:54
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:41697
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3629
static SCIP_DECL_PROPEXEC(propExecPseudoobj)
#define SCIP_EVENTTYPE_VARADDED
Definition: type_event.h:46
#define DEFAULT_MAXIMPLVARS
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3149
const char * SCIPpropGetName(SCIP_PROP *prop)
Definition: prop.c:887
static SCIP_Real getMaxObjPseudoactivity(SCIP *scip, SCIP_PROPDATA *propdata)
static SCIP_RETCODE propagateLowerboundBinvar(SCIP *scip, SCIP_VAR *var, SCIP_Real lowerbound, SCIP_Real maxpseudoobjact, SCIP_Bool useimplics, SCIP_Bool *infeasible, SCIP_Bool *tightened)
SCIP_RETCODE SCIPcatchEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:36554
int SCIPcliqueGetId(SCIP_CLIQUE *clique)
Definition: implics.c:3133
#define PROP_TIMING
#define SCIP_EVENTTYPE_BOUNDRELAXED
Definition: type_event.h:98